summaryrefslogtreecommitdiff
path: root/libnm-core
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2015-01-22 00:29:39 +0100
committerMichael Biebl <biebl@debian.org>2015-01-22 00:29:39 +0100
commit2c032d8f1c6292c1338a615e6ec40252889ba85c (patch)
tree1f77182220b2b0264288ba4a476ab47e5bc48716 /libnm-core
parent33491bc4279481db8ae47213e34a6d695a0e8830 (diff)
Imported Upstream version 1.0.0upstream/1.0.0
Diffstat (limited to 'libnm-core')
-rw-r--r--libnm-core/Makefile.am48
-rw-r--r--libnm-core/Makefile.in1350
-rw-r--r--libnm-core/Makefile.libnm-core91
-rw-r--r--libnm-core/crypto.c816
-rw-r--r--libnm-core/crypto.h133
-rw-r--r--libnm-core/crypto_gnutls.c454
-rw-r--r--libnm-core/crypto_nss.c526
-rw-r--r--libnm-core/nm-connection-private.h35
-rw-r--r--libnm-core/nm-connection.c2077
-rw-r--r--libnm-core/nm-connection.h219
-rw-r--r--libnm-core/nm-core-enum-types.c1031
-rw-r--r--libnm-core/nm-core-enum-types.h97
-rw-r--r--libnm-core/nm-core-internal.h135
-rw-r--r--libnm-core/nm-core-types.h60
-rw-r--r--libnm-core/nm-dbus-interface.h611
-rw-r--r--libnm-core/nm-errors.c90
-rw-r--r--libnm-core/nm-errors.h319
-rw-r--r--libnm-core/nm-property-compare.c122
-rw-r--r--libnm-core/nm-property-compare.h30
-rw-r--r--libnm-core/nm-setting-8021x.c3864
-rw-r--r--libnm-core/nm-setting-8021x.h278
-rw-r--r--libnm-core/nm-setting-adsl.c448
-rw-r--r--libnm-core/nm-setting-adsl.h81
-rw-r--r--libnm-core/nm-setting-bluetooth.c285
-rw-r--r--libnm-core/nm-setting-bluetooth.h81
-rw-r--r--libnm-core/nm-setting-bond.c760
-rw-r--r--libnm-core/nm-setting-bond.h98
-rw-r--r--libnm-core/nm-setting-bridge-port.c321
-rw-r--r--libnm-core/nm-setting-bridge-port.h69
-rw-r--r--libnm-core/nm-setting-bridge.c540
-rw-r--r--libnm-core/nm-setting-bridge.h81
-rw-r--r--libnm-core/nm-setting-cdma.c336
-rw-r--r--libnm-core/nm-setting-cdma.h69
-rw-r--r--libnm-core/nm-setting-connection.c1569
-rw-r--r--libnm-core/nm-setting-connection.h125
-rw-r--r--libnm-core/nm-setting-dcb.c1280
-rw-r--r--libnm-core/nm-setting-dcb.h164
-rw-r--r--libnm-core/nm-setting-generic.c73
-rw-r--r--libnm-core/nm-setting-generic.h59
-rw-r--r--libnm-core/nm-setting-gsm.c616
-rw-r--r--libnm-core/nm-setting-gsm.h80
-rw-r--r--libnm-core/nm-setting-infiniband.c522
-rw-r--r--libnm-core/nm-setting-infiniband.h72
-rw-r--r--libnm-core/nm-setting-ip-config.c2363
-rw-r--r--libnm-core/nm-setting-ip-config.h221
-rw-r--r--libnm-core/nm-setting-ip4-config.c695
-rw-r--r--libnm-core/nm-setting-ip4-config.h108
-rw-r--r--libnm-core/nm-setting-ip6-config.c610
-rw-r--r--libnm-core/nm-setting-ip6-config.h136
-rw-r--r--libnm-core/nm-setting-olpc-mesh.c268
-rw-r--r--libnm-core/nm-setting-olpc-mesh.h67
-rw-r--r--libnm-core/nm-setting-ppp.c803
-rw-r--r--libnm-core/nm-setting-ppp.h97
-rw-r--r--libnm-core/nm-setting-pppoe.c322
-rw-r--r--libnm-core/nm-setting-pppoe.h69
-rw-r--r--libnm-core/nm-setting-private.h158
-rw-r--r--libnm-core/nm-setting-serial.c351
-rw-r--r--libnm-core/nm-setting-serial.h85
-rw-r--r--libnm-core/nm-setting-team-port.c192
-rw-r--r--libnm-core/nm-setting-team-port.h62
-rw-r--r--libnm-core/nm-setting-team.c186
-rw-r--r--libnm-core/nm-setting-team.h62
-rw-r--r--libnm-core/nm-setting-vlan.c822
-rw-r--r--libnm-core/nm-setting-vlan.h134
-rw-r--r--libnm-core/nm-setting-vpn.c913
-rw-r--r--libnm-core/nm-setting-vpn.h102
-rw-r--r--libnm-core/nm-setting-wimax.c245
-rw-r--r--libnm-core/nm-setting-wimax.h64
-rw-r--r--libnm-core/nm-setting-wired.c1103
-rw-r--r--libnm-core/nm-setting-wired.h109
-rw-r--r--libnm-core/nm-setting-wireless-security.c1704
-rw-r--r--libnm-core/nm-setting-wireless-security.h147
-rw-r--r--libnm-core/nm-setting-wireless.c1335
-rw-r--r--libnm-core/nm-setting-wireless.h138
-rw-r--r--libnm-core/nm-setting.c1818
-rw-r--r--libnm-core/nm-setting.h282
-rw-r--r--libnm-core/nm-simple-connection.c123
-rw-r--r--libnm-core/nm-simple-connection.h61
-rw-r--r--libnm-core/nm-utils-private.h51
-rw-r--r--libnm-core/nm-utils.c3215
-rw-r--r--libnm-core/nm-utils.h190
-rw-r--r--libnm-core/nm-version.h123
-rw-r--r--libnm-core/nm-version.h.in123
-rw-r--r--libnm-core/nm-vpn-dbus-interface.h307
-rw-r--r--libnm-core/tests/Makefile.am56
-rw-r--r--libnm-core/tests/Makefile.in959
-rw-r--r--libnm-core/tests/certs/ca-no-ending-newline.pem15
-rw-r--r--libnm-core/tests/certs/pkcs8-decrypted.derbin0 -> 1194 bytes
-rw-r--r--libnm-core/tests/certs/pkcs8-enc-key.pem29
-rw-r--r--libnm-core/tests/certs/pkcs8-noenc-key.pem28
-rw-r--r--libnm-core/tests/certs/test-aes-key.pem30
-rw-r--r--libnm-core/tests/certs/test-cert.p12bin0 -> 4092 bytes
-rw-r--r--libnm-core/tests/certs/test-key-only-decrypted.derbin0 -> 1192 bytes
-rw-r--r--libnm-core/tests/certs/test-key-only-decrypted.pem27
-rw-r--r--libnm-core/tests/certs/test-key-only.pem92
-rw-r--r--libnm-core/tests/certs/test2-cert.p12bin0 -> 4136 bytes
-rw-r--r--libnm-core/tests/certs/test2_ca_cert.pem27
-rw-r--r--libnm-core/tests/certs/test2_key_and_cert.pem119
-rw-r--r--libnm-core/tests/certs/test_ca_cert.derbin0 -> 1162 bytes
-rw-r--r--libnm-core/tests/certs/test_ca_cert.pem27
-rw-r--r--libnm-core/tests/certs/test_key_and_cert.pem119
-rw-r--r--libnm-core/tests/test-compare.c248
-rw-r--r--libnm-core/tests/test-crypto.c501
-rw-r--r--libnm-core/tests/test-general.c3961
-rw-r--r--libnm-core/tests/test-secrets.c766
-rw-r--r--libnm-core/tests/test-setting-8021x.c458
-rw-r--r--libnm-core/tests/test-setting-dcb.c326
-rw-r--r--libnm-core/tests/test-settings-defaults.c133
108 files changed, 48000 insertions, 0 deletions
diff --git a/libnm-core/Makefile.am b/libnm-core/Makefile.am
new file mode 100644
index 000000000..8fab84bcb
--- /dev/null
+++ b/libnm-core/Makefile.am
@@ -0,0 +1,48 @@
+include $(GLIB_MAKEFILE)
+
+SUBDIRS = . tests
+
+AM_CPPFLAGS = \
+ -I${top_srcdir}/include \
+ -DG_LOG_DOMAIN=\""libnm"\" \
+ -DLOCALEDIR=\"$(datadir)/locale\" \
+ -DNETWORKMANAGER_COMPILATION \
+ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
+ $(GLIB_CFLAGS)
+
+noinst_LTLIBRARIES = libnm-core.la
+
+# header/source defines are in Makefile.libnm-core, so they can be shared
+# with libnm/Makefile.am
+include Makefile.libnm-core
+
+libnmincludedir = $(includedir)/libnm
+
+libnminclude_HEADERS = $(libnm_core_headers)
+libnm_core_la_SOURCES = \
+ $(libnm_core_sources) \
+ $(libnm_core_private_headers)
+
+GLIB_GENERATED = nm-core-enum-types.h nm-core-enum-types.c
+nm_core_enum_types_sources = $(notdir $(libnminclude_HEADERS))
+GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM
+GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM
+
+libnm_core_la_LIBADD = \
+ $(GLIB_LIBS) \
+ $(UUID_LIBS)
+
+if WITH_GNUTLS
+AM_CPPFLAGS += $(LIBGCRYPT_CFLAGS) $(GNUTLS_CFLAGS)
+libnm_core_la_SOURCES += crypto_gnutls.c
+libnm_core_la_LIBADD += $(LIBGCRYPT_LIBS) $(GNUTLS_LIBS)
+endif
+
+if WITH_NSS
+AM_CPPFLAGS += $(NSS_CFLAGS)
+libnm_core_la_SOURCES += crypto_nss.c
+libnm_core_la_LIBADD += $(NSS_LIBS)
+endif
+
+BUILT_SOURCES = $(GLIB_GENERATED)
+CLEANFILES = $(BUILT_SOURCES)
diff --git a/libnm-core/Makefile.in b/libnm-core/Makefile.in
new file mode 100644
index 000000000..8ec1414e3
--- /dev/null
+++ b/libnm-core/Makefile.in
@@ -0,0 +1,1350 @@
+# Makefile.in generated by automake 1.13.4 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# In order for this to work correctly from both libnm-core/ and libnm/,
+# we have to specify full pathnames. (We can't just use $(addprefix) from
+# libnm/, because that's incompatible with the Makefile.introspection rules.)
+
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+DIST_COMMON = $(srcdir)/Makefile.libnm-core $(srcdir)/Makefile.in \
+ $(srcdir)/Makefile.am $(srcdir)/nm-version.h.in \
+ $(top_srcdir)/build-aux/depcomp $(libnminclude_HEADERS)
+@WITH_GNUTLS_TRUE@am__append_1 = $(LIBGCRYPT_CFLAGS) $(GNUTLS_CFLAGS)
+@WITH_GNUTLS_TRUE@am__append_2 = crypto_gnutls.c
+@WITH_GNUTLS_TRUE@am__append_3 = $(LIBGCRYPT_LIBS) $(GNUTLS_LIBS)
+@WITH_NSS_TRUE@am__append_4 = $(NSS_CFLAGS)
+@WITH_NSS_TRUE@am__append_5 = crypto_nss.c
+@WITH_NSS_TRUE@am__append_6 = $(NSS_LIBS)
+subdir = libnm-core
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \
+ $(top_srcdir)/m4/compiler_warnings.m4 \
+ $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/gnome-code-coverage.m4 \
+ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \
+ $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/lib-ld.m4 \
+ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
+ $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = nm-version.h
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+@WITH_GNUTLS_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) \
+@WITH_GNUTLS_TRUE@ $(am__DEPENDENCIES_1)
+@WITH_NSS_TRUE@am__DEPENDENCIES_3 = $(am__DEPENDENCIES_1)
+libnm_core_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \
+ $(am__DEPENDENCIES_3)
+am__libnm_core_la_SOURCES_DIST = $(core_build)/nm-core-enum-types.c \
+ $(core)/crypto.c $(core)/nm-connection.c $(core)/nm-errors.c \
+ $(core)/nm-property-compare.c $(core)/nm-setting-8021x.c \
+ $(core)/nm-setting-adsl.c $(core)/nm-setting-bluetooth.c \
+ $(core)/nm-setting-bond.c $(core)/nm-setting-bridge-port.c \
+ $(core)/nm-setting-bridge.c $(core)/nm-setting-cdma.c \
+ $(core)/nm-setting-connection.c $(core)/nm-setting-dcb.c \
+ $(core)/nm-setting-generic.c $(core)/nm-setting-gsm.c \
+ $(core)/nm-setting-infiniband.c $(core)/nm-setting-ip-config.c \
+ $(core)/nm-setting-ip4-config.c \
+ $(core)/nm-setting-ip6-config.c $(core)/nm-setting-olpc-mesh.c \
+ $(core)/nm-setting-ppp.c $(core)/nm-setting-pppoe.c \
+ $(core)/nm-setting-serial.c $(core)/nm-setting-team-port.c \
+ $(core)/nm-setting-team.c $(core)/nm-setting-vlan.c \
+ $(core)/nm-setting-vpn.c $(core)/nm-setting-wimax.c \
+ $(core)/nm-setting-wired.c \
+ $(core)/nm-setting-wireless-security.c \
+ $(core)/nm-setting-wireless.c $(core)/nm-setting.c \
+ $(core)/nm-simple-connection.c $(core)/nm-utils.c \
+ $(core)/crypto.h $(core)/nm-connection-private.h \
+ $(core)/nm-core-internal.h $(core)/nm-property-compare.h \
+ $(core)/nm-setting-private.h $(core)/nm-utils-private.h \
+ crypto_gnutls.c crypto_nss.c
+am__objects_1 = nm-core-enum-types.lo crypto.lo nm-connection.lo \
+ nm-errors.lo nm-property-compare.lo nm-setting-8021x.lo \
+ nm-setting-adsl.lo nm-setting-bluetooth.lo nm-setting-bond.lo \
+ nm-setting-bridge-port.lo nm-setting-bridge.lo \
+ nm-setting-cdma.lo nm-setting-connection.lo nm-setting-dcb.lo \
+ nm-setting-generic.lo nm-setting-gsm.lo \
+ nm-setting-infiniband.lo nm-setting-ip-config.lo \
+ nm-setting-ip4-config.lo nm-setting-ip6-config.lo \
+ nm-setting-olpc-mesh.lo nm-setting-ppp.lo nm-setting-pppoe.lo \
+ nm-setting-serial.lo nm-setting-team-port.lo \
+ nm-setting-team.lo nm-setting-vlan.lo nm-setting-vpn.lo \
+ nm-setting-wimax.lo nm-setting-wired.lo \
+ nm-setting-wireless-security.lo nm-setting-wireless.lo \
+ nm-setting.lo nm-simple-connection.lo nm-utils.lo
+am__objects_2 =
+@WITH_GNUTLS_TRUE@am__objects_3 = crypto_gnutls.lo
+@WITH_NSS_TRUE@am__objects_4 = crypto_nss.lo
+am_libnm_core_la_OBJECTS = $(am__objects_1) $(am__objects_2) \
+ $(am__objects_3) $(am__objects_4)
+libnm_core_la_OBJECTS = $(am_libnm_core_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libnm_core_la_SOURCES)
+DIST_SOURCES = $(am__libnm_core_la_SOURCES_DIST)
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+ ctags-recursive dvi-recursive html-recursive info-recursive \
+ install-data-recursive install-dvi-recursive \
+ install-exec-recursive install-html-recursive \
+ install-info-recursive install-pdf-recursive \
+ install-ps-recursive install-recursive installcheck-recursive \
+ installdirs-recursive pdf-recursive ps-recursive \
+ tags-recursive uninstall-recursive
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(libnmincludedir)"
+HEADERS = $(libnminclude_HEADERS)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+ $(RECURSIVE_TARGETS) \
+ $(RECURSIVE_CLEAN_TARGETS) \
+ $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+ distdir
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BLUEZ5_CFLAGS = @BLUEZ5_CFLAGS@
+BLUEZ5_LIBS = @BLUEZ5_LIBS@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CKDB_PATH = @CKDB_PATH@
+CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@
+CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
+CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@
+DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@
+DBUS_LIBS = @DBUS_LIBS@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DHCLIENT_PATH = @DHCLIENT_PATH@
+DHCPCD_PATH = @DHCPCD_PATH@
+DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@
+DLLTOOL = @DLLTOOL@
+DNSMASQ_PATH = @DNSMASQ_PATH@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GENHTML = @GENHTML@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MAKEFILE = @GLIB_MAKEFILE@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUDEV_CFLAGS = @GUDEV_CFLAGS@
+GUDEV_LIBS = @GUDEV_LIBS@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
+INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
+INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
+INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+IPTABLES_PATH = @IPTABLES_PATH@
+IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@
+IWMX_SDK_LIBS = @IWMX_SDK_LIBS@
+KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBDL = @LIBDL@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBM = @LIBM@
+LIBNDP_CFLAGS = @LIBNDP_CFLAGS@
+LIBNDP_LIBS = @LIBNDP_LIBS@
+LIBNL_CFLAGS = @LIBNL_CFLAGS@
+LIBNL_LIBS = @LIBNL_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
+LIBSOUP_LIBS = @LIBSOUP_LIBS@
+LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@
+LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MM_GLIB_CFLAGS = @MM_GLIB_CFLAGS@
+MM_GLIB_LIBS = @MM_GLIB_LIBS@
+MOC = @MOC@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NEWT_CFLAGS = @NEWT_CFLAGS@
+NEWT_LIBS = @NEWT_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@
+NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
+NM_MICRO_VERSION = @NM_MICRO_VERSION@
+NM_MINOR_VERSION = @NM_MINOR_VERSION@
+NM_MODIFY_SYSTEM_POLICY = @NM_MODIFY_SYSTEM_POLICY@
+NM_VERSION = @NM_VERSION@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PPPD_PATH = @PPPD_PATH@
+PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
+PPPOE_PATH = @PPPOE_PATH@
+QT_CFLAGS = @QT_CFLAGS@
+QT_LIBS = @QT_LIBS@
+RANLIB = @RANLIB@
+READLINE_LIBS = @READLINE_LIBS@
+SED = @SED@
+SELINUX_CFLAGS = @SELINUX_CFLAGS@
+SELINUX_LIBS = @SELINUX_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@
+SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@
+SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@
+SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@
+SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@
+SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@
+SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
+UDEV_DIR = @UDEV_DIR@
+USE_NLS = @USE_NLS@
+UUID_CFLAGS = @UUID_CFLAGS@
+UUID_LIBS = @UUID_LIBS@
+VALGRIND_RULES = @VALGRIND_RULES@
+VAPIGEN = @VAPIGEN@
+VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@
+VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+intltool__v_merge_options_ = @intltool__v_merge_options_@
+intltool__v_merge_options_0 = @intltool__v_merge_options_0@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nmbinary = @nmbinary@
+nmconfdir = @nmconfdir@
+nmdatadir = @nmdatadir@
+nmrundir = @nmrundir@
+nmstatedir = @nmstatedir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+systemdsystemunitdir = @systemdsystemunitdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+with_dhclient = @with_dhclient@
+with_dhcpcd = @with_dhcpcd@
+with_netconfig = @with_netconfig@
+with_resolvconf = @with_resolvconf@
+with_valgrind = @with_valgrind@
+SUBDIRS = . tests
+AM_CPPFLAGS = -I${top_srcdir}/include -DG_LOG_DOMAIN=\""libnm"\" \
+ -DLOCALEDIR=\"$(datadir)/locale\" -DNETWORKMANAGER_COMPILATION \
+ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE $(GLIB_CFLAGS) \
+ $(am__append_1) $(am__append_4)
+noinst_LTLIBRARIES = libnm-core.la
+core = $(top_srcdir)/libnm-core
+core_build = $(top_builddir)/libnm-core
+libnm_core_headers = \
+ $(core_build)/nm-core-enum-types.h \
+ $(core_build)/nm-version.h \
+ $(core)/nm-connection.h \
+ $(core)/nm-core-types.h \
+ $(core)/nm-dbus-interface.h \
+ $(core)/nm-errors.h \
+ $(core)/nm-setting-8021x.h \
+ $(core)/nm-setting-adsl.h \
+ $(core)/nm-setting-bluetooth.h \
+ $(core)/nm-setting-bond.h \
+ $(core)/nm-setting-bridge-port.h \
+ $(core)/nm-setting-bridge.h \
+ $(core)/nm-setting-cdma.h \
+ $(core)/nm-setting-connection.h \
+ $(core)/nm-setting-dcb.h \
+ $(core)/nm-setting-generic.h \
+ $(core)/nm-setting-gsm.h \
+ $(core)/nm-setting-infiniband.h \
+ $(core)/nm-setting-ip-config.h \
+ $(core)/nm-setting-ip4-config.h \
+ $(core)/nm-setting-ip6-config.h \
+ $(core)/nm-setting-olpc-mesh.h \
+ $(core)/nm-setting-ppp.h \
+ $(core)/nm-setting-pppoe.h \
+ $(core)/nm-setting-serial.h \
+ $(core)/nm-setting-team-port.h \
+ $(core)/nm-setting-team.h \
+ $(core)/nm-setting-vlan.h \
+ $(core)/nm-setting-vpn.h \
+ $(core)/nm-setting-wimax.h \
+ $(core)/nm-setting-wired.h \
+ $(core)/nm-setting-wireless-security.h \
+ $(core)/nm-setting-wireless.h \
+ $(core)/nm-setting.h \
+ $(core)/nm-simple-connection.h \
+ $(core)/nm-utils.h \
+ $(core)/nm-vpn-dbus-interface.h
+
+libnm_core_private_headers = \
+ $(core)/crypto.h \
+ $(core)/nm-connection-private.h \
+ $(core)/nm-core-internal.h \
+ $(core)/nm-property-compare.h \
+ $(core)/nm-setting-private.h \
+ $(core)/nm-utils-private.h
+
+libnm_core_sources = \
+ $(core_build)/nm-core-enum-types.c \
+ $(core)/crypto.c \
+ $(core)/nm-connection.c \
+ $(core)/nm-errors.c \
+ $(core)/nm-property-compare.c \
+ $(core)/nm-setting-8021x.c \
+ $(core)/nm-setting-adsl.c \
+ $(core)/nm-setting-bluetooth.c \
+ $(core)/nm-setting-bond.c \
+ $(core)/nm-setting-bridge-port.c \
+ $(core)/nm-setting-bridge.c \
+ $(core)/nm-setting-cdma.c \
+ $(core)/nm-setting-connection.c \
+ $(core)/nm-setting-dcb.c \
+ $(core)/nm-setting-generic.c \
+ $(core)/nm-setting-gsm.c \
+ $(core)/nm-setting-infiniband.c \
+ $(core)/nm-setting-ip-config.c \
+ $(core)/nm-setting-ip4-config.c \
+ $(core)/nm-setting-ip6-config.c \
+ $(core)/nm-setting-olpc-mesh.c \
+ $(core)/nm-setting-ppp.c \
+ $(core)/nm-setting-pppoe.c \
+ $(core)/nm-setting-serial.c \
+ $(core)/nm-setting-team-port.c \
+ $(core)/nm-setting-team.c \
+ $(core)/nm-setting-vlan.c \
+ $(core)/nm-setting-vpn.c \
+ $(core)/nm-setting-wimax.c \
+ $(core)/nm-setting-wired.c \
+ $(core)/nm-setting-wireless-security.c \
+ $(core)/nm-setting-wireless.c \
+ $(core)/nm-setting.c \
+ $(core)/nm-simple-connection.c \
+ $(core)/nm-utils.c
+
+
+# header/source defines are in Makefile.libnm-core, so they can be shared
+# with libnm/Makefile.am
+libnmincludedir = $(includedir)/libnm
+libnminclude_HEADERS = $(libnm_core_headers)
+libnm_core_la_SOURCES = $(libnm_core_sources) \
+ $(libnm_core_private_headers) $(am__append_2) $(am__append_5)
+GLIB_GENERATED = nm-core-enum-types.h nm-core-enum-types.c
+nm_core_enum_types_sources = $(notdir $(libnminclude_HEADERS))
+GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM
+GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM
+libnm_core_la_LIBADD = $(GLIB_LIBS) $(UUID_LIBS) $(am__append_3) \
+ $(am__append_6)
+BUILT_SOURCES = $(GLIB_GENERATED)
+CLEANFILES = $(BUILT_SOURCES)
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/Makefile.libnm-core $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libnm-core/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu libnm-core/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+$(srcdir)/Makefile.libnm-core:
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+nm-version.h: $(top_builddir)/config.status $(srcdir)/nm-version.h.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libnm-core.la: $(libnm_core_la_OBJECTS) $(libnm_core_la_DEPENDENCIES) $(EXTRA_libnm_core_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(libnm_core_la_OBJECTS) $(libnm_core_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto_gnutls.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto_nss.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-connection.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-core-enum-types.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-errors.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-property-compare.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-8021x.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-adsl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-bluetooth.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-bond.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-bridge-port.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-bridge.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-cdma.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-connection.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-dcb.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-generic.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-gsm.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-infiniband.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-ip-config.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-ip4-config.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-ip6-config.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-olpc-mesh.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-ppp.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-pppoe.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-serial.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-team-port.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-team.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-vlan.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-vpn.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-wimax.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-wired.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-wireless-security.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting-wireless.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-setting.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-simple-connection.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-utils.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+nm-core-enum-types.lo: $(core_build)/nm-core-enum-types.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-core-enum-types.lo -MD -MP -MF $(DEPDIR)/nm-core-enum-types.Tpo -c -o nm-core-enum-types.lo `test -f '$(core_build)/nm-core-enum-types.c' || echo '$(srcdir)/'`$(core_build)/nm-core-enum-types.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-core-enum-types.Tpo $(DEPDIR)/nm-core-enum-types.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core_build)/nm-core-enum-types.c' object='nm-core-enum-types.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-core-enum-types.lo `test -f '$(core_build)/nm-core-enum-types.c' || echo '$(srcdir)/'`$(core_build)/nm-core-enum-types.c
+
+crypto.lo: $(core)/crypto.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT crypto.lo -MD -MP -MF $(DEPDIR)/crypto.Tpo -c -o crypto.lo `test -f '$(core)/crypto.c' || echo '$(srcdir)/'`$(core)/crypto.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/crypto.Tpo $(DEPDIR)/crypto.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/crypto.c' object='crypto.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o crypto.lo `test -f '$(core)/crypto.c' || echo '$(srcdir)/'`$(core)/crypto.c
+
+nm-connection.lo: $(core)/nm-connection.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-connection.lo -MD -MP -MF $(DEPDIR)/nm-connection.Tpo -c -o nm-connection.lo `test -f '$(core)/nm-connection.c' || echo '$(srcdir)/'`$(core)/nm-connection.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-connection.Tpo $(DEPDIR)/nm-connection.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-connection.c' object='nm-connection.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-connection.lo `test -f '$(core)/nm-connection.c' || echo '$(srcdir)/'`$(core)/nm-connection.c
+
+nm-errors.lo: $(core)/nm-errors.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-errors.lo -MD -MP -MF $(DEPDIR)/nm-errors.Tpo -c -o nm-errors.lo `test -f '$(core)/nm-errors.c' || echo '$(srcdir)/'`$(core)/nm-errors.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-errors.Tpo $(DEPDIR)/nm-errors.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-errors.c' object='nm-errors.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-errors.lo `test -f '$(core)/nm-errors.c' || echo '$(srcdir)/'`$(core)/nm-errors.c
+
+nm-property-compare.lo: $(core)/nm-property-compare.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-property-compare.lo -MD -MP -MF $(DEPDIR)/nm-property-compare.Tpo -c -o nm-property-compare.lo `test -f '$(core)/nm-property-compare.c' || echo '$(srcdir)/'`$(core)/nm-property-compare.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-property-compare.Tpo $(DEPDIR)/nm-property-compare.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-property-compare.c' object='nm-property-compare.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-property-compare.lo `test -f '$(core)/nm-property-compare.c' || echo '$(srcdir)/'`$(core)/nm-property-compare.c
+
+nm-setting-8021x.lo: $(core)/nm-setting-8021x.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-8021x.lo -MD -MP -MF $(DEPDIR)/nm-setting-8021x.Tpo -c -o nm-setting-8021x.lo `test -f '$(core)/nm-setting-8021x.c' || echo '$(srcdir)/'`$(core)/nm-setting-8021x.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-8021x.Tpo $(DEPDIR)/nm-setting-8021x.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-8021x.c' object='nm-setting-8021x.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-8021x.lo `test -f '$(core)/nm-setting-8021x.c' || echo '$(srcdir)/'`$(core)/nm-setting-8021x.c
+
+nm-setting-adsl.lo: $(core)/nm-setting-adsl.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-adsl.lo -MD -MP -MF $(DEPDIR)/nm-setting-adsl.Tpo -c -o nm-setting-adsl.lo `test -f '$(core)/nm-setting-adsl.c' || echo '$(srcdir)/'`$(core)/nm-setting-adsl.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-adsl.Tpo $(DEPDIR)/nm-setting-adsl.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-adsl.c' object='nm-setting-adsl.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-adsl.lo `test -f '$(core)/nm-setting-adsl.c' || echo '$(srcdir)/'`$(core)/nm-setting-adsl.c
+
+nm-setting-bluetooth.lo: $(core)/nm-setting-bluetooth.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-bluetooth.lo -MD -MP -MF $(DEPDIR)/nm-setting-bluetooth.Tpo -c -o nm-setting-bluetooth.lo `test -f '$(core)/nm-setting-bluetooth.c' || echo '$(srcdir)/'`$(core)/nm-setting-bluetooth.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-bluetooth.Tpo $(DEPDIR)/nm-setting-bluetooth.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-bluetooth.c' object='nm-setting-bluetooth.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-bluetooth.lo `test -f '$(core)/nm-setting-bluetooth.c' || echo '$(srcdir)/'`$(core)/nm-setting-bluetooth.c
+
+nm-setting-bond.lo: $(core)/nm-setting-bond.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-bond.lo -MD -MP -MF $(DEPDIR)/nm-setting-bond.Tpo -c -o nm-setting-bond.lo `test -f '$(core)/nm-setting-bond.c' || echo '$(srcdir)/'`$(core)/nm-setting-bond.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-bond.Tpo $(DEPDIR)/nm-setting-bond.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-bond.c' object='nm-setting-bond.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-bond.lo `test -f '$(core)/nm-setting-bond.c' || echo '$(srcdir)/'`$(core)/nm-setting-bond.c
+
+nm-setting-bridge-port.lo: $(core)/nm-setting-bridge-port.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-bridge-port.lo -MD -MP -MF $(DEPDIR)/nm-setting-bridge-port.Tpo -c -o nm-setting-bridge-port.lo `test -f '$(core)/nm-setting-bridge-port.c' || echo '$(srcdir)/'`$(core)/nm-setting-bridge-port.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-bridge-port.Tpo $(DEPDIR)/nm-setting-bridge-port.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-bridge-port.c' object='nm-setting-bridge-port.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-bridge-port.lo `test -f '$(core)/nm-setting-bridge-port.c' || echo '$(srcdir)/'`$(core)/nm-setting-bridge-port.c
+
+nm-setting-bridge.lo: $(core)/nm-setting-bridge.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-bridge.lo -MD -MP -MF $(DEPDIR)/nm-setting-bridge.Tpo -c -o nm-setting-bridge.lo `test -f '$(core)/nm-setting-bridge.c' || echo '$(srcdir)/'`$(core)/nm-setting-bridge.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-bridge.Tpo $(DEPDIR)/nm-setting-bridge.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-bridge.c' object='nm-setting-bridge.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-bridge.lo `test -f '$(core)/nm-setting-bridge.c' || echo '$(srcdir)/'`$(core)/nm-setting-bridge.c
+
+nm-setting-cdma.lo: $(core)/nm-setting-cdma.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-cdma.lo -MD -MP -MF $(DEPDIR)/nm-setting-cdma.Tpo -c -o nm-setting-cdma.lo `test -f '$(core)/nm-setting-cdma.c' || echo '$(srcdir)/'`$(core)/nm-setting-cdma.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-cdma.Tpo $(DEPDIR)/nm-setting-cdma.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-cdma.c' object='nm-setting-cdma.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-cdma.lo `test -f '$(core)/nm-setting-cdma.c' || echo '$(srcdir)/'`$(core)/nm-setting-cdma.c
+
+nm-setting-connection.lo: $(core)/nm-setting-connection.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-connection.lo -MD -MP -MF $(DEPDIR)/nm-setting-connection.Tpo -c -o nm-setting-connection.lo `test -f '$(core)/nm-setting-connection.c' || echo '$(srcdir)/'`$(core)/nm-setting-connection.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-connection.Tpo $(DEPDIR)/nm-setting-connection.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-connection.c' object='nm-setting-connection.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-connection.lo `test -f '$(core)/nm-setting-connection.c' || echo '$(srcdir)/'`$(core)/nm-setting-connection.c
+
+nm-setting-dcb.lo: $(core)/nm-setting-dcb.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-dcb.lo -MD -MP -MF $(DEPDIR)/nm-setting-dcb.Tpo -c -o nm-setting-dcb.lo `test -f '$(core)/nm-setting-dcb.c' || echo '$(srcdir)/'`$(core)/nm-setting-dcb.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-dcb.Tpo $(DEPDIR)/nm-setting-dcb.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-dcb.c' object='nm-setting-dcb.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-dcb.lo `test -f '$(core)/nm-setting-dcb.c' || echo '$(srcdir)/'`$(core)/nm-setting-dcb.c
+
+nm-setting-generic.lo: $(core)/nm-setting-generic.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-generic.lo -MD -MP -MF $(DEPDIR)/nm-setting-generic.Tpo -c -o nm-setting-generic.lo `test -f '$(core)/nm-setting-generic.c' || echo '$(srcdir)/'`$(core)/nm-setting-generic.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-generic.Tpo $(DEPDIR)/nm-setting-generic.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-generic.c' object='nm-setting-generic.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-generic.lo `test -f '$(core)/nm-setting-generic.c' || echo '$(srcdir)/'`$(core)/nm-setting-generic.c
+
+nm-setting-gsm.lo: $(core)/nm-setting-gsm.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-gsm.lo -MD -MP -MF $(DEPDIR)/nm-setting-gsm.Tpo -c -o nm-setting-gsm.lo `test -f '$(core)/nm-setting-gsm.c' || echo '$(srcdir)/'`$(core)/nm-setting-gsm.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-gsm.Tpo $(DEPDIR)/nm-setting-gsm.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-gsm.c' object='nm-setting-gsm.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-gsm.lo `test -f '$(core)/nm-setting-gsm.c' || echo '$(srcdir)/'`$(core)/nm-setting-gsm.c
+
+nm-setting-infiniband.lo: $(core)/nm-setting-infiniband.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-infiniband.lo -MD -MP -MF $(DEPDIR)/nm-setting-infiniband.Tpo -c -o nm-setting-infiniband.lo `test -f '$(core)/nm-setting-infiniband.c' || echo '$(srcdir)/'`$(core)/nm-setting-infiniband.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-infiniband.Tpo $(DEPDIR)/nm-setting-infiniband.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-infiniband.c' object='nm-setting-infiniband.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-infiniband.lo `test -f '$(core)/nm-setting-infiniband.c' || echo '$(srcdir)/'`$(core)/nm-setting-infiniband.c
+
+nm-setting-ip-config.lo: $(core)/nm-setting-ip-config.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-ip-config.lo -MD -MP -MF $(DEPDIR)/nm-setting-ip-config.Tpo -c -o nm-setting-ip-config.lo `test -f '$(core)/nm-setting-ip-config.c' || echo '$(srcdir)/'`$(core)/nm-setting-ip-config.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-ip-config.Tpo $(DEPDIR)/nm-setting-ip-config.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-ip-config.c' object='nm-setting-ip-config.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-ip-config.lo `test -f '$(core)/nm-setting-ip-config.c' || echo '$(srcdir)/'`$(core)/nm-setting-ip-config.c
+
+nm-setting-ip4-config.lo: $(core)/nm-setting-ip4-config.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-ip4-config.lo -MD -MP -MF $(DEPDIR)/nm-setting-ip4-config.Tpo -c -o nm-setting-ip4-config.lo `test -f '$(core)/nm-setting-ip4-config.c' || echo '$(srcdir)/'`$(core)/nm-setting-ip4-config.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-ip4-config.Tpo $(DEPDIR)/nm-setting-ip4-config.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-ip4-config.c' object='nm-setting-ip4-config.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-ip4-config.lo `test -f '$(core)/nm-setting-ip4-config.c' || echo '$(srcdir)/'`$(core)/nm-setting-ip4-config.c
+
+nm-setting-ip6-config.lo: $(core)/nm-setting-ip6-config.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-ip6-config.lo -MD -MP -MF $(DEPDIR)/nm-setting-ip6-config.Tpo -c -o nm-setting-ip6-config.lo `test -f '$(core)/nm-setting-ip6-config.c' || echo '$(srcdir)/'`$(core)/nm-setting-ip6-config.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-ip6-config.Tpo $(DEPDIR)/nm-setting-ip6-config.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-ip6-config.c' object='nm-setting-ip6-config.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-ip6-config.lo `test -f '$(core)/nm-setting-ip6-config.c' || echo '$(srcdir)/'`$(core)/nm-setting-ip6-config.c
+
+nm-setting-olpc-mesh.lo: $(core)/nm-setting-olpc-mesh.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-olpc-mesh.lo -MD -MP -MF $(DEPDIR)/nm-setting-olpc-mesh.Tpo -c -o nm-setting-olpc-mesh.lo `test -f '$(core)/nm-setting-olpc-mesh.c' || echo '$(srcdir)/'`$(core)/nm-setting-olpc-mesh.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-olpc-mesh.Tpo $(DEPDIR)/nm-setting-olpc-mesh.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-olpc-mesh.c' object='nm-setting-olpc-mesh.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-olpc-mesh.lo `test -f '$(core)/nm-setting-olpc-mesh.c' || echo '$(srcdir)/'`$(core)/nm-setting-olpc-mesh.c
+
+nm-setting-ppp.lo: $(core)/nm-setting-ppp.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-ppp.lo -MD -MP -MF $(DEPDIR)/nm-setting-ppp.Tpo -c -o nm-setting-ppp.lo `test -f '$(core)/nm-setting-ppp.c' || echo '$(srcdir)/'`$(core)/nm-setting-ppp.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-ppp.Tpo $(DEPDIR)/nm-setting-ppp.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-ppp.c' object='nm-setting-ppp.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-ppp.lo `test -f '$(core)/nm-setting-ppp.c' || echo '$(srcdir)/'`$(core)/nm-setting-ppp.c
+
+nm-setting-pppoe.lo: $(core)/nm-setting-pppoe.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-pppoe.lo -MD -MP -MF $(DEPDIR)/nm-setting-pppoe.Tpo -c -o nm-setting-pppoe.lo `test -f '$(core)/nm-setting-pppoe.c' || echo '$(srcdir)/'`$(core)/nm-setting-pppoe.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-pppoe.Tpo $(DEPDIR)/nm-setting-pppoe.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-pppoe.c' object='nm-setting-pppoe.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-pppoe.lo `test -f '$(core)/nm-setting-pppoe.c' || echo '$(srcdir)/'`$(core)/nm-setting-pppoe.c
+
+nm-setting-serial.lo: $(core)/nm-setting-serial.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-serial.lo -MD -MP -MF $(DEPDIR)/nm-setting-serial.Tpo -c -o nm-setting-serial.lo `test -f '$(core)/nm-setting-serial.c' || echo '$(srcdir)/'`$(core)/nm-setting-serial.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-serial.Tpo $(DEPDIR)/nm-setting-serial.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-serial.c' object='nm-setting-serial.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-serial.lo `test -f '$(core)/nm-setting-serial.c' || echo '$(srcdir)/'`$(core)/nm-setting-serial.c
+
+nm-setting-team-port.lo: $(core)/nm-setting-team-port.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-team-port.lo -MD -MP -MF $(DEPDIR)/nm-setting-team-port.Tpo -c -o nm-setting-team-port.lo `test -f '$(core)/nm-setting-team-port.c' || echo '$(srcdir)/'`$(core)/nm-setting-team-port.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-team-port.Tpo $(DEPDIR)/nm-setting-team-port.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-team-port.c' object='nm-setting-team-port.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-team-port.lo `test -f '$(core)/nm-setting-team-port.c' || echo '$(srcdir)/'`$(core)/nm-setting-team-port.c
+
+nm-setting-team.lo: $(core)/nm-setting-team.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-team.lo -MD -MP -MF $(DEPDIR)/nm-setting-team.Tpo -c -o nm-setting-team.lo `test -f '$(core)/nm-setting-team.c' || echo '$(srcdir)/'`$(core)/nm-setting-team.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-team.Tpo $(DEPDIR)/nm-setting-team.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-team.c' object='nm-setting-team.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-team.lo `test -f '$(core)/nm-setting-team.c' || echo '$(srcdir)/'`$(core)/nm-setting-team.c
+
+nm-setting-vlan.lo: $(core)/nm-setting-vlan.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-vlan.lo -MD -MP -MF $(DEPDIR)/nm-setting-vlan.Tpo -c -o nm-setting-vlan.lo `test -f '$(core)/nm-setting-vlan.c' || echo '$(srcdir)/'`$(core)/nm-setting-vlan.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-vlan.Tpo $(DEPDIR)/nm-setting-vlan.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-vlan.c' object='nm-setting-vlan.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-vlan.lo `test -f '$(core)/nm-setting-vlan.c' || echo '$(srcdir)/'`$(core)/nm-setting-vlan.c
+
+nm-setting-vpn.lo: $(core)/nm-setting-vpn.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-vpn.lo -MD -MP -MF $(DEPDIR)/nm-setting-vpn.Tpo -c -o nm-setting-vpn.lo `test -f '$(core)/nm-setting-vpn.c' || echo '$(srcdir)/'`$(core)/nm-setting-vpn.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-vpn.Tpo $(DEPDIR)/nm-setting-vpn.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-vpn.c' object='nm-setting-vpn.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-vpn.lo `test -f '$(core)/nm-setting-vpn.c' || echo '$(srcdir)/'`$(core)/nm-setting-vpn.c
+
+nm-setting-wimax.lo: $(core)/nm-setting-wimax.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-wimax.lo -MD -MP -MF $(DEPDIR)/nm-setting-wimax.Tpo -c -o nm-setting-wimax.lo `test -f '$(core)/nm-setting-wimax.c' || echo '$(srcdir)/'`$(core)/nm-setting-wimax.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-wimax.Tpo $(DEPDIR)/nm-setting-wimax.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-wimax.c' object='nm-setting-wimax.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-wimax.lo `test -f '$(core)/nm-setting-wimax.c' || echo '$(srcdir)/'`$(core)/nm-setting-wimax.c
+
+nm-setting-wired.lo: $(core)/nm-setting-wired.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-wired.lo -MD -MP -MF $(DEPDIR)/nm-setting-wired.Tpo -c -o nm-setting-wired.lo `test -f '$(core)/nm-setting-wired.c' || echo '$(srcdir)/'`$(core)/nm-setting-wired.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-wired.Tpo $(DEPDIR)/nm-setting-wired.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-wired.c' object='nm-setting-wired.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-wired.lo `test -f '$(core)/nm-setting-wired.c' || echo '$(srcdir)/'`$(core)/nm-setting-wired.c
+
+nm-setting-wireless-security.lo: $(core)/nm-setting-wireless-security.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-wireless-security.lo -MD -MP -MF $(DEPDIR)/nm-setting-wireless-security.Tpo -c -o nm-setting-wireless-security.lo `test -f '$(core)/nm-setting-wireless-security.c' || echo '$(srcdir)/'`$(core)/nm-setting-wireless-security.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-wireless-security.Tpo $(DEPDIR)/nm-setting-wireless-security.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-wireless-security.c' object='nm-setting-wireless-security.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-wireless-security.lo `test -f '$(core)/nm-setting-wireless-security.c' || echo '$(srcdir)/'`$(core)/nm-setting-wireless-security.c
+
+nm-setting-wireless.lo: $(core)/nm-setting-wireless.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting-wireless.lo -MD -MP -MF $(DEPDIR)/nm-setting-wireless.Tpo -c -o nm-setting-wireless.lo `test -f '$(core)/nm-setting-wireless.c' || echo '$(srcdir)/'`$(core)/nm-setting-wireless.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting-wireless.Tpo $(DEPDIR)/nm-setting-wireless.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting-wireless.c' object='nm-setting-wireless.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting-wireless.lo `test -f '$(core)/nm-setting-wireless.c' || echo '$(srcdir)/'`$(core)/nm-setting-wireless.c
+
+nm-setting.lo: $(core)/nm-setting.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-setting.lo -MD -MP -MF $(DEPDIR)/nm-setting.Tpo -c -o nm-setting.lo `test -f '$(core)/nm-setting.c' || echo '$(srcdir)/'`$(core)/nm-setting.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-setting.Tpo $(DEPDIR)/nm-setting.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-setting.c' object='nm-setting.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-setting.lo `test -f '$(core)/nm-setting.c' || echo '$(srcdir)/'`$(core)/nm-setting.c
+
+nm-simple-connection.lo: $(core)/nm-simple-connection.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-simple-connection.lo -MD -MP -MF $(DEPDIR)/nm-simple-connection.Tpo -c -o nm-simple-connection.lo `test -f '$(core)/nm-simple-connection.c' || echo '$(srcdir)/'`$(core)/nm-simple-connection.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-simple-connection.Tpo $(DEPDIR)/nm-simple-connection.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-simple-connection.c' object='nm-simple-connection.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-simple-connection.lo `test -f '$(core)/nm-simple-connection.c' || echo '$(srcdir)/'`$(core)/nm-simple-connection.c
+
+nm-utils.lo: $(core)/nm-utils.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT nm-utils.lo -MD -MP -MF $(DEPDIR)/nm-utils.Tpo -c -o nm-utils.lo `test -f '$(core)/nm-utils.c' || echo '$(srcdir)/'`$(core)/nm-utils.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/nm-utils.Tpo $(DEPDIR)/nm-utils.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(core)/nm-utils.c' object='nm-utils.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o nm-utils.lo `test -f '$(core)/nm-utils.c' || echo '$(srcdir)/'`$(core)/nm-utils.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-libnmincludeHEADERS: $(libnminclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(libnminclude_HEADERS)'; test -n "$(libnmincludedir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(libnmincludedir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(libnmincludedir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libnmincludedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libnmincludedir)" || exit $$?; \
+ done
+
+uninstall-libnmincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(libnminclude_HEADERS)'; test -n "$(libnmincludedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(libnmincludedir)'; $(am__uninstall_files_from_dir)
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+# (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+ @fail=; \
+ if $(am__make_keepgoing); then \
+ failcom='fail=yes'; \
+ else \
+ failcom='exit 1'; \
+ fi; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-recursive
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-recursive
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-recursive
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ $(am__make_dryrun) \
+ || test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-recursive
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(libnmincludedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-libnmincludeHEADERS
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-libnmincludeHEADERS
+
+.MAKE: $(am__recursive_targets) all check install install-am \
+ install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
+ check-am clean clean-generic clean-libtool \
+ clean-noinstLTLIBRARIES cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am \
+ install-libnmincludeHEADERS install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs installdirs-am \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \
+ uninstall-libnmincludeHEADERS
+
+include $(GLIB_MAKEFILE)
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/libnm-core/Makefile.libnm-core b/libnm-core/Makefile.libnm-core
new file mode 100644
index 000000000..fc6d779b5
--- /dev/null
+++ b/libnm-core/Makefile.libnm-core
@@ -0,0 +1,91 @@
+# In order for this to work correctly from both libnm-core/ and libnm/,
+# we have to specify full pathnames. (We can't just use $(addprefix) from
+# libnm/, because that's incompatible with the Makefile.introspection rules.)
+
+core = $(top_srcdir)/libnm-core
+core_build = $(top_builddir)/libnm-core
+
+libnm_core_headers = \
+ $(core_build)/nm-core-enum-types.h \
+ $(core_build)/nm-version.h \
+ $(core)/nm-connection.h \
+ $(core)/nm-core-types.h \
+ $(core)/nm-dbus-interface.h \
+ $(core)/nm-errors.h \
+ $(core)/nm-setting-8021x.h \
+ $(core)/nm-setting-adsl.h \
+ $(core)/nm-setting-bluetooth.h \
+ $(core)/nm-setting-bond.h \
+ $(core)/nm-setting-bridge-port.h \
+ $(core)/nm-setting-bridge.h \
+ $(core)/nm-setting-cdma.h \
+ $(core)/nm-setting-connection.h \
+ $(core)/nm-setting-dcb.h \
+ $(core)/nm-setting-generic.h \
+ $(core)/nm-setting-gsm.h \
+ $(core)/nm-setting-infiniband.h \
+ $(core)/nm-setting-ip-config.h \
+ $(core)/nm-setting-ip4-config.h \
+ $(core)/nm-setting-ip6-config.h \
+ $(core)/nm-setting-olpc-mesh.h \
+ $(core)/nm-setting-ppp.h \
+ $(core)/nm-setting-pppoe.h \
+ $(core)/nm-setting-serial.h \
+ $(core)/nm-setting-team-port.h \
+ $(core)/nm-setting-team.h \
+ $(core)/nm-setting-vlan.h \
+ $(core)/nm-setting-vpn.h \
+ $(core)/nm-setting-wimax.h \
+ $(core)/nm-setting-wired.h \
+ $(core)/nm-setting-wireless-security.h \
+ $(core)/nm-setting-wireless.h \
+ $(core)/nm-setting.h \
+ $(core)/nm-simple-connection.h \
+ $(core)/nm-utils.h \
+ $(core)/nm-vpn-dbus-interface.h
+
+libnm_core_private_headers = \
+ $(core)/crypto.h \
+ $(core)/nm-connection-private.h \
+ $(core)/nm-core-internal.h \
+ $(core)/nm-property-compare.h \
+ $(core)/nm-setting-private.h \
+ $(core)/nm-utils-private.h
+
+libnm_core_sources = \
+ $(core_build)/nm-core-enum-types.c \
+ $(core)/crypto.c \
+ $(core)/nm-connection.c \
+ $(core)/nm-errors.c \
+ $(core)/nm-property-compare.c \
+ $(core)/nm-setting-8021x.c \
+ $(core)/nm-setting-adsl.c \
+ $(core)/nm-setting-bluetooth.c \
+ $(core)/nm-setting-bond.c \
+ $(core)/nm-setting-bridge-port.c \
+ $(core)/nm-setting-bridge.c \
+ $(core)/nm-setting-cdma.c \
+ $(core)/nm-setting-connection.c \
+ $(core)/nm-setting-dcb.c \
+ $(core)/nm-setting-generic.c \
+ $(core)/nm-setting-gsm.c \
+ $(core)/nm-setting-infiniband.c \
+ $(core)/nm-setting-ip-config.c \
+ $(core)/nm-setting-ip4-config.c \
+ $(core)/nm-setting-ip6-config.c \
+ $(core)/nm-setting-olpc-mesh.c \
+ $(core)/nm-setting-ppp.c \
+ $(core)/nm-setting-pppoe.c \
+ $(core)/nm-setting-serial.c \
+ $(core)/nm-setting-team-port.c \
+ $(core)/nm-setting-team.c \
+ $(core)/nm-setting-vlan.c \
+ $(core)/nm-setting-vpn.c \
+ $(core)/nm-setting-wimax.c \
+ $(core)/nm-setting-wired.c \
+ $(core)/nm-setting-wireless-security.c \
+ $(core)/nm-setting-wireless.c \
+ $(core)/nm-setting.c \
+ $(core)/nm-simple-connection.c \
+ $(core)/nm-utils.c
+
diff --git a/libnm-core/crypto.c b/libnm-core/crypto.c
new file mode 100644
index 000000000..205d22c61
--- /dev/null
+++ b/libnm-core/crypto.c
@@ -0,0 +1,816 @@
+/* -*- 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 "config.h"
+
+#include <glib.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <glib/gi18n-lib.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;
+
+ 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 (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;
+ int nkey = buflen;
+ gsize digest_len;
+ int count = 0;
+ char digest[16];
+ char *p = buffer;
+
+ g_assert_cmpint (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);
+
+ while (nkey > 0) {
+ int i = 0;
+
+ g_checksum_reset (ctx);
+ if (count++)
+ g_checksum_update (ctx, (const guchar *) digest, sizeof (digest));
+ 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);
+ g_assert (digest_len == sizeof (digest));
+
+ while (nkey && (i < sizeof (digest))) {
+ *(p++) = digest[i++];
+ nkey--;
+ }
+ }
+
+ memset (digest, 0, sizeof (digest));
+ g_checksum_free (ctx);
+}
diff --git a/libnm-core/crypto.h b/libnm-core/crypto.h
new file mode 100644
index 000000000..434f108d0
--- /dev/null
+++ b/libnm-core/crypto.h
@@ -0,0 +1,133 @@
+/* -*- 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__
+
+#include <glib.h>
+
+#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/crypto_gnutls.c b/libnm-core/crypto_gnutls.c
new file mode 100644
index 000000000..96dddb902
--- /dev/null
+++ b/libnm-core/crypto_gnutls.c
@@ -0,0 +1,454 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager Wireless Applet -- Display wireless access points and allow user control
+ *
+ * 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 - 2009 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+
+#include <gcrypt.h>
+#include <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/pkcs12.h>
+
+#include "crypto.h"
+#include "nm-errors.h"
+
+#define SALT_LEN 8
+
+static gboolean initialized = FALSE;
+
+gboolean
+crypto_init (GError **error)
+{
+ if (initialized)
+ return TRUE;
+
+ 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."));
+ return FALSE;
+ }
+
+ 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)
+{
+ gcry_cipher_hd_t ctx;
+ gcry_error_t err;
+ int cipher_mech, i;
+ char *output = NULL;
+ gboolean success = FALSE;
+ gsize pad_len, real_iv_len;
+
+ if (!crypto_init (error))
+ return NULL;
+
+ if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) {
+ cipher_mech = GCRY_CIPHER_3DES;
+ real_iv_len = SALT_LEN;
+ } else if (!strcmp (cipher, CIPHER_DES_CBC)) {
+ cipher_mech = GCRY_CIPHER_DES;
+ real_iv_len = SALT_LEN;
+ } else if (!strcmp (cipher, CIPHER_AES_CBC)) {
+ cipher_mech = GCRY_CIPHER_AES;
+ real_iv_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 (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);
+ return NULL;
+ }
+
+ output = g_malloc0 (data_len);
+
+ err = gcry_cipher_open (&ctx, cipher_mech, GCRY_CIPHER_MODE_CBC, 0);
+ if (err) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_DECRYPTION_FAILED,
+ _("Failed to initialize the decryption cipher context: %s / %s."),
+ gcry_strsource (err), gcry_strerror (err));
+ goto out;
+ }
+
+ err = gcry_cipher_setkey (ctx, key, key_len);
+ if (err) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_DECRYPTION_FAILED,
+ _("Failed to set symmetric key for decryption: %s / %s."),
+ gcry_strsource (err), gcry_strerror (err));
+ goto out;
+ }
+
+ err = gcry_cipher_setiv (ctx, iv, iv_len);
+ if (err) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_DECRYPTION_FAILED,
+ _("Failed to set IV for decryption: %s / %s."),
+ gcry_strsource (err), gcry_strerror (err));
+ goto out;
+ }
+
+ err = gcry_cipher_decrypt (ctx, output, data_len, data, data_len);
+ if (err) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_DECRYPTION_FAILED,
+ _("Failed to decrypt the private key: %s / %s."),
+ gcry_strsource (err), gcry_strerror (err));
+ goto out;
+ }
+ pad_len = output[data_len - 1];
+
+ /* Check if the padding at the end of the decrypted data is valid */
+ 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;
+ }
+
+ /* 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) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_DECRYPTION_FAILED,
+ _("Failed to decrypt the private key."));
+ goto out;
+ }
+ }
+
+ *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;
+ }
+ }
+ gcry_cipher_close (ctx);
+ return output;
+}
+
+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)
+{
+ gcry_cipher_hd_t ctx;
+ gcry_error_t err;
+ int cipher_mech;
+ char *output = NULL;
+ gboolean success = FALSE;
+ gsize padded_buf_len, pad_len, output_len;
+ char *padded_buf = NULL;
+ guint32 i;
+ gsize salt_len;
+
+ if (!crypto_init (error))
+ return NULL;
+
+ if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) {
+ cipher_mech = GCRY_CIPHER_3DES;
+ salt_len = SALT_LEN;
+ } else if (!strcmp (cipher, CIPHER_AES_CBC)) {
+ cipher_mech = GCRY_CIPHER_AES;
+ salt_len = iv_len;
+ } else {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_UNKNOWN_CIPHER,
+ _("Private key cipher '%s' was unknown."),
+ cipher);
+ 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);
+
+ err = gcry_cipher_open (&ctx, cipher_mech, GCRY_CIPHER_MODE_CBC, 0);
+ if (err) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
+ _("Failed to initialize the encryption cipher context: %s / %s."),
+ gcry_strsource (err), gcry_strerror (err));
+ goto out;
+ }
+
+ err = gcry_cipher_setkey (ctx, key, key_len);
+ if (err) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
+ _("Failed to set symmetric key for encryption: %s / %s."),
+ gcry_strsource (err), gcry_strerror (err));
+ goto out;
+ }
+
+ /* gcrypt only wants 8 bytes of the IV (same as the DES block length) */
+ err = gcry_cipher_setiv (ctx, iv, salt_len);
+ if (err) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
+ _("Failed to set IV for encryption: %s / %s."),
+ gcry_strsource (err), gcry_strerror (err));
+ goto out;
+ }
+
+ err = gcry_cipher_encrypt (ctx, output, output_len, padded_buf, padded_buf_len);
+ if (err) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
+ _("Failed to encrypt the data: %s / %s."),
+ gcry_strsource (err), gcry_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;
+ }
+
+ if (!success) {
+ if (output) {
+ /* Don't expose key material */
+ memset (output, 0, output_len);
+ g_free (output);
+ output = NULL;
+ }
+ }
+ gcry_cipher_close (ctx);
+ return output;
+}
+
+NMCryptoFileFormat
+crypto_verify_cert (const unsigned char *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;
+
+ err = gnutls_x509_crt_init (&der);
+ if (err < 0) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_INVALID_DATA,
+ _("Error initializing certificate data: %s"),
+ gnutls_strerror (err));
+ return NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+ }
+
+ /* Try DER first */
+ dt.data = (unsigned char *) data;
+ dt.size = len;
+ 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;
+ }
+
+ /* 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;
+
+ 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;
+}
+
+gboolean
+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))
+ return FALSE;
+
+ dt.data = (unsigned char *) data;
+ dt.size = data_len;
+
+ err = gnutls_pkcs12_init (&p12);
+ if (err < 0) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_FAILED,
+ _("Couldn't initialize PKCS#12 decoder: %s"),
+ gnutls_strerror (err));
+ return FALSE;
+ }
+
+ /* DER first */
+ err = gnutls_pkcs12_import (p12, &dt, GNUTLS_X509_FMT_DER, 0);
+ if (err < 0) {
+ /* PEM next */
+ err = gnutls_pkcs12_import (p12, &dt, GNUTLS_X509_FMT_PEM, 0);
+ if (err < 0) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_INVALID_DATA,
+ _("Couldn't decode PKCS#12 file: %s"),
+ gnutls_strerror (err));
+ goto out;
+ }
+ }
+
+ err = gnutls_pkcs12_verify_mac (p12, password);
+ if (err == GNUTLS_E_SUCCESS)
+ success = TRUE;
+ else {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_DECRYPTION_FAILED,
+ _("Couldn't verify PKCS#12 file: %s"),
+ gnutls_strerror (err));
+ }
+
+out:
+ gnutls_pkcs12_deinit (p12);
+ return success;
+}
+
+gboolean
+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;
+ int err;
+
+ g_return_val_if_fail (data != NULL, FALSE);
+
+ if (!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,
+ NM_CRYPTO_ERROR_FAILED,
+ _("Couldn't initialize PKCS#8 decoder: %s"),
+ gnutls_strerror (err));
+ return FALSE;
+ }
+
+ 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) {
+ if (err == GNUTLS_E_UNKNOWN_CIPHER_TYPE) {
+ /* HACK: gnutls doesn't support all the cipher types that openssl
+ * can use with PKCS#8, so if we encounter one, we have to assume
+ * the given password works. gnutls needs to unsuckify, apparently.
+ * Specifically, by default openssl uses pbeWithMD5AndDES-CBC
+ * which gnutls does not support.
+ */
+ } else {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_INVALID_DATA,
+ _("Couldn't decode PKCS#8 file: %s"),
+ gnutls_strerror (err));
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+gboolean
+crypto_randomize (void *buffer, gsize buffer_len, GError **error)
+{
+ if (!crypto_init (error))
+ return FALSE;
+
+ gcry_randomize (buffer, buffer_len, GCRY_STRONG_RANDOM);
+ return TRUE;
+}
diff --git a/libnm-core/crypto_nss.c b/libnm-core/crypto_nss.c
new file mode 100644
index 000000000..d0c3506b8
--- /dev/null
+++ b/libnm-core/crypto_nss.c
@@ -0,0 +1,526 @@
+/* -*- 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 - 2009 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib/gi18n-lib.h>
+
+#include <prinit.h>
+#include <nss.h>
+#include <pk11pub.h>
+#include <pkcs11t.h>
+#include <cert.h>
+#include <prerror.h>
+#include <p12.h>
+#include <ciferfam.h>
+#include <p12plcy.h>
+
+#include "crypto.h"
+#include "nm-errors.h"
+
+static gboolean initialized = FALSE;
+
+gboolean
+crypto_init (GError **error)
+{
+ SECStatus ret;
+
+ if (initialized)
+ return TRUE;
+
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 1);
+ ret = NSS_NoDB_Init (NULL);
+ if (ret != SECSuccess) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_FAILED,
+ _("Failed to initialize the crypto engine: %d."),
+ PR_GetError ());
+ PR_Cleanup ();
+ 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);
+
+ 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)
+{
+ 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;
+ SECStatus s;
+ gboolean success = FALSE;
+ unsigned int pad_len = 0, extra = 0;
+ guint32 i, real_iv_len = 0;
+
+ if (!crypto_init (error))
+ return NULL;
+
+ 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 {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_UNKNOWN_CIPHER,
+ _("Private key cipher '%s' was unknown."),
+ cipher);
+ 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);
+ return NULL;
+ }
+
+ output = g_malloc0 (data_len);
+
+ slot = PK11_GetBestSlot (cipher_mech, NULL);
+ if (!slot) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_FAILED,
+ _("Failed to initialize the decryption cipher slot."));
+ goto out;
+ }
+
+ key_item.data = (unsigned char *) key;
+ key_item.len = key_len;
+ sym_key = PK11_ImportSymKey (slot, cipher_mech, PK11_OriginUnwrap, CKA_DECRYPT, &key_item, NULL);
+ if (!sym_key) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_DECRYPTION_FAILED,
+ _("Failed to set symmetric key for decryption."));
+ goto out;
+ }
+
+ key_item.data = (unsigned char *) iv;
+ key_item.len = real_iv_len;
+ sec_param = PK11_ParamFromIV (cipher_mech, &key_item);
+ if (!sec_param) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_DECRYPTION_FAILED,
+ _("Failed to set IV for decryption."));
+ goto out;
+ }
+
+ ctx = PK11_CreateContextBySymKey (cipher_mech, CKA_DECRYPT, sym_key, sec_param);
+ if (!ctx) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_DECRYPTION_FAILED,
+ _("Failed to initialize the decryption context."));
+ goto out;
+ }
+
+ s = PK11_CipherOp (ctx,
+ (unsigned char *) output,
+ &decrypted_len,
+ data_len,
+ data,
+ data_len);
+ if (s != SECSuccess) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_DECRYPTION_FAILED,
+ _("Failed to decrypt the private key: %d."),
+ PORT_GetError ());
+ goto out;
+ }
+
+ if (decrypted_len > data_len) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_DECRYPTION_FAILED,
+ _("Failed to decrypt the private key: decrypted data too large."));
+ goto out;
+ }
+
+ s = PK11_DigestFinal (ctx,
+ (unsigned char *) (output + decrypted_len),
+ &extra,
+ data_len - decrypted_len);
+ if (s != SECSuccess) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_DECRYPTION_FAILED,
+ _("Failed to finalize decryption of the private key: %d."),
+ PORT_GetError ());
+ goto out;
+ }
+ decrypted_len += extra;
+ pad_len = data_len - decrypted_len;
+
+ /* Check if the padding at the end of the decrypted data is valid */
+ 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;
+ }
+
+ /* Validate tail padding; last byte is the padding size, and all pad bytes
+ * should contain the padding size.
+ */
+ for (i = pad_len; i > 0; i--) {
+ if (output[data_len - i] != pad_len) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_DECRYPTION_FAILED,
+ _("Failed to decrypt the private key."));
+ goto out;
+ }
+ }
+
+ *out_len = decrypted_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 (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;
+}
+
+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)
+{
+ SECStatus ret;
+ CK_MECHANISM_TYPE cipher_mech = CKM_DES3_CBC_PAD;
+ PK11SlotInfo *slot = NULL;
+ SECItem key_item = { .data = (unsigned char *) key, .len = key_len };
+ SECItem iv_item = { .data = (unsigned char *) iv, .len = iv_len };
+ PK11SymKey *sym_key = NULL;
+ SECItem *sec_param = NULL;
+ PK11Context *ctx = NULL;
+ unsigned char *output, *padded_buf;
+ gsize output_len;
+ int encrypted_len = 0, i;
+ gboolean success = FALSE;
+ gsize padded_buf_len, pad_len;
+
+ if (!crypto_init (error))
+ return NULL;
+
+ 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 {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_UNKNOWN_CIPHER,
+ _("Private key cipher '%s' was unknown."),
+ cipher);
+ 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);
+
+ 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;
+ }
+
+ sym_key = PK11_ImportSymKey (slot, cipher_mech, PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, NULL);
+ if (!sym_key) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
+ _("Failed to set symmetric key for encryption."));
+ goto out;
+ }
+
+ sec_param = PK11_ParamFromIV (cipher_mech, &iv_item);
+ if (!sec_param) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
+ _("Failed to set IV for encryption."));
+ goto out;
+ }
+
+ ctx = PK11_CreateContextBySymKey (cipher_mech, CKA_ENCRYPT, sym_key, sec_param);
+ if (!ctx) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
+ _("Failed to initialize the encryption context."));
+ goto out;
+ }
+
+ ret = PK11_CipherOp (ctx, output, &encrypted_len, output_len, padded_buf, padded_buf_len);
+ if (ret != SECSuccess) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
+ _("Failed to encrypt: %d."),
+ PORT_GetError ());
+ goto out;
+ }
+
+ 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 (slot)
+ PK11_FreeSlot (slot);
+
+ memset (padded_buf, 0, padded_buf_len);
+ g_free (padded_buf);
+
+ if (!success) {
+ memset (output, 0, output_len);
+ g_free (output);
+ output = NULL;
+ }
+ return (char *) output;
+}
+
+NMCryptoFileFormat
+crypto_verify_cert (const unsigned char *data,
+ gsize len,
+ GError **error)
+{
+ CERTCertificate *cert;
+
+ if (!crypto_init (error))
+ return NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+
+ /* Try DER/PEM first */
+ cert = CERT_DecodeCertFromPackage ((char *) data, len);
+ if (!cert) {
+ 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;
+ }
+
+ CERT_DestroyCertificate (cert);
+ return NM_CRYPTO_FILE_FORMAT_X509;
+}
+
+gboolean
+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 */
+
+ if (error)
+ g_return_val_if_fail (*error == NULL, FALSE);
+
+ if (!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)) {
+ 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;
+ }
+
+ 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;
+ }
+
+ s = SEC_PKCS12DecoderUpdate (p12ctx, (guint8 *)data, data_len);
+ if (s != SECSuccess) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_INVALID_DATA,
+ _("Couldn't decode PKCS#12 file: %d"),
+ PORT_GetError());
+ goto error;
+ }
+
+ s = SEC_PKCS12DecoderVerify (p12ctx);
+ if (s != SECSuccess) {
+ g_set_error (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_DECRYPTION_FAILED,
+ _("Couldn't verify PKCS#12 file: %d"),
+ PORT_GetError());
+ goto error;
+ }
+
+ SEC_PKCS12DecoderFinish (p12ctx);
+ SECITEM_ZfreeItem (&pw, PR_FALSE);
+ return TRUE;
+
+error:
+ if (p12ctx)
+ SEC_PKCS12DecoderFinish (p12ctx);
+
+ if (slot)
+ PK11_FreeSlot(slot);
+
+ SECITEM_ZfreeItem (&pw, PR_FALSE);
+ return FALSE;
+}
+
+gboolean
+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))
+ return FALSE;
+
+ /* NSS apparently doesn't do PKCS#8 natively, but you have to put the
+ * PKCS#8 key into a PKCS#12 file and import that?? So until we figure
+ * all that out, we can only assume the password is valid.
+ */
+ return TRUE;
+}
+
+gboolean
+crypto_randomize (void *buffer, gsize buffer_len, GError **error)
+{
+ SECStatus s;
+
+ if (!crypto_init (error))
+ return FALSE;
+
+ s = PK11_GenerateRandom (buffer, buffer_len);
+ if (s != SECSuccess) {
+ g_set_error_literal (error, NM_CRYPTO_ERROR,
+ NM_CRYPTO_ERROR_FAILED,
+ _("Could not generate random data."));
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/libnm-core/nm-connection-private.h b/libnm-core/nm-connection-private.h
new file mode 100644
index 000000000..620e6a81e
--- /dev/null
+++ b/libnm-core/nm-connection-private.h
@@ -0,0 +1,35 @@
+/* -*- 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 2014 Red Hat, Inc.
+ */
+
+#ifndef __NM_CONNECTION_PRIVATE_H__
+#define __NM_CONNECTION_PRIVATE_H__
+
+#include "nm-setting.h"
+#include "nm-connection.h"
+
+NMSetting *_nm_connection_find_base_type_setting (NMConnection *connection);
+
+const char *_nm_connection_detect_slave_type (NMConnection *connection,
+ NMSetting **out_s_port);
+
+gboolean _nm_connection_verify_required_interface_name (NMConnection *connection,
+ GError **error);
+
+#endif /* __NM_CONNECTION_PRIVATE_H__ */
diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c
new file mode 100644
index 000000000..907713bd0
--- /dev/null
+++ b/libnm-core/nm-connection.c
@@ -0,0 +1,2077 @@
+/* -*- 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 2007 - 2013 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+#include <glib/gi18n-lib.h>
+#include <string.h>
+#include "nm-connection.h"
+#include "nm-connection-private.h"
+#include "nm-utils.h"
+#include "nm-setting-private.h"
+#include "nm-core-internal.h"
+
+/**
+ * SECTION:nm-connection
+ * @short_description: Describes a connection to specific network or provider
+ *
+ * An #NMConnection describes all the settings and configuration values that
+ * are necessary to configure network devices for operation on a specific
+ * network. Connections are the fundamental operating object for
+ * NetworkManager; no device is connected without a #NMConnection, or
+ * disconnected without having been connected with a #NMConnection.
+ *
+ * Each #NMConnection contains a list of #NMSetting objects usually referenced
+ * by name (using nm_connection_get_setting_by_name()) or by type (with
+ * nm_connection_get_setting()). The settings describe the actual parameters
+ * with which the network devices are configured, including device-specific
+ * parameters (MTU, SSID, APN, channel, rate, etc) and IP-level parameters
+ * (addresses, routes, addressing methods, etc).
+ *
+ */
+
+typedef struct {
+ NMConnection *self;
+
+ GHashTable *settings;
+
+ /* D-Bus path of the connection, if any */
+ char *path;
+} NMConnectionPrivate;
+
+static NMConnectionPrivate *nm_connection_get_private (NMConnection *connection);
+#define NM_CONNECTION_GET_PRIVATE(o) (nm_connection_get_private ((NMConnection *)o))
+
+G_DEFINE_INTERFACE (NMConnection, nm_connection, G_TYPE_OBJECT)
+
+enum {
+ SECRETS_UPDATED,
+ SECRETS_CLEARED,
+ CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+
+static NMSettingVerifyResult _nm_connection_verify (NMConnection *connection, GError **error);
+
+
+/*************************************************************/
+
+static void
+setting_changed_cb (NMSetting *setting,
+ GParamSpec *pspec,
+ NMConnection *self)
+{
+ g_signal_emit (self, signals[CHANGED], 0);
+}
+
+static gboolean
+_setting_release (gpointer key, gpointer value, gpointer user_data)
+{
+ g_signal_handlers_disconnect_by_func (user_data, setting_changed_cb, value);
+ return TRUE;
+}
+
+static void
+_nm_connection_add_setting (NMConnection *connection, NMSetting *setting)
+{
+ NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (connection);
+ const char *name = G_OBJECT_TYPE_NAME (setting);
+ NMSetting *s_old;
+
+ if ((s_old = g_hash_table_lookup (priv->settings, (gpointer) name)))
+ g_signal_handlers_disconnect_by_func (s_old, setting_changed_cb, connection);
+ g_hash_table_insert (priv->settings, (gpointer) name, setting);
+ /* Listen for property changes so we can emit the 'changed' signal */
+ g_signal_connect (setting, "notify", (GCallback) setting_changed_cb, connection);
+}
+
+/**
+ * nm_connection_add_setting:
+ * @connection: a #NMConnection
+ * @setting: (transfer full): the #NMSetting to add to the connection object
+ *
+ * Adds a #NMSetting to the connection, replacing any previous #NMSetting of the
+ * same name which has previously been added to the #NMConnection. The
+ * connection takes ownership of the #NMSetting object and does not increase
+ * the setting object's reference count.
+ **/
+void
+nm_connection_add_setting (NMConnection *connection, NMSetting *setting)
+{
+ g_return_if_fail (NM_IS_CONNECTION (connection));
+ g_return_if_fail (NM_IS_SETTING (setting));
+
+ _nm_connection_add_setting (connection, setting);
+ g_signal_emit (connection, signals[CHANGED], 0);
+}
+
+/**
+ * nm_connection_remove_setting:
+ * @connection: a #NMConnection
+ * @setting_type: the #GType of the setting object to remove
+ *
+ * Removes the #NMSetting with the given #GType from the #NMConnection. This
+ * operation dereferences the #NMSetting object.
+ **/
+void
+nm_connection_remove_setting (NMConnection *connection, GType setting_type)
+{
+ NMConnectionPrivate *priv;
+ NMSetting *setting;
+ const char *setting_name;
+
+ g_return_if_fail (NM_IS_CONNECTION (connection));
+ g_return_if_fail (g_type_is_a (setting_type, NM_TYPE_SETTING));
+
+ priv = NM_CONNECTION_GET_PRIVATE (connection);
+ setting_name = g_type_name (setting_type);
+ setting = g_hash_table_lookup (priv->settings, setting_name);
+ if (setting) {
+ g_signal_handlers_disconnect_by_func (setting, setting_changed_cb, connection);
+ g_hash_table_remove (priv->settings, setting_name);
+ g_signal_emit (connection, signals[CHANGED], 0);
+ }
+}
+
+/**
+ * nm_connection_get_setting:
+ * @connection: a #NMConnection
+ * @setting_type: the #GType of the setting object to return
+ *
+ * Gets the #NMSetting with the given #GType, if one has been previously added
+ * to the #NMConnection.
+ *
+ * Returns: (transfer none): the #NMSetting, or %NULL if no setting of that type was previously
+ * added to the #NMConnection
+ **/
+NMSetting *
+nm_connection_get_setting (NMConnection *connection, GType setting_type)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+ g_return_val_if_fail (g_type_is_a (setting_type, NM_TYPE_SETTING), NULL);
+
+ return (NMSetting *) g_hash_table_lookup (NM_CONNECTION_GET_PRIVATE (connection)->settings,
+ g_type_name (setting_type));
+}
+
+/**
+ * nm_connection_get_setting_by_name:
+ * @connection: a #NMConnection
+ * @name: a setting name
+ *
+ * Gets the #NMSetting with the given name, if one has been previously added
+ * the #NMConnection.
+ *
+ * Returns: (transfer none): the #NMSetting, or %NULL if no setting with that name was previously
+ * added to the #NMConnection
+ **/
+NMSetting *
+nm_connection_get_setting_by_name (NMConnection *connection, const char *name)
+{
+ GType type;
+
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+ g_return_val_if_fail (name != NULL, NULL);
+
+ type = nm_setting_lookup_type (name);
+
+ return type ? nm_connection_get_setting (connection, type) : NULL;
+}
+
+static gboolean
+validate_permissions_type (GVariant *variant, GError **error)
+{
+ GVariant *s_con;
+ GVariant *permissions;
+ gboolean valid = TRUE;
+
+ /* Ensure the connection::permissions item (if present) is the correct
+ * type, otherwise the g_object_set() will throw a warning and ignore the
+ * error, leaving us with no permissions.
+ */
+ s_con = g_variant_lookup_value (variant, NM_SETTING_CONNECTION_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
+ if (!s_con)
+ return TRUE;
+
+ permissions = g_variant_lookup_value (s_con, NM_SETTING_CONNECTION_PERMISSIONS, NULL);
+ if (permissions) {
+ if (!g_variant_is_of_type (permissions, G_VARIANT_TYPE_STRING_ARRAY)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("wrong type; should be a list of strings."));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_PERMISSIONS);
+ valid = FALSE;
+ }
+ g_variant_unref (permissions);
+ }
+
+ g_variant_unref (s_con);
+ return valid;
+}
+
+/**
+ * nm_connection_replace_settings:
+ * @connection: a #NMConnection
+ * @new_settings: a #GVariant of type %NM_VARIANT_TYPE_CONNECTION, with the new settings
+ * @error: location to store error, or %NULL
+ *
+ * Replaces @connection's settings with @new_settings (which must be
+ * syntactically valid, and describe a known type of connection, but does not
+ * need to result in a connection that passes nm_connection_verify()).
+ *
+ * Returns: %TRUE if connection was updated, %FALSE if @new_settings could not
+ * be deserialized (in which case @connection will be unchanged).
+ **/
+gboolean
+nm_connection_replace_settings (NMConnection *connection,
+ GVariant *new_settings,
+ GError **error)
+{
+ NMConnectionPrivate *priv;
+ GVariantIter iter;
+ const char *setting_name;
+ GVariant *setting_dict;
+ GSList *settings = NULL, *s;
+ gboolean changed;
+
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
+ g_return_val_if_fail (g_variant_is_of_type (new_settings, NM_VARIANT_TYPE_CONNECTION), FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ priv = NM_CONNECTION_GET_PRIVATE (connection);
+
+ if (!validate_permissions_type (new_settings, error))
+ return FALSE;
+
+ g_variant_iter_init (&iter, new_settings);
+ while (g_variant_iter_next (&iter, "{&s@a{sv}}", &setting_name, &setting_dict)) {
+ NMSetting *setting;
+ GType type;
+
+ type = nm_setting_lookup_type (setting_name);
+ if (type == G_TYPE_INVALID) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_SETTING,
+ _("unknown setting name"));
+ g_prefix_error (error, "%s: ", setting_name);
+ g_variant_unref (setting_dict);
+ g_slist_free_full (settings, g_object_unref);
+ return FALSE;
+ }
+
+ setting = _nm_setting_new_from_dbus (type, setting_dict, new_settings, error);
+ g_variant_unref (setting_dict);
+
+ if (!setting) {
+ g_slist_free_full (settings, g_object_unref);
+ return FALSE;
+ }
+
+ settings = g_slist_prepend (settings, setting);
+ }
+
+ if (g_hash_table_size (priv->settings) > 0) {
+ g_hash_table_foreach_remove (priv->settings, _setting_release, connection);
+ changed = TRUE;
+ } else
+ changed = (settings != NULL);
+
+ for (s = settings; s; s = s->next)
+ _nm_connection_add_setting (connection, s->data);
+
+ if (changed)
+ g_signal_emit (connection, signals[CHANGED], 0);
+ return TRUE;
+}
+
+/**
+ * nm_connection_replace_settings_from_connection:
+ * @connection: a #NMConnection
+ * @new_connection: a #NMConnection to replace the settings of @connection with
+ *
+ * Deep-copies the settings of @new_connection and replaces the settings of @connection
+ * with the copied settings.
+ **/
+void
+nm_connection_replace_settings_from_connection (NMConnection *connection,
+ NMConnection *new_connection)
+{
+ NMConnectionPrivate *priv, *new_priv;
+ GHashTableIter iter;
+ NMSetting *setting;
+ gboolean changed;
+
+ g_return_if_fail (NM_IS_CONNECTION (connection));
+ g_return_if_fail (NM_IS_CONNECTION (new_connection));
+
+ /* When 'connection' and 'new_connection' are the same object simply return
+ * in order not to destroy 'connection'.
+ */
+ if (connection == new_connection)
+ return;
+
+ /* No need to validate permissions like nm_connection_replace_settings()
+ * since we're dealing with an NMConnection which has already done that.
+ */
+
+ priv = NM_CONNECTION_GET_PRIVATE (connection);
+ new_priv = NM_CONNECTION_GET_PRIVATE (new_connection);
+
+ if ((changed = g_hash_table_size (priv->settings) > 0))
+ g_hash_table_foreach_remove (priv->settings, _setting_release, connection);
+
+ if (g_hash_table_size (new_priv->settings)) {
+ g_hash_table_iter_init (&iter, new_priv->settings);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer) &setting))
+ _nm_connection_add_setting (connection, nm_setting_duplicate (setting));
+ changed = TRUE;
+ }
+
+ if (changed)
+ g_signal_emit (connection, signals[CHANGED], 0);
+}
+
+/**
+ * nm_connection_clear_settings:
+ * @connection: a #NMConnection
+ *
+ * Deletes all of @connection's settings.
+ **/
+void
+nm_connection_clear_settings (NMConnection *connection)
+{
+ NMConnectionPrivate *priv;
+
+ g_return_if_fail (NM_IS_CONNECTION (connection));
+
+ priv = NM_CONNECTION_GET_PRIVATE (connection);
+
+ if (g_hash_table_size (priv->settings) > 0) {
+ g_hash_table_foreach_remove (priv->settings, _setting_release, connection);
+ g_signal_emit (connection, signals[CHANGED], 0);
+ }
+}
+
+/**
+ * nm_connection_compare:
+ * @a: a #NMConnection
+ * @b: a second #NMConnection to compare with the first
+ * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT
+ *
+ * Compares two #NMConnection objects for similarity, with comparison behavior
+ * modified by a set of flags. See nm_setting_compare() for a description of
+ * each flag's behavior.
+ *
+ * Returns: %TRUE if the comparison succeeds, %FALSE if it does not
+ **/
+gboolean
+nm_connection_compare (NMConnection *a,
+ NMConnection *b,
+ NMSettingCompareFlags flags)
+{
+ GHashTableIter iter;
+ NMSetting *src;
+
+ if (a == b)
+ return TRUE;
+ if (!a || !b)
+ return FALSE;
+
+ /* B / A: ensure settings in B that are not in A make the comparison fail */
+ if (g_hash_table_size (NM_CONNECTION_GET_PRIVATE (a)->settings) !=
+ g_hash_table_size (NM_CONNECTION_GET_PRIVATE (b)->settings))
+ return FALSE;
+
+ /* A / B: ensure all settings in A match corresponding ones in B */
+ g_hash_table_iter_init (&iter, NM_CONNECTION_GET_PRIVATE (a)->settings);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer) &src)) {
+ NMSetting *cmp = nm_connection_get_setting (b, G_OBJECT_TYPE (src));
+
+ if (!cmp || !nm_setting_compare (src, cmp, flags))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+static void
+diff_one_connection (NMConnection *a,
+ NMConnection *b,
+ NMSettingCompareFlags flags,
+ gboolean invert_results,
+ GHashTable *diffs)
+{
+ NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (a);
+ GHashTableIter iter;
+ NMSetting *a_setting = NULL;
+
+ g_hash_table_iter_init (&iter, priv->settings);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer) &a_setting)) {
+ NMSetting *b_setting = NULL;
+ const char *setting_name = nm_setting_get_name (a_setting);
+ GHashTable *results;
+ gboolean new_results = TRUE;
+
+ if (b)
+ b_setting = nm_connection_get_setting (b, G_OBJECT_TYPE (a_setting));
+
+ results = g_hash_table_lookup (diffs, setting_name);
+ if (results)
+ new_results = FALSE;
+
+ if (!nm_setting_diff (a_setting, b_setting, flags, invert_results, &results)) {
+ if (new_results)
+ g_hash_table_insert (diffs, g_strdup (setting_name), results);
+ }
+ }
+}
+
+/**
+ * nm_connection_diff:
+ * @a: a #NMConnection
+ * @b: a second #NMConnection to compare with the first
+ * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT
+ * @out_settings: (element-type utf8 GLib.HashTable): if the
+ * connections differ, on return a hash table mapping setting names to
+ * second-level GHashTable (utf8 to guint32), which contains the key names that
+ * differ mapped to one or more of %NMSettingDiffResult as a bitfield
+ *
+ * Compares two #NMConnection objects for similarity, with comparison behavior
+ * modified by a set of flags. See nm_setting_compare() for a description of
+ * each flag's behavior. If the connections differ, settings and keys within
+ * each setting that differ are added to the returned @out_settings hash table.
+ * No values are returned, only key names.
+ *
+ * Returns: %TRUE if the connections contain the same values, %FALSE if they do
+ * not
+ **/
+gboolean
+nm_connection_diff (NMConnection *a,
+ NMConnection *b,
+ NMSettingCompareFlags flags,
+ GHashTable **out_settings)
+{
+ GHashTable *diffs;
+
+ g_return_val_if_fail (NM_IS_CONNECTION (a), FALSE);
+ g_return_val_if_fail (out_settings != NULL, FALSE);
+ g_return_val_if_fail (*out_settings == NULL, FALSE);
+ if (b)
+ g_return_val_if_fail (NM_IS_CONNECTION (b), FALSE);
+
+ if (a == b)
+ return TRUE;
+
+ diffs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_hash_table_destroy);
+
+ /* Diff A to B, then B to A to capture keys in B that aren't in A */
+ diff_one_connection (a, b, flags, FALSE, diffs);
+ if (b)
+ diff_one_connection (b, a, flags, TRUE, diffs);
+
+ if (g_hash_table_size (diffs) == 0)
+ g_hash_table_destroy (diffs);
+ else
+ *out_settings = diffs;
+
+ return *out_settings ? FALSE : TRUE;
+}
+
+NMSetting *
+_nm_connection_find_base_type_setting (NMConnection *connection)
+{
+ NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (connection);
+ GHashTableIter iter;
+ NMSetting *setting = NULL, *s_iter;
+
+ g_hash_table_iter_init (&iter, priv->settings);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &s_iter)) {
+ if (!_nm_setting_is_base_type (s_iter))
+ continue;
+
+ if (setting) {
+ /* FIXME: currently, if there is more than one matching base type,
+ * we cannot detect the base setting.
+ * See: https://bugzilla.gnome.org/show_bug.cgi?id=696936#c8 */
+ return NULL;
+ }
+ setting = s_iter;
+ }
+ return setting;
+}
+
+static gboolean
+_normalize_connection_uuid (NMConnection *self)
+{
+ NMSettingConnection *s_con = nm_connection_get_setting_connection (self);
+ char *uuid;
+
+ g_assert (s_con);
+
+ if (nm_setting_connection_get_uuid (s_con))
+ return FALSE;
+
+ uuid = nm_utils_uuid_generate ();
+ g_object_set (s_con, NM_SETTING_CONNECTION_UUID, uuid, NULL);
+ g_free (uuid);
+
+ return TRUE;
+}
+
+static gboolean
+_normalize_connection_type (NMConnection *self)
+{
+ NMSettingConnection *s_con = nm_connection_get_setting_connection (self);
+ NMSetting *s_base = NULL;
+ const char *type;
+
+ type = nm_setting_connection_get_connection_type (s_con);
+
+ if (type) {
+ s_base = nm_connection_get_setting_by_name (self, type);
+
+ if (!s_base) {
+ GType base_type = nm_setting_lookup_type (type);
+
+ g_return_val_if_fail (base_type, FALSE);
+ nm_connection_add_setting (self, g_object_new (base_type, NULL));
+ return TRUE;
+ }
+ } else {
+ s_base = _nm_connection_find_base_type_setting (self);
+ g_return_val_if_fail (s_base, FALSE);
+
+ type = nm_setting_get_name (s_base);
+ g_object_set (s_con, NM_SETTING_CONNECTION_TYPE, type, NULL);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+const char *
+_nm_connection_detect_slave_type (NMConnection *connection, NMSetting **out_s_port)
+{
+ NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (connection);
+ GHashTableIter iter;
+ const char *slave_type = NULL;
+ NMSetting *s_port = NULL, *s_iter;
+
+ g_hash_table_iter_init (&iter, priv->settings);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &s_iter)) {
+ const char *name = nm_setting_get_name (s_iter);
+ const char *i_slave_type = NULL;
+
+ if (!strcmp (name, NM_SETTING_BRIDGE_PORT_SETTING_NAME))
+ i_slave_type = NM_SETTING_BRIDGE_SETTING_NAME;
+ else if (!strcmp (name, NM_SETTING_TEAM_PORT_SETTING_NAME))
+ i_slave_type = NM_SETTING_TEAM_SETTING_NAME;
+ else
+ continue;
+
+ if (slave_type) {
+ /* there are more then one matching port types, cannot detect the slave type. */
+ slave_type = NULL;
+ s_port = NULL;
+ break;
+ }
+ slave_type = i_slave_type;
+ s_port = s_iter;
+ }
+
+ if (out_s_port)
+ *out_s_port = s_port;
+ return slave_type;
+}
+
+static gboolean
+_normalize_connection_slave_type (NMConnection *self)
+{
+ NMSettingConnection *s_con = nm_connection_get_setting_connection (self);
+ const char *slave_type, *port_type;
+
+ if (!s_con)
+ return FALSE;
+ if (!nm_setting_connection_get_master (s_con))
+ return FALSE;
+
+ slave_type = nm_setting_connection_get_slave_type (s_con);
+ if (slave_type) {
+ if ( _nm_setting_slave_type_is_valid (slave_type, &port_type)
+ && port_type) {
+ NMSetting *s_port;
+
+ s_port = nm_connection_get_setting_by_name (self, port_type);
+ if (!s_port) {
+ GType p_type = nm_setting_lookup_type (port_type);
+
+ g_return_val_if_fail (p_type, FALSE);
+ nm_connection_add_setting (self, g_object_new (p_type, NULL));
+ return TRUE;
+ }
+ }
+ } else {
+ if ((slave_type = _nm_connection_detect_slave_type (self, NULL))) {
+ g_object_set (s_con, NM_SETTING_CONNECTION_SLAVE_TYPE, slave_type, NULL);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static gboolean
+_normalize_ip_config (NMConnection *self, GHashTable *parameters)
+{
+ NMSettingConnection *s_con = nm_connection_get_setting_connection (self);
+ const char *default_ip4_method = NM_SETTING_IP4_CONFIG_METHOD_AUTO;
+ const char *default_ip6_method = NULL;
+ NMSettingIPConfig *s_ip4, *s_ip6;
+ NMSetting *setting;
+
+ if (parameters)
+ default_ip6_method = g_hash_table_lookup (parameters, NM_CONNECTION_NORMALIZE_PARAM_IP6_CONFIG_METHOD);
+ if (!default_ip6_method)
+ default_ip6_method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
+
+ s_ip4 = nm_connection_get_setting_ip4_config (self);
+ s_ip6 = nm_connection_get_setting_ip6_config (self);
+
+ if (nm_setting_connection_get_master (s_con)) {
+ /* 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);
+
+ return s_ip4 || s_ip6;
+ } 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 (!s_ip4) {
+ 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);
+ }
+ if (!s_ip6) {
+ setting = nm_setting_ip6_config_new ();
+
+ g_object_set (setting,
+ NM_SETTING_IP_CONFIG_METHOD, default_ip6_method,
+ NM_SETTING_IP_CONFIG_MAY_FAIL, TRUE,
+ NULL);
+ nm_connection_add_setting (self, setting);
+ }
+ return !s_ip4 || !s_ip6;
+ }
+}
+
+static gboolean
+_normalize_infiniband_mtu (NMConnection *self, GHashTable *parameters)
+{
+ NMSettingInfiniband *s_infini = nm_connection_get_setting_infiniband (self);
+
+ if (s_infini) {
+ const char *transport_mode = nm_setting_infiniband_get_transport_mode (s_infini);
+ guint32 max_mtu = 0;
+
+ if (transport_mode) {
+ if (!strcmp (transport_mode, "datagram"))
+ max_mtu = 2044;
+ else if (!strcmp (transport_mode, "connected"))
+ max_mtu = 65520;
+
+ if (max_mtu && nm_setting_infiniband_get_mtu (s_infini) > max_mtu) {
+ g_object_set (s_infini, NM_SETTING_INFINIBAND_MTU, max_mtu, NULL);
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * nm_connection_verify:
+ * @connection: the #NMConnection to verify
+ * @error: location to store error, or %NULL
+ *
+ * Validates the connection and all its settings. Each setting's properties
+ * have allowed values, and some values are dependent on other values. For
+ * example, if a Wi-Fi connection is security enabled, the #NMSettingWireless
+ * setting object's 'security' property must contain the setting name of the
+ * #NMSettingWirelessSecurity object, which must also be present in the
+ * connection for the connection to be valid. As another example, the
+ * #NMSettingWired object's 'mac-address' property must be a validly formatted
+ * MAC address. The returned #GError contains information about which
+ * setting and which property failed validation, and how it failed validation.
+ *
+ * Returns: %TRUE if the connection is valid, %FALSE if it is not
+ **/
+gboolean
+nm_connection_verify (NMConnection *connection, GError **error)
+{
+ NMSettingVerifyResult result;
+
+ result = _nm_connection_verify (connection, error);
+
+ /* we treat normalizable connections as valid. */
+ if (result == NM_SETTING_VERIFY_NORMALIZABLE)
+ g_clear_error (error);
+
+ return result == NM_SETTING_VERIFY_SUCCESS || result == NM_SETTING_VERIFY_NORMALIZABLE;
+}
+
+static NMSettingVerifyResult
+_nm_connection_verify (NMConnection *connection, GError **error)
+{
+ NMConnectionPrivate *priv;
+ NMSettingConnection *s_con;
+ NMSettingIPConfig *s_ip4, *s_ip6;
+ GHashTableIter iter;
+ gpointer value;
+ GSList *all_settings = NULL, *setting_i;
+ NMSettingVerifyResult success = NM_SETTING_VERIFY_ERROR;
+ GError *normalizable_error = NULL;
+ NMSettingVerifyResult normalizable_error_type = NM_SETTING_VERIFY_SUCCESS;
+
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NM_SETTING_VERIFY_ERROR);
+ g_return_val_if_fail (!error || !*error, NM_SETTING_VERIFY_ERROR);
+
+ priv = NM_CONNECTION_GET_PRIVATE (connection);
+
+ /* First, make sure there's at least 'connection' setting */
+ s_con = nm_connection_get_setting_connection (connection);
+ if (!s_con) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_SETTING,
+ _("setting not found"));
+ g_prefix_error (error, "%s: ", NM_SETTING_CONNECTION_SETTING_NAME);
+ goto EXIT;
+ }
+
+ /* Build up the list of settings */
+ g_hash_table_iter_init (&iter, priv->settings);
+ while (g_hash_table_iter_next (&iter, NULL, &value)) {
+ /* Order NMSettingConnection so that it will be verified first.
+ * The reason is, that errors in this setting might be more fundamental
+ * and should be checked and reported with higher priority.
+ */
+ if (value == s_con)
+ all_settings = g_slist_append (all_settings, value);
+ else
+ all_settings = g_slist_prepend (all_settings, value);
+ }
+ all_settings = g_slist_reverse (all_settings);
+
+ /* Now, run the verify function of each setting */
+ for (setting_i = all_settings; setting_i; setting_i = setting_i->next) {
+ GError *verify_error = NULL;
+ NMSettingVerifyResult verify_result;
+
+ /* verify all settings. We stop if we find the first non-normalizable
+ * @NM_SETTING_VERIFY_ERROR. If we find normalizable errors we continue
+ * but remember the error to return it to the user.
+ * @NM_SETTING_VERIFY_NORMALIZABLE_ERROR has a higher priority then
+ * @NM_SETTING_VERIFY_NORMALIZABLE, so, if we encounter such an error type,
+ * we remember it instead (to return it as output).
+ **/
+ verify_result = _nm_setting_verify (NM_SETTING (setting_i->data), connection, &verify_error);
+ if (verify_result == NM_SETTING_VERIFY_NORMALIZABLE ||
+ verify_result == NM_SETTING_VERIFY_NORMALIZABLE_ERROR) {
+ if ( verify_result == NM_SETTING_VERIFY_NORMALIZABLE_ERROR
+ && normalizable_error_type == NM_SETTING_VERIFY_NORMALIZABLE) {
+ /* NORMALIZABLE_ERROR has higher priority. */
+ g_clear_error (&normalizable_error);
+ }
+ if (!normalizable_error) {
+ g_propagate_error (&normalizable_error, verify_error);
+ verify_error = NULL;
+ normalizable_error_type = verify_result;
+ }
+ } else if (verify_result != NM_SETTING_VERIFY_SUCCESS) {
+ g_propagate_error (error, verify_error);
+ g_slist_free (all_settings);
+ g_return_val_if_fail (verify_result == NM_SETTING_VERIFY_ERROR, success);
+ goto EXIT;
+ }
+ g_clear_error (&verify_error);
+ }
+ g_slist_free (all_settings);
+
+ s_ip4 = nm_connection_get_setting_ip4_config (connection);
+ s_ip6 = nm_connection_get_setting_ip6_config (connection);
+
+ if (nm_setting_connection_get_master (s_con)) {
+ if ((normalizable_error_type == NM_SETTING_VERIFY_SUCCESS ||
+ (normalizable_error_type == NM_SETTING_VERIFY_NORMALIZABLE)) && (s_ip4 || 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: ",
+ s_ip4 ? NM_SETTING_IP4_CONFIG_SETTING_NAME : 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;
+ }
+ } else {
+ if (normalizable_error_type == NM_SETTING_VERIFY_SUCCESS && (!s_ip4 || !s_ip6)) {
+ 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 : 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;
+ }
+ }
+
+ if (normalizable_error_type != NM_SETTING_VERIFY_SUCCESS) {
+ g_propagate_error (error, normalizable_error);
+ normalizable_error = NULL;
+ success = normalizable_error_type;
+ } else
+ success = NM_SETTING_VERIFY_SUCCESS;
+
+EXIT:
+ g_clear_error (&normalizable_error);
+ return success;
+}
+
+/**
+ * nm_connection_normalize:
+ * @connection: the #NMConnection to normalize
+ * @parameters: (allow-none) (element-type utf8 gpointer): a #GHashTable with
+ * normalization parameters to allow customization of the normalization by providing
+ * specific arguments. Unknown arguments will be ignored and the default will be
+ * used. The keys must be strings, hashed by g_str_hash() and g_str_equal() functions.
+ * The values are opaque and depend on the parameter name.
+ * @modified: (out) (allow-none): outputs whether any settings were modified.
+ * @error: location to store error, or %NULL. Contains the reason,
+ * why the connection is invalid, if the function returns an error.
+ *
+ * Does some basic normalization and fixup of well known inconsistencies
+ * and deprecated fields. If the connection was modified in any way,
+ * the output parameter @modified is set %TRUE.
+ *
+ * Finally the connection will be verified and %TRUE returns if the connection
+ * is valid. As this function only performs some specific normalization steps
+ * it cannot repair all connections. If the connection has errors that
+ * cannot be normalized, the connection will not be modified.
+ *
+ * Returns: %TRUE if the connection is valid, %FALSE if it is not
+ **/
+gboolean
+nm_connection_normalize (NMConnection *connection,
+ GHashTable *parameters,
+ gboolean *modified,
+ GError **error)
+{
+ NMSettingVerifyResult success;
+ gboolean was_modified = FALSE;
+ GError *normalizable_error = NULL;
+
+ success = _nm_connection_verify (connection, &normalizable_error);
+
+ if (success == NM_SETTING_VERIFY_ERROR ||
+ success == NM_SETTING_VERIFY_SUCCESS) {
+ if (normalizable_error)
+ g_propagate_error (error, normalizable_error);
+ if (modified)
+ *modified = FALSE;
+ if (success == NM_SETTING_VERIFY_ERROR && error && !*error) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_FAILED,
+ _("Unexpected failure to verify the connection"));
+ g_return_val_if_reached (FALSE);
+ }
+ return success == NM_SETTING_VERIFY_SUCCESS;
+ }
+ g_assert (success == NM_SETTING_VERIFY_NORMALIZABLE || success == NM_SETTING_VERIFY_NORMALIZABLE_ERROR);
+ g_clear_error (&normalizable_error);
+
+ /* Try to perform all kind of normalizations on the settings to fix it.
+ * We only do this, after verifying that the connection contains no un-normalizable
+ * errors, because in that case we rather fail without touching the settings. */
+
+ was_modified |= _normalize_connection_uuid (connection);
+ was_modified |= _normalize_connection_type (connection);
+ was_modified |= _normalize_connection_slave_type (connection);
+ was_modified |= _normalize_ip_config (connection, parameters);
+ was_modified |= _normalize_infiniband_mtu (connection, parameters);
+
+ /* Verify anew. */
+ success = _nm_connection_verify (connection, error);
+
+ if (modified)
+ *modified = was_modified;
+
+ if (success != NM_SETTING_VERIFY_SUCCESS) {
+ /* we would expect, that after normalization, the connection can be verified.
+ * Also treat NM_SETTING_VERIFY_NORMALIZABLE as failure, because there is something
+ * odd going on. */
+ if (error && !*error) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_FAILED,
+ _("Unexpected failure to normalize the connection"));
+ }
+ g_return_val_if_reached (FALSE);
+ }
+
+ /* we would expect, that the connection was modified during normalization. */
+ g_return_val_if_fail (was_modified, TRUE);
+
+ return TRUE;
+}
+
+/**
+ * nm_connection_update_secrets:
+ * @connection: the #NMConnection
+ * @setting_name: the setting object name to which the secrets apply
+ * @secrets: a #GVariant of secrets, of type %NM_VARIANT_TYPE_CONNECTION
+ * or %NM_VARIANT_TYPE_SETTING
+ * @error: location to store error, or %NULL
+ *
+ * Update the specified setting's secrets, given a dictionary of secrets
+ * intended for that setting (deserialized from D-Bus for example). Will also
+ * extract the given setting's secrets hash if given a connection dictionary.
+ * If @setting_name is %NULL, expects a fully serialized #NMConnection as
+ * returned by nm_connection_to_dbus() and will update all secrets from all
+ * settings contained in @secrets.
+ *
+ * Returns: %TRUE if the secrets were successfully updated, %FALSE if the update
+ * failed (tried to update secrets for a setting that doesn't exist, etc)
+ **/
+gboolean
+nm_connection_update_secrets (NMConnection *connection,
+ const char *setting_name,
+ GVariant *secrets,
+ GError **error)
+{
+ NMSetting *setting;
+ gboolean success = TRUE, updated = FALSE;
+ GVariant *setting_dict = NULL;
+ GVariantIter iter;
+ const char *key;
+ gboolean full_connection;
+ int success_detail;
+
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
+ g_return_val_if_fail ( g_variant_is_of_type (secrets, NM_VARIANT_TYPE_SETTING)
+ || g_variant_is_of_type (secrets, NM_VARIANT_TYPE_CONNECTION), FALSE);
+ if (error)
+ g_return_val_if_fail (*error == NULL, FALSE);
+
+ full_connection = g_variant_is_of_type (secrets, NM_VARIANT_TYPE_CONNECTION);
+ g_return_val_if_fail (setting_name != NULL || full_connection, FALSE);
+
+ /* Empty @secrets means success */
+ if (g_variant_n_children (secrets) == 0)
+ return TRUE;
+
+ if (setting_name) {
+ /* Update just one setting's secrets */
+ setting = nm_connection_get_setting_by_name (connection, setting_name);
+ if (!setting) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_SETTING_NOT_FOUND,
+ setting_name);
+ return FALSE;
+ }
+
+ if (full_connection) {
+ setting_dict = g_variant_lookup_value (secrets, setting_name, NM_VARIANT_TYPE_SETTING);
+ if (!setting_dict) {
+ /* The connection dictionary didn't contain any secrets for
+ * @setting_name; just return success.
+ */
+ return TRUE;
+ }
+ }
+
+ g_signal_handlers_block_by_func (setting, (GCallback) setting_changed_cb, connection);
+ success_detail = _nm_setting_update_secrets (setting,
+ setting_dict ? setting_dict : secrets,
+ error);
+ g_signal_handlers_unblock_by_func (setting, (GCallback) setting_changed_cb, connection);
+
+ g_clear_pointer (&setting_dict, g_variant_unref);
+
+ if (success_detail == NM_SETTING_UPDATE_SECRET_ERROR)
+ return FALSE;
+ if (success_detail == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED)
+ updated = TRUE;
+ } else {
+ /* check first, whether all the settings exist... */
+ g_variant_iter_init (&iter, secrets);
+ while (g_variant_iter_next (&iter, "{&s@a{sv}}", &key, NULL)) {
+ setting = nm_connection_get_setting_by_name (connection, key);
+ if (!setting) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_SETTING_NOT_FOUND,
+ key);
+ return FALSE;
+ }
+ }
+
+ /* Update each setting with any secrets from the connection dictionary */
+ g_variant_iter_init (&iter, secrets);
+ while (g_variant_iter_next (&iter, "{&s@a{sv}}", &key, &setting_dict)) {
+ /* Update the secrets for this setting */
+ setting = nm_connection_get_setting_by_name (connection, key);
+
+ g_signal_handlers_block_by_func (setting, (GCallback) setting_changed_cb, connection);
+ success_detail = _nm_setting_update_secrets (setting, setting_dict, error);
+ g_signal_handlers_unblock_by_func (setting, (GCallback) setting_changed_cb, connection);
+
+ g_variant_unref (setting_dict);
+
+ if (success_detail == NM_SETTING_UPDATE_SECRET_ERROR) {
+ success = FALSE;
+ break;
+ }
+ if (success_detail == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED)
+ updated = TRUE;
+ }
+ }
+
+ if (updated) {
+ g_signal_emit (connection, signals[SECRETS_UPDATED], 0, setting_name);
+ g_signal_emit (connection, signals[CHANGED], 0);
+ }
+
+ return success;
+}
+
+/**
+ * nm_connection_need_secrets:
+ * @connection: the #NMConnection
+ * @hints: (out) (element-type utf8) (allow-none) (transfer container):
+ * the address of a pointer to a #GPtrArray, initialized to %NULL, which on
+ * return points to an allocated #GPtrArray containing the property names of
+ * secrets of the #NMSetting which may be required; the caller owns the array
+ * and must free the array itself with g_ptr_array_free(), but not free its
+ * elements
+ *
+ * Returns the name of the first setting object in the connection which would
+ * need secrets to make a successful connection. The returned hints are only
+ * intended as a guide to what secrets may be required, because in some
+ * circumstances, there is no way to conclusively determine exactly which
+ * secrets are needed.
+ *
+ * Returns: the setting name of the #NMSetting object which has invalid or
+ * missing secrets
+ **/
+const char *
+nm_connection_need_secrets (NMConnection *connection,
+ GPtrArray **hints)
+{
+ NMConnectionPrivate *priv;
+ GHashTableIter hiter;
+ GSList *settings = NULL;
+ GSList *iter;
+ const char *name = NULL;
+ NMSetting *setting;
+
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+ if (hints)
+ g_return_val_if_fail (*hints == NULL, NULL);
+
+ priv = NM_CONNECTION_GET_PRIVATE (connection);
+
+ /* Get list of settings in priority order */
+ g_hash_table_iter_init (&hiter, priv->settings);
+ while (g_hash_table_iter_next (&hiter, NULL, (gpointer) &setting))
+ settings = g_slist_insert_sorted (settings, setting, _nm_setting_compare_priority);
+
+ for (iter = settings; iter; iter = g_slist_next (iter)) {
+ GPtrArray *secrets;
+
+ setting = NM_SETTING (iter->data);
+ secrets = _nm_setting_need_secrets (setting);
+ if (secrets) {
+ if (hints)
+ *hints = secrets;
+ else
+ g_ptr_array_free (secrets, TRUE);
+
+ name = nm_setting_get_name (setting);
+ break;
+ }
+ }
+
+ g_slist_free (settings);
+ return name;
+}
+
+/**
+ * nm_connection_clear_secrets:
+ * @connection: the #NMConnection
+ *
+ * Clears and frees any secrets that may be stored in the connection, to avoid
+ * keeping secret data in memory when not needed.
+ **/
+void
+nm_connection_clear_secrets (NMConnection *connection)
+{
+ GHashTableIter iter;
+ NMSetting *setting;
+ gboolean changed = FALSE;
+
+ g_return_if_fail (NM_IS_CONNECTION (connection));
+
+ g_hash_table_iter_init (&iter, NM_CONNECTION_GET_PRIVATE (connection)->settings);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer) &setting)) {
+ g_signal_handlers_block_by_func (setting, (GCallback) setting_changed_cb, connection);
+ changed |= _nm_setting_clear_secrets (setting);
+ g_signal_handlers_unblock_by_func (setting, (GCallback) setting_changed_cb, connection);
+ }
+
+ g_signal_emit (connection, signals[SECRETS_CLEARED], 0);
+ if (changed)
+ g_signal_emit (connection, signals[CHANGED], 0);
+}
+
+/**
+ * nm_connection_clear_secrets_with_flags:
+ * @connection: the #NMConnection
+ * @func: (scope call): function to be called to determine whether a
+ * specific secret should be cleared or not
+ * @user_data: caller-supplied data passed to @func
+ *
+ * Clears and frees secrets determined by @func.
+ **/
+void
+nm_connection_clear_secrets_with_flags (NMConnection *connection,
+ NMSettingClearSecretsWithFlagsFn func,
+ gpointer user_data)
+{
+ GHashTableIter iter;
+ NMSetting *setting;
+ gboolean changed = FALSE;
+
+ g_return_if_fail (NM_IS_CONNECTION (connection));
+
+ g_hash_table_iter_init (&iter, NM_CONNECTION_GET_PRIVATE (connection)->settings);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer) &setting)) {
+ g_signal_handlers_block_by_func (setting, (GCallback) setting_changed_cb, connection);
+ changed |= _nm_setting_clear_secrets_with_flags (setting, func, user_data);
+ g_signal_handlers_unblock_by_func (setting, (GCallback) setting_changed_cb, connection);
+ }
+
+ g_signal_emit (connection, signals[SECRETS_CLEARED], 0);
+ if (changed)
+ g_signal_emit (connection, signals[CHANGED], 0);
+}
+
+/**
+ * nm_connection_to_dbus:
+ * @connection: the #NMConnection
+ * @flags: serialization flags, e.g. %NM_CONNECTION_SERIALIZE_ALL
+ *
+ * Converts the #NMConnection into a #GVariant of type
+ * %NM_VARIANT_TYPE_CONNECTION describing the connection, suitable for
+ * marshalling over D-Bus or otherwise serializing.
+ *
+ * Returns: (transfer none): a new floating #GVariant describing the connection,
+ * its settings, and each setting's properties.
+ **/
+GVariant *
+nm_connection_to_dbus (NMConnection *connection,
+ NMConnectionSerializationFlags flags)
+{
+ NMConnectionPrivate *priv;
+ GVariantBuilder builder;
+ GHashTableIter iter;
+ gpointer key, data;
+ GVariant *setting_dict, *ret;
+
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+ priv = NM_CONNECTION_GET_PRIVATE (connection);
+
+ g_variant_builder_init (&builder, NM_VARIANT_TYPE_CONNECTION);
+
+ /* Add each setting's hash to the main hash */
+ g_hash_table_iter_init (&iter, priv->settings);
+ while (g_hash_table_iter_next (&iter, &key, &data)) {
+ NMSetting *setting = NM_SETTING (data);
+
+ setting_dict = _nm_setting_to_dbus (setting, connection, flags);
+ if (setting_dict)
+ g_variant_builder_add (&builder, "{s@a{sv}}", nm_setting_get_name (setting), setting_dict);
+ }
+
+ ret = g_variant_builder_end (&builder);
+
+ /* Don't send empty hashes */
+ if (g_variant_n_children (ret) == 0) {
+ g_variant_unref (ret);
+ ret = NULL;
+ }
+
+ return ret;
+}
+
+/**
+ * nm_connection_is_type:
+ * @connection: the #NMConnection
+ * @type: a setting name to check the connection's type against (like
+ * %NM_SETTING_WIRELESS_SETTING_NAME or %NM_SETTING_WIRED_SETTING_NAME)
+ *
+ * A convenience function to check if the given @connection is a particular
+ * type (ie wired, Wi-Fi, ppp, etc). Checks the #NMSettingConnection:type
+ * property of the connection and matches that against @type.
+ *
+ * Returns: %TRUE if the connection is of the given @type, %FALSE if not
+ **/
+gboolean
+nm_connection_is_type (NMConnection *connection, const char *type)
+{
+ NMSettingConnection *s_con;
+ const char *type2;
+
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
+ g_return_val_if_fail (type != NULL, FALSE);
+
+ s_con = nm_connection_get_setting_connection (connection);
+ if (!s_con)
+ return FALSE;
+
+ type2 = nm_setting_connection_get_connection_type (s_con);
+
+ return (g_strcmp0 (type2, type) == 0);
+}
+
+/**
+ * nm_connection_for_each_setting_value:
+ * @connection: the #NMConnection
+ * @func: (scope call): user-supplied function called for each setting's property
+ * @user_data: user data passed to @func at each invocation
+ *
+ * Iterates over the properties of each #NMSetting object in the #NMConnection,
+ * calling the supplied user function for each property.
+ **/
+void
+nm_connection_for_each_setting_value (NMConnection *connection,
+ NMSettingValueIterFn func,
+ gpointer user_data)
+{
+ GHashTableIter iter;
+ gpointer value;
+
+ g_return_if_fail (NM_IS_CONNECTION (connection));
+ g_return_if_fail (func != NULL);
+
+ g_hash_table_iter_init (&iter, NM_CONNECTION_GET_PRIVATE (connection)->settings);
+ while (g_hash_table_iter_next (&iter, NULL, &value))
+ nm_setting_enumerate_values (NM_SETTING (value), func, user_data);
+}
+
+/**
+ * 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.
+ **/
+void
+nm_connection_dump (NMConnection *connection)
+{
+ GHashTableIter iter;
+ NMSetting *setting;
+ const char *setting_name;
+ char *str;
+
+ if (!connection)
+ return;
+
+ g_hash_table_iter_init (&iter, NM_CONNECTION_GET_PRIVATE (connection)->settings);
+ while (g_hash_table_iter_next (&iter, (gpointer) &setting_name, (gpointer) &setting)) {
+ str = nm_setting_to_string (setting);
+ g_print ("%s\n", str);
+ g_free (str);
+ }
+}
+
+/**
+ * nm_connection_set_path:
+ * @connection: the #NMConnection
+ * @path: the D-Bus path of the connection as given by the settings service
+ * which provides the connection
+ *
+ * Sets the D-Bus path of the connection. This property is not serialized, and
+ * is only for the reference of the caller. Sets the #NMConnection:path
+ * property.
+ **/
+void
+nm_connection_set_path (NMConnection *connection, const char *path)
+{
+ NMConnectionPrivate *priv;
+
+ g_return_if_fail (NM_IS_CONNECTION (connection));
+
+ priv = NM_CONNECTION_GET_PRIVATE (connection);
+
+ g_free (priv->path);
+ priv->path = NULL;
+
+ if (path)
+ priv->path = g_strdup (path);
+}
+
+/**
+ * nm_connection_get_path:
+ * @connection: the #NMConnection
+ *
+ * Returns the connection's D-Bus path.
+ *
+ * Returns: the D-Bus path of the connection, previously set by a call to
+ * nm_connection_set_path().
+ **/
+const char *
+nm_connection_get_path (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return NM_CONNECTION_GET_PRIVATE (connection)->path;
+}
+
+/**
+ * nm_connection_get_interface_name:
+ * @connection: The #NMConnection
+ *
+ * Returns the interface name as stored in NMSettingConnection:interface_name.
+ * If the connection contains no NMSettingConnection, it will return %NULL.
+ *
+ * For hardware devices and software devices created outside of NetworkManager,
+ * this name is used to match the device. for software devices created by
+ * NetworkManager, this is the name of the created interface.
+ *
+ * Returns: Name of the kernel interface or %NULL
+ */
+const char *
+nm_connection_get_interface_name (NMConnection *connection)
+{
+ NMSettingConnection *s_con;
+
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ s_con = nm_connection_get_setting_connection (connection);
+
+ return s_con ? nm_setting_connection_get_interface_name (s_con) : NULL;
+}
+
+gboolean
+_nm_connection_verify_required_interface_name (NMConnection *connection,
+ GError **error)
+{
+ const char *interface_name;
+
+ interface_name = nm_connection_get_interface_name (connection);
+ if (interface_name)
+ return TRUE;
+
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME);
+ return FALSE;
+}
+
+/**
+ * nm_connection_get_uuid:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return the UUID from the connection's #NMSettingConnection.
+ *
+ * Returns: the UUID from the connection's 'connection' setting
+ **/
+const char *
+nm_connection_get_uuid (NMConnection *connection)
+{
+ NMSettingConnection *s_con;
+
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_return_val_if_fail (s_con != NULL, NULL);
+
+ return nm_setting_connection_get_uuid (s_con);
+}
+
+/**
+ * nm_connection_get_id:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return the ID from the connection's #NMSettingConnection.
+ *
+ * Returns: the ID from the connection's 'connection' setting
+ **/
+const char *
+nm_connection_get_id (NMConnection *connection)
+{
+ NMSettingConnection *s_con;
+
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_return_val_if_fail (s_con != NULL, NULL);
+
+ return nm_setting_connection_get_id (s_con);
+}
+
+/**
+ * nm_connection_get_connection_type:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return the type from the connection's #NMSettingConnection.
+ *
+ * Returns: the type from the connection's 'connection' setting
+ **/
+const char *
+nm_connection_get_connection_type (NMConnection *connection)
+{
+ NMSettingConnection *s_con;
+
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_return_val_if_fail (s_con != NULL, NULL);
+
+ return nm_setting_connection_get_connection_type (s_con);
+}
+
+/**
+ * nm_connection_is_virtual:
+ * @connection: an #NMConnection
+ *
+ * Checks if @connection refers to a virtual device (and thus can potentially be
+ * activated even if the device it refers to doesn't exist).
+ *
+ * Returns: whether @connection refers to a virtual device
+ */
+gboolean
+nm_connection_is_virtual (NMConnection *connection)
+{
+ const char *type;
+
+ type = nm_connection_get_connection_type (connection);
+ g_return_val_if_fail (type != NULL, FALSE);
+
+ if ( !strcmp (type, NM_SETTING_BOND_SETTING_NAME)
+ || !strcmp (type, NM_SETTING_TEAM_SETTING_NAME)
+ || !strcmp (type, NM_SETTING_BRIDGE_SETTING_NAME)
+ || !strcmp (type, NM_SETTING_VLAN_SETTING_NAME))
+ return TRUE;
+
+ if (!strcmp (type, NM_SETTING_INFINIBAND_SETTING_NAME)) {
+ NMSettingInfiniband *s_ib;
+
+ s_ib = nm_connection_get_setting_infiniband (connection);
+ g_return_val_if_fail (s_ib != NULL, FALSE);
+ return nm_setting_infiniband_get_virtual_interface_name (s_ib) != NULL;
+ }
+
+ return FALSE;
+}
+
+/**
+ * nm_connection_get_virtual_device_description:
+ * @connection: an #NMConnection for a virtual device type
+ *
+ * Returns the name that nm_device_disambiguate_names() would
+ * return for the virtual device that would be created for @connection.
+ * Eg, "VLAN (eth1.1)".
+ *
+ * Returns: (transfer full): the name of @connection's device,
+ * or %NULL if @connection is not a virtual connection type
+ */
+char *
+nm_connection_get_virtual_device_description (NMConnection *connection)
+{
+ const char *type;
+ const char *iface = NULL, *display_type = NULL;
+
+ iface = nm_connection_get_interface_name (connection);
+
+ type = nm_connection_get_connection_type (connection);
+ g_return_val_if_fail (type != NULL, FALSE);
+
+ if (!strcmp (type, NM_SETTING_BOND_SETTING_NAME))
+ display_type = _("Bond");
+ else if (!strcmp (type, NM_SETTING_TEAM_SETTING_NAME))
+ display_type = _("Team");
+ else if (!strcmp (type, NM_SETTING_BRIDGE_SETTING_NAME))
+ display_type = _("Bridge");
+ else if (!strcmp (type, NM_SETTING_VLAN_SETTING_NAME))
+ display_type = _("VLAN");
+ else if (!strcmp (type, NM_SETTING_INFINIBAND_SETTING_NAME)) {
+ display_type = _("InfiniBand");
+ iface = nm_setting_infiniband_get_virtual_interface_name (nm_connection_get_setting_infiniband (connection));
+ }
+
+ if (!iface || !display_type)
+ return NULL;
+
+ return g_strdup_printf ("%s (%s)", display_type, iface);
+}
+
+/*************************************************************/
+
+/**
+ * nm_connection_get_setting_802_1x:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSetting8021x the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSetting8021x if the connection contains one, otherwise %NULL
+ **/
+NMSetting8021x *
+nm_connection_get_setting_802_1x (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSetting8021x *) nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X);
+}
+
+/**
+ * nm_connection_get_setting_bluetooth:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingBluetooth the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingBluetooth if the connection contains one, otherwise %NULL
+ **/
+NMSettingBluetooth *
+nm_connection_get_setting_bluetooth (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingBluetooth *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BLUETOOTH);
+}
+
+/**
+ * nm_connection_get_setting_bond:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingBond the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingBond if the connection contains one, otherwise %NULL
+ **/
+NMSettingBond *
+nm_connection_get_setting_bond (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingBond *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BOND);
+}
+
+/**
+ * nm_connection_get_setting_team:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingTeam the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingTeam if the connection contains one, otherwise %NULL
+ **/
+NMSettingTeam *
+nm_connection_get_setting_team (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingTeam *) nm_connection_get_setting (connection, NM_TYPE_SETTING_TEAM);
+}
+
+/**
+ * nm_connection_get_setting_team_port:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingTeamPort the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingTeamPort if the connection contains one, otherwise %NULL
+ **/
+NMSettingTeamPort *
+nm_connection_get_setting_team_port (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingTeamPort *) nm_connection_get_setting (connection, NM_TYPE_SETTING_TEAM_PORT);
+}
+
+/**
+ * nm_connection_get_setting_bridge:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingBridge the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingBridge if the connection contains one, otherwise %NULL
+ **/
+NMSettingBridge *
+nm_connection_get_setting_bridge (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingBridge *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BRIDGE);
+}
+
+/**
+ * nm_connection_get_setting_cdma:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingCdma the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingCdma if the connection contains one, otherwise %NULL
+ **/
+NMSettingCdma *
+nm_connection_get_setting_cdma (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingCdma *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CDMA);
+}
+
+/**
+ * nm_connection_get_setting_connection:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingConnection the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingConnection if the connection contains one, otherwise %NULL
+ **/
+NMSettingConnection *
+nm_connection_get_setting_connection (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
+}
+
+/**
+ * nm_connection_get_setting_dcb:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingDcb the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingDcb if the connection contains one, otherwise NULL
+ **/
+NMSettingDcb *
+nm_connection_get_setting_dcb (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingDcb *) nm_connection_get_setting (connection, NM_TYPE_SETTING_DCB);
+}
+
+/**
+ * nm_connection_get_setting_generic:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingGeneric the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingGeneric if the connection contains one, otherwise NULL
+ **/
+NMSettingGeneric *
+nm_connection_get_setting_generic (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingGeneric *) nm_connection_get_setting (connection, NM_TYPE_SETTING_GENERIC);
+}
+
+/**
+ * nm_connection_get_setting_gsm:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingGsm the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingGsm if the connection contains one, otherwise %NULL
+ **/
+NMSettingGsm *
+nm_connection_get_setting_gsm (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingGsm *) nm_connection_get_setting (connection, NM_TYPE_SETTING_GSM);
+}
+
+/**
+ * nm_connection_get_setting_infiniband:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingInfiniband the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingInfiniband if the connection contains one, otherwise %NULL
+ **/
+NMSettingInfiniband *
+nm_connection_get_setting_infiniband (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingInfiniband *) nm_connection_get_setting (connection, NM_TYPE_SETTING_INFINIBAND);
+}
+
+/**
+ * nm_connection_get_setting_ip4_config:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingIP4Config the connection might contain.
+ *
+ * Note that it returns the value as type #NMSettingIPConfig, since the vast
+ * majority of IPv4-setting-related methods are on that type, not
+ * #NMSettingIP4Config.
+ *
+ * Returns: (type NMSettingIP4Config) (transfer none): an #NMSettingIP4Config if the
+ * connection contains one, otherwise %NULL
+ **/
+NMSettingIPConfig *
+nm_connection_get_setting_ip4_config (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingIPConfig *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
+}
+
+/**
+ * nm_connection_get_setting_ip6_config:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingIP6Config the connection might contain.
+ *
+ * Note that it returns the value as type #NMSettingIPConfig, since the vast
+ * majority of IPv6-setting-related methods are on that type, not
+ * #NMSettingIP6Config.
+ *
+ * Returns: (type NMSettingIP6Config) (transfer none): an #NMSettingIP6Config if the
+ * connection contains one, otherwise %NULL
+ **/
+NMSettingIPConfig *
+nm_connection_get_setting_ip6_config (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingIPConfig *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
+}
+
+/**
+ * nm_connection_get_setting_olpc_mesh:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingOlpcMesh the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingOlpcMesh if the connection contains one, otherwise %NULL
+ **/
+NMSettingOlpcMesh *
+nm_connection_get_setting_olpc_mesh (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingOlpcMesh *) nm_connection_get_setting (connection, NM_TYPE_SETTING_OLPC_MESH);
+}
+
+/**
+ * nm_connection_get_setting_ppp:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingPpp the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingPpp if the connection contains one, otherwise %NULL
+ **/
+NMSettingPpp *
+nm_connection_get_setting_ppp (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingPpp *) nm_connection_get_setting (connection, NM_TYPE_SETTING_PPP);
+}
+
+/**
+ * nm_connection_get_setting_pppoe:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingPppoe the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingPppoe if the connection contains one, otherwise %NULL
+ **/
+NMSettingPppoe *
+nm_connection_get_setting_pppoe (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingPppoe *) nm_connection_get_setting (connection, NM_TYPE_SETTING_PPPOE);
+}
+
+/**
+ * nm_connection_get_setting_serial:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingSerial the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingSerial if the connection contains one, otherwise %NULL
+ **/
+NMSettingSerial *
+nm_connection_get_setting_serial (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingSerial *) nm_connection_get_setting (connection, NM_TYPE_SETTING_SERIAL);
+}
+
+/**
+ * nm_connection_get_setting_vpn:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingVpn the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingVpn if the connection contains one, otherwise %NULL
+ **/
+NMSettingVpn *
+nm_connection_get_setting_vpn (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingVpn *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VPN);
+}
+
+/**
+ * nm_connection_get_setting_wimax:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingWimax the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingWimax if the connection contains one, otherwise %NULL
+ **/
+NMSettingWimax *
+nm_connection_get_setting_wimax (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingWimax *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIMAX);
+}
+
+/**
+ * nm_connection_get_setting_wired:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingWired the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingWired if the connection contains one, otherwise %NULL
+ **/
+NMSettingWired *
+nm_connection_get_setting_wired (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingWired *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED);
+}
+
+/**
+ * nm_connection_get_setting_adsl:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingAdsl the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingAdsl if the connection contains one, otherwise %NULL
+ **/
+NMSettingAdsl *
+nm_connection_get_setting_adsl (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingAdsl *) nm_connection_get_setting (connection, NM_TYPE_SETTING_ADSL);
+}
+
+/**
+ * nm_connection_get_setting_wireless:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingWireless the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingWireless if the connection contains one, otherwise %NULL
+ **/
+NMSettingWireless *
+nm_connection_get_setting_wireless (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingWireless *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS);
+}
+
+/**
+ * nm_connection_get_setting_wireless_security:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingWirelessSecurity the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingWirelessSecurity if the connection contains one, otherwise %NULL
+ **/
+NMSettingWirelessSecurity *
+nm_connection_get_setting_wireless_security (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingWirelessSecurity *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS_SECURITY);
+}
+
+/**
+ * nm_connection_get_setting_bridge_port:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingBridgePort the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingBridgePort if the connection contains one, otherwise %NULL
+ **/
+NMSettingBridgePort *
+nm_connection_get_setting_bridge_port (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingBridgePort *) nm_connection_get_setting (connection, NM_TYPE_SETTING_BRIDGE_PORT);
+}
+
+/**
+ * nm_connection_get_setting_vlan:
+ * @connection: the #NMConnection
+ *
+ * A shortcut to return any #NMSettingVlan the connection might contain.
+ *
+ * Returns: (transfer none): an #NMSettingVlan if the connection contains one, otherwise %NULL
+ **/
+NMSettingVlan *
+nm_connection_get_setting_vlan (NMConnection *connection)
+{
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ return (NMSettingVlan *) nm_connection_get_setting (connection, NM_TYPE_SETTING_VLAN);
+}
+
+/*************************************************************/
+
+static void
+nm_connection_private_free (NMConnectionPrivate *priv)
+{
+ NMConnection *self = priv->self;
+
+ g_hash_table_foreach_remove (priv->settings, _setting_release, self);
+ g_hash_table_destroy (priv->settings);
+ g_free (priv->path);
+
+ g_slice_free (NMConnectionPrivate, priv);
+}
+
+static NMConnectionPrivate *
+nm_connection_get_private (NMConnection *connection)
+{
+ NMConnectionPrivate *priv;
+
+ priv = g_object_get_data (G_OBJECT (connection), "NMConnectionPrivate");
+ if (!priv) {
+ priv = g_slice_new0 (NMConnectionPrivate);
+ g_object_set_data_full (G_OBJECT (connection), "NMConnectionPrivate",
+ priv, (GDestroyNotify) nm_connection_private_free);
+
+ priv->self = connection;
+ priv->settings = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
+ }
+
+ return priv;
+}
+
+static void
+nm_connection_default_init (NMConnectionInterface *iface)
+{
+ /* Signals */
+
+ /**
+ * NMConnection::secrets-updated:
+ * @connection: the object on which the signal is emitted
+ * @setting_name: the setting name of the #NMSetting for which secrets were
+ * updated
+ *
+ * The ::secrets-updated signal is emitted when the secrets of a setting
+ * have been changed.
+ */
+ signals[SECRETS_UPDATED] =
+ g_signal_new (NM_CONNECTION_SECRETS_UPDATED,
+ NM_TYPE_CONNECTION,
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (NMConnectionInterface, secrets_updated),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1,
+ G_TYPE_STRING);
+
+ /**
+ * NMConnection::secrets-cleared:
+ * @connection: the object on which the signal is emitted
+ *
+ * The ::secrets-cleared signal is emitted when the secrets of a connection
+ * are cleared.
+ */
+ signals[SECRETS_CLEARED] =
+ g_signal_new (NM_CONNECTION_SECRETS_CLEARED,
+ NM_TYPE_CONNECTION,
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (NMConnectionInterface, secrets_cleared),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ /**
+ * NMConnection::changed:
+ * @connection: the object on which the signal is emitted
+ *
+ * The ::changed signal is emitted when any property of any property
+ * (including secrets) of any setting of the connection is modified,
+ * or when settings are added or removed.
+ */
+ signals[CHANGED] =
+ g_signal_new (NM_CONNECTION_CHANGED,
+ NM_TYPE_CONNECTION,
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (NMConnectionInterface, changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
diff --git a/libnm-core/nm-connection.h b/libnm-core/nm-connection.h
new file mode 100644
index 000000000..c76ad6076
--- /dev/null
+++ b/libnm-core/nm-connection.h
@@ -0,0 +1,219 @@
+/* -*- 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 2007 - 2013 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#ifndef __NM_CONNECTION_H__
+#define __NM_CONNECTION_H__
+
+#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
+#error "Only <NetworkManager.h> can be included directly."
+#endif
+
+#include <nm-core-types.h>
+#include <nm-setting.h>
+#include <nm-errors.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_CONNECTION (nm_connection_get_type ())
+#define NM_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_CONNECTION, NMConnection))
+#define NM_IS_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_CONNECTION))
+#define NM_CONNECTION_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_CONNECTION, NMConnectionClass))
+
+/* Signals */
+#define NM_CONNECTION_SECRETS_UPDATED "secrets-updated"
+#define NM_CONNECTION_SECRETS_CLEARED "secrets-cleared"
+#define NM_CONNECTION_CHANGED "changed"
+
+/*
+ * NM_CONNECTION_NORMALIZE_PARAM_IP6_CONFIG_METHOD: overwrite the ip6 method
+ * when normalizing ip6 configuration. If omited, this defaults to
+ * @NM_SETTING_IP6_CONFIG_METHOD_AUTO.
+ */
+#define NM_CONNECTION_NORMALIZE_PARAM_IP6_CONFIG_METHOD "ip6-config-method"
+
+/**
+ * NMConnection:
+ *
+ * NMConnection is the interface implemented by #NMRemoteConnection on the
+ * client side, and #NMSettingsConnection on the daemon side.
+ */
+
+/**
+ * NMConnectionInterface:
+ * @parent: the parent interace struct
+ * @secrets_updated: emitted when the connection's secrets are updated
+ * @secrets_cleared: emitted when the connection's secrets are cleared
+ * @changed: emitted when any change to the connection's settings occurs
+ */
+typedef struct {
+ GTypeInterface parent;
+
+ /* Signals */
+ void (*secrets_updated) (NMConnection *connection,
+ const char *setting);
+ void (*secrets_cleared) (NMConnection *connection);
+ void (*changed) (NMConnection *connection);
+
+} NMConnectionInterface;
+
+GType nm_connection_get_type (void);
+
+void nm_connection_add_setting (NMConnection *connection,
+ NMSetting *setting);
+
+void nm_connection_remove_setting (NMConnection *connection,
+ GType setting_type);
+
+NMSetting *nm_connection_get_setting (NMConnection *connection,
+ GType setting_type);
+
+NMSetting *nm_connection_get_setting_by_name (NMConnection *connection,
+ const char *name);
+
+/**
+ * NM_VARIANT_TYPE_CONNECTION:
+ *
+ * #GVariantType for a dictionary mapping from setting names to
+ * %NM_VARIANT_TYPE_SETTING variants. This is used to represent an
+ * #NMConnection, and is the type taken by nm_simple_connection_new_from_dbus()
+ * and returned from nm_connection_to_dbus().
+ */
+#define NM_VARIANT_TYPE_CONNECTION (G_VARIANT_TYPE ("a{sa{sv}}"))
+
+/**
+ * NM_VARIANT_TYPE_SETTING:
+ *
+ * #GVariantType for a dictionary mapping from property names to values. This is
+ * an alias for %G_VARIANT_TYPE_VARDICT, and is the type of each element of
+ * an %NM_VARIANT_TYPE_CONNECTION dictionary.
+ */
+#define NM_VARIANT_TYPE_SETTING G_VARIANT_TYPE_VARDICT
+
+/**
+ * NMConnectionSerializationFlags:
+ * @NM_CONNECTION_SERIALIZE_ALL: serialize all properties (including secrets)
+ * @NM_CONNECTION_SERIALIZE_NO_SECRETS: do not include secrets
+ * @NM_CONNECTION_SERIALIZE_ONLY_SECRETS: only serialize secrets
+ *
+ * These flags determine which properties are serialized when calling when
+ * calling nm_connection_to_dbus().
+ **/
+typedef enum { /*< flags >*/
+ NM_CONNECTION_SERIALIZE_ALL = 0x00000000,
+ NM_CONNECTION_SERIALIZE_NO_SECRETS = 0x00000001,
+ NM_CONNECTION_SERIALIZE_ONLY_SECRETS = 0x00000002,
+} NMConnectionSerializationFlags;
+
+GVariant *nm_connection_to_dbus (NMConnection *connection,
+ NMConnectionSerializationFlags flags);
+
+gboolean nm_connection_replace_settings (NMConnection *connection,
+ GVariant *new_settings,
+ GError **error);
+
+void nm_connection_replace_settings_from_connection (NMConnection *connection,
+ NMConnection *new_connection);
+
+void nm_connection_clear_settings (NMConnection *connection);
+
+gboolean nm_connection_compare (NMConnection *a,
+ NMConnection *b,
+ NMSettingCompareFlags flags);
+
+gboolean nm_connection_diff (NMConnection *a,
+ NMConnection *b,
+ NMSettingCompareFlags flags,
+ GHashTable **out_settings);
+
+gboolean nm_connection_verify (NMConnection *connection, GError **error);
+gboolean nm_connection_normalize (NMConnection *connection,
+ GHashTable *parameters,
+ gboolean *modified,
+ GError **error);
+
+const char * nm_connection_need_secrets (NMConnection *connection,
+ GPtrArray **hints);
+
+void nm_connection_clear_secrets (NMConnection *connection);
+
+void nm_connection_clear_secrets_with_flags (NMConnection *connection,
+ NMSettingClearSecretsWithFlagsFn func,
+ gpointer user_data);
+
+gboolean nm_connection_update_secrets (NMConnection *connection,
+ const char *setting_name,
+ GVariant *secrets,
+ GError **error);
+
+void nm_connection_set_path (NMConnection *connection,
+ const char *path);
+
+const char * nm_connection_get_path (NMConnection *connection);
+
+const char * nm_connection_get_interface_name (NMConnection *connection);
+
+gboolean nm_connection_is_type (NMConnection *connection, const char *type);
+
+void nm_connection_for_each_setting_value (NMConnection *connection,
+ NMSettingValueIterFn func,
+ gpointer user_data);
+
+void nm_connection_dump (NMConnection *connection);
+
+/* Helpers */
+const char * nm_connection_get_uuid (NMConnection *connection);
+const char * nm_connection_get_id (NMConnection *connection);
+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);
+
+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);
+NMSettingTeam * nm_connection_get_setting_team (NMConnection *connection);
+NMSettingTeamPort * nm_connection_get_setting_team_port (NMConnection *connection);
+NMSettingBridge * nm_connection_get_setting_bridge (NMConnection *connection);
+NMSettingBridgePort * nm_connection_get_setting_bridge_port (NMConnection *connection);
+NMSettingCdma * nm_connection_get_setting_cdma (NMConnection *connection);
+NMSettingConnection * nm_connection_get_setting_connection (NMConnection *connection);
+NMSettingDcb * nm_connection_get_setting_dcb (NMConnection *connection);
+NMSettingGeneric * nm_connection_get_setting_generic (NMConnection *connection);
+NMSettingGsm * nm_connection_get_setting_gsm (NMConnection *connection);
+NMSettingInfiniband * nm_connection_get_setting_infiniband (NMConnection *connection);
+NMSettingIPConfig * nm_connection_get_setting_ip4_config (NMConnection *connection);
+NMSettingIPConfig * nm_connection_get_setting_ip6_config (NMConnection *connection);
+NMSettingOlpcMesh * nm_connection_get_setting_olpc_mesh (NMConnection *connection);
+NMSettingPpp * nm_connection_get_setting_ppp (NMConnection *connection);
+NMSettingPppoe * nm_connection_get_setting_pppoe (NMConnection *connection);
+NMSettingSerial * nm_connection_get_setting_serial (NMConnection *connection);
+NMSettingVpn * nm_connection_get_setting_vpn (NMConnection *connection);
+NMSettingWimax * nm_connection_get_setting_wimax (NMConnection *connection);
+NMSettingAdsl * nm_connection_get_setting_adsl (NMConnection *connection);
+NMSettingWired * nm_connection_get_setting_wired (NMConnection *connection);
+NMSettingWireless * nm_connection_get_setting_wireless (NMConnection *connection);
+NMSettingWirelessSecurity *nm_connection_get_setting_wireless_security (NMConnection *connection);
+NMSettingVlan * nm_connection_get_setting_vlan (NMConnection *connection);
+
+G_END_DECLS
+
+#endif /* __NM_CONNECTION_H__ */
diff --git a/libnm-core/nm-core-enum-types.c b/libnm-core/nm-core-enum-types.c
new file mode 100644
index 000000000..d7d4291bc
--- /dev/null
+++ b/libnm-core/nm-core-enum-types.c
@@ -0,0 +1,1031 @@
+
+
+
+/* Generated by glib-mkenums. Do not edit */
+
+#include "nm-core-enum-types.h"
+
+#include "nm-version.h"
+#include "nm-connection.h"
+#include "nm-core-types.h"
+#include "nm-dbus-interface.h"
+#include "nm-errors.h"
+#include "nm-setting-8021x.h"
+#include "nm-setting-adsl.h"
+#include "nm-setting-bluetooth.h"
+#include "nm-setting-bond.h"
+#include "nm-setting-bridge-port.h"
+#include "nm-setting-bridge.h"
+#include "nm-setting-cdma.h"
+#include "nm-setting-connection.h"
+#include "nm-setting-dcb.h"
+#include "nm-setting-generic.h"
+#include "nm-setting-gsm.h"
+#include "nm-setting-infiniband.h"
+#include "nm-setting-ip-config.h"
+#include "nm-setting-ip4-config.h"
+#include "nm-setting-ip6-config.h"
+#include "nm-setting-olpc-mesh.h"
+#include "nm-setting-ppp.h"
+#include "nm-setting-pppoe.h"
+#include "nm-setting-serial.h"
+#include "nm-setting-team-port.h"
+#include "nm-setting-team.h"
+#include "nm-setting-vlan.h"
+#include "nm-setting-vpn.h"
+#include "nm-setting-wimax.h"
+#include "nm-setting-wired.h"
+#include "nm-setting-wireless-security.h"
+#include "nm-setting-wireless.h"
+#include "nm-setting.h"
+#include "nm-simple-connection.h"
+#include "nm-utils.h"
+#include "nm-vpn-dbus-interface.h"
+
+GType
+nm_connection_serialization_flags_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GFlagsValue values[] = {
+ { NM_CONNECTION_SERIALIZE_ALL, "NM_CONNECTION_SERIALIZE_ALL", "all" },
+ { NM_CONNECTION_SERIALIZE_NO_SECRETS, "NM_CONNECTION_SERIALIZE_NO_SECRETS", "no-secrets" },
+ { NM_CONNECTION_SERIALIZE_ONLY_SECRETS, "NM_CONNECTION_SERIALIZE_ONLY_SECRETS", "only-secrets" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_flags_register_static (g_intern_static_string ("NMConnectionSerializationFlags"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_state_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_STATE_UNKNOWN, "NM_STATE_UNKNOWN", "unknown" },
+ { NM_STATE_ASLEEP, "NM_STATE_ASLEEP", "asleep" },
+ { NM_STATE_DISCONNECTED, "NM_STATE_DISCONNECTED", "disconnected" },
+ { NM_STATE_DISCONNECTING, "NM_STATE_DISCONNECTING", "disconnecting" },
+ { NM_STATE_CONNECTING, "NM_STATE_CONNECTING", "connecting" },
+ { NM_STATE_CONNECTED_LOCAL, "NM_STATE_CONNECTED_LOCAL", "connected-local" },
+ { NM_STATE_CONNECTED_SITE, "NM_STATE_CONNECTED_SITE", "connected-site" },
+ { NM_STATE_CONNECTED_GLOBAL, "NM_STATE_CONNECTED_GLOBAL", "connected-global" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMState"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_connectivity_state_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_CONNECTIVITY_UNKNOWN, "NM_CONNECTIVITY_UNKNOWN", "unknown" },
+ { NM_CONNECTIVITY_NONE, "NM_CONNECTIVITY_NONE", "none" },
+ { NM_CONNECTIVITY_PORTAL, "NM_CONNECTIVITY_PORTAL", "portal" },
+ { NM_CONNECTIVITY_LIMITED, "NM_CONNECTIVITY_LIMITED", "limited" },
+ { NM_CONNECTIVITY_FULL, "NM_CONNECTIVITY_FULL", "full" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMConnectivityState"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_device_type_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_DEVICE_TYPE_UNKNOWN, "NM_DEVICE_TYPE_UNKNOWN", "unknown" },
+ { NM_DEVICE_TYPE_ETHERNET, "NM_DEVICE_TYPE_ETHERNET", "ethernet" },
+ { NM_DEVICE_TYPE_WIFI, "NM_DEVICE_TYPE_WIFI", "wifi" },
+ { NM_DEVICE_TYPE_UNUSED1, "NM_DEVICE_TYPE_UNUSED1", "unused1" },
+ { NM_DEVICE_TYPE_UNUSED2, "NM_DEVICE_TYPE_UNUSED2", "unused2" },
+ { NM_DEVICE_TYPE_BT, "NM_DEVICE_TYPE_BT", "bt" },
+ { NM_DEVICE_TYPE_OLPC_MESH, "NM_DEVICE_TYPE_OLPC_MESH", "olpc-mesh" },
+ { NM_DEVICE_TYPE_WIMAX, "NM_DEVICE_TYPE_WIMAX", "wimax" },
+ { NM_DEVICE_TYPE_MODEM, "NM_DEVICE_TYPE_MODEM", "modem" },
+ { NM_DEVICE_TYPE_INFINIBAND, "NM_DEVICE_TYPE_INFINIBAND", "infiniband" },
+ { NM_DEVICE_TYPE_BOND, "NM_DEVICE_TYPE_BOND", "bond" },
+ { NM_DEVICE_TYPE_VLAN, "NM_DEVICE_TYPE_VLAN", "vlan" },
+ { NM_DEVICE_TYPE_ADSL, "NM_DEVICE_TYPE_ADSL", "adsl" },
+ { NM_DEVICE_TYPE_BRIDGE, "NM_DEVICE_TYPE_BRIDGE", "bridge" },
+ { NM_DEVICE_TYPE_GENERIC, "NM_DEVICE_TYPE_GENERIC", "generic" },
+ { NM_DEVICE_TYPE_TEAM, "NM_DEVICE_TYPE_TEAM", "team" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMDeviceType"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_device_capabilities_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GFlagsValue values[] = {
+ { NM_DEVICE_CAP_NONE, "NM_DEVICE_CAP_NONE", "none" },
+ { NM_DEVICE_CAP_NM_SUPPORTED, "NM_DEVICE_CAP_NM_SUPPORTED", "nm-supported" },
+ { NM_DEVICE_CAP_CARRIER_DETECT, "NM_DEVICE_CAP_CARRIER_DETECT", "carrier-detect" },
+ { NM_DEVICE_CAP_IS_SOFTWARE, "NM_DEVICE_CAP_IS_SOFTWARE", "is-software" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_flags_register_static (g_intern_static_string ("NMDeviceCapabilities"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_device_wifi_capabilities_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GFlagsValue values[] = {
+ { NM_WIFI_DEVICE_CAP_NONE, "NM_WIFI_DEVICE_CAP_NONE", "none" },
+ { NM_WIFI_DEVICE_CAP_CIPHER_WEP40, "NM_WIFI_DEVICE_CAP_CIPHER_WEP40", "cipher-wep40" },
+ { NM_WIFI_DEVICE_CAP_CIPHER_WEP104, "NM_WIFI_DEVICE_CAP_CIPHER_WEP104", "cipher-wep104" },
+ { NM_WIFI_DEVICE_CAP_CIPHER_TKIP, "NM_WIFI_DEVICE_CAP_CIPHER_TKIP", "cipher-tkip" },
+ { NM_WIFI_DEVICE_CAP_CIPHER_CCMP, "NM_WIFI_DEVICE_CAP_CIPHER_CCMP", "cipher-ccmp" },
+ { NM_WIFI_DEVICE_CAP_WPA, "NM_WIFI_DEVICE_CAP_WPA", "wpa" },
+ { NM_WIFI_DEVICE_CAP_RSN, "NM_WIFI_DEVICE_CAP_RSN", "rsn" },
+ { NM_WIFI_DEVICE_CAP_AP, "NM_WIFI_DEVICE_CAP_AP", "ap" },
+ { NM_WIFI_DEVICE_CAP_ADHOC, "NM_WIFI_DEVICE_CAP_ADHOC", "adhoc" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_flags_register_static (g_intern_static_string ("NMDeviceWifiCapabilities"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_802_11_ap_flags_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GFlagsValue values[] = {
+ { NM_802_11_AP_FLAGS_NONE, "NM_802_11_AP_FLAGS_NONE", "none" },
+ { NM_802_11_AP_FLAGS_PRIVACY, "NM_802_11_AP_FLAGS_PRIVACY", "privacy" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_flags_register_static (g_intern_static_string ("NM80211ApFlags"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_802_11_ap_security_flags_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GFlagsValue values[] = {
+ { NM_802_11_AP_SEC_NONE, "NM_802_11_AP_SEC_NONE", "none" },
+ { NM_802_11_AP_SEC_PAIR_WEP40, "NM_802_11_AP_SEC_PAIR_WEP40", "pair-wep40" },
+ { NM_802_11_AP_SEC_PAIR_WEP104, "NM_802_11_AP_SEC_PAIR_WEP104", "pair-wep104" },
+ { NM_802_11_AP_SEC_PAIR_TKIP, "NM_802_11_AP_SEC_PAIR_TKIP", "pair-tkip" },
+ { NM_802_11_AP_SEC_PAIR_CCMP, "NM_802_11_AP_SEC_PAIR_CCMP", "pair-ccmp" },
+ { NM_802_11_AP_SEC_GROUP_WEP40, "NM_802_11_AP_SEC_GROUP_WEP40", "group-wep40" },
+ { NM_802_11_AP_SEC_GROUP_WEP104, "NM_802_11_AP_SEC_GROUP_WEP104", "group-wep104" },
+ { NM_802_11_AP_SEC_GROUP_TKIP, "NM_802_11_AP_SEC_GROUP_TKIP", "group-tkip" },
+ { NM_802_11_AP_SEC_GROUP_CCMP, "NM_802_11_AP_SEC_GROUP_CCMP", "group-ccmp" },
+ { NM_802_11_AP_SEC_KEY_MGMT_PSK, "NM_802_11_AP_SEC_KEY_MGMT_PSK", "key-mgmt-psk" },
+ { NM_802_11_AP_SEC_KEY_MGMT_802_1X, "NM_802_11_AP_SEC_KEY_MGMT_802_1X", "key-mgmt-802-1x" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_flags_register_static (g_intern_static_string ("NM80211ApSecurityFlags"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_802_11_mode_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_802_11_MODE_UNKNOWN, "NM_802_11_MODE_UNKNOWN", "unknown" },
+ { NM_802_11_MODE_ADHOC, "NM_802_11_MODE_ADHOC", "adhoc" },
+ { NM_802_11_MODE_INFRA, "NM_802_11_MODE_INFRA", "infra" },
+ { NM_802_11_MODE_AP, "NM_802_11_MODE_AP", "ap" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NM80211Mode"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_bluetooth_capabilities_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GFlagsValue values[] = {
+ { NM_BT_CAPABILITY_NONE, "NM_BT_CAPABILITY_NONE", "none" },
+ { NM_BT_CAPABILITY_DUN, "NM_BT_CAPABILITY_DUN", "dun" },
+ { NM_BT_CAPABILITY_NAP, "NM_BT_CAPABILITY_NAP", "nap" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_flags_register_static (g_intern_static_string ("NMBluetoothCapabilities"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_device_modem_capabilities_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GFlagsValue values[] = {
+ { NM_DEVICE_MODEM_CAPABILITY_NONE, "NM_DEVICE_MODEM_CAPABILITY_NONE", "none" },
+ { NM_DEVICE_MODEM_CAPABILITY_POTS, "NM_DEVICE_MODEM_CAPABILITY_POTS", "pots" },
+ { NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO, "NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO", "cdma-evdo" },
+ { NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS, "NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS", "gsm-umts" },
+ { NM_DEVICE_MODEM_CAPABILITY_LTE, "NM_DEVICE_MODEM_CAPABILITY_LTE", "lte" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_flags_register_static (g_intern_static_string ("NMDeviceModemCapabilities"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_device_state_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_DEVICE_STATE_UNKNOWN, "NM_DEVICE_STATE_UNKNOWN", "unknown" },
+ { NM_DEVICE_STATE_UNMANAGED, "NM_DEVICE_STATE_UNMANAGED", "unmanaged" },
+ { NM_DEVICE_STATE_UNAVAILABLE, "NM_DEVICE_STATE_UNAVAILABLE", "unavailable" },
+ { NM_DEVICE_STATE_DISCONNECTED, "NM_DEVICE_STATE_DISCONNECTED", "disconnected" },
+ { NM_DEVICE_STATE_PREPARE, "NM_DEVICE_STATE_PREPARE", "prepare" },
+ { NM_DEVICE_STATE_CONFIG, "NM_DEVICE_STATE_CONFIG", "config" },
+ { NM_DEVICE_STATE_NEED_AUTH, "NM_DEVICE_STATE_NEED_AUTH", "need-auth" },
+ { NM_DEVICE_STATE_IP_CONFIG, "NM_DEVICE_STATE_IP_CONFIG", "ip-config" },
+ { NM_DEVICE_STATE_IP_CHECK, "NM_DEVICE_STATE_IP_CHECK", "ip-check" },
+ { NM_DEVICE_STATE_SECONDARIES, "NM_DEVICE_STATE_SECONDARIES", "secondaries" },
+ { NM_DEVICE_STATE_ACTIVATED, "NM_DEVICE_STATE_ACTIVATED", "activated" },
+ { NM_DEVICE_STATE_DEACTIVATING, "NM_DEVICE_STATE_DEACTIVATING", "deactivating" },
+ { NM_DEVICE_STATE_FAILED, "NM_DEVICE_STATE_FAILED", "failed" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMDeviceState"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_device_state_reason_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_DEVICE_STATE_REASON_NONE, "NM_DEVICE_STATE_REASON_NONE", "none" },
+ { NM_DEVICE_STATE_REASON_UNKNOWN, "NM_DEVICE_STATE_REASON_UNKNOWN", "unknown" },
+ { NM_DEVICE_STATE_REASON_NOW_MANAGED, "NM_DEVICE_STATE_REASON_NOW_MANAGED", "now-managed" },
+ { NM_DEVICE_STATE_REASON_NOW_UNMANAGED, "NM_DEVICE_STATE_REASON_NOW_UNMANAGED", "now-unmanaged" },
+ { NM_DEVICE_STATE_REASON_CONFIG_FAILED, "NM_DEVICE_STATE_REASON_CONFIG_FAILED", "config-failed" },
+ { NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE, "NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE", "ip-config-unavailable" },
+ { NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED, "NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED", "ip-config-expired" },
+ { NM_DEVICE_STATE_REASON_NO_SECRETS, "NM_DEVICE_STATE_REASON_NO_SECRETS", "no-secrets" },
+ { NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT, "NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT", "supplicant-disconnect" },
+ { NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED, "NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED", "supplicant-config-failed" },
+ { NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED, "NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED", "supplicant-failed" },
+ { NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT, "NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT", "supplicant-timeout" },
+ { NM_DEVICE_STATE_REASON_PPP_START_FAILED, "NM_DEVICE_STATE_REASON_PPP_START_FAILED", "ppp-start-failed" },
+ { NM_DEVICE_STATE_REASON_PPP_DISCONNECT, "NM_DEVICE_STATE_REASON_PPP_DISCONNECT", "ppp-disconnect" },
+ { NM_DEVICE_STATE_REASON_PPP_FAILED, "NM_DEVICE_STATE_REASON_PPP_FAILED", "ppp-failed" },
+ { NM_DEVICE_STATE_REASON_DHCP_START_FAILED, "NM_DEVICE_STATE_REASON_DHCP_START_FAILED", "dhcp-start-failed" },
+ { NM_DEVICE_STATE_REASON_DHCP_ERROR, "NM_DEVICE_STATE_REASON_DHCP_ERROR", "dhcp-error" },
+ { NM_DEVICE_STATE_REASON_DHCP_FAILED, "NM_DEVICE_STATE_REASON_DHCP_FAILED", "dhcp-failed" },
+ { NM_DEVICE_STATE_REASON_SHARED_START_FAILED, "NM_DEVICE_STATE_REASON_SHARED_START_FAILED", "shared-start-failed" },
+ { NM_DEVICE_STATE_REASON_SHARED_FAILED, "NM_DEVICE_STATE_REASON_SHARED_FAILED", "shared-failed" },
+ { NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED, "NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED", "autoip-start-failed" },
+ { NM_DEVICE_STATE_REASON_AUTOIP_ERROR, "NM_DEVICE_STATE_REASON_AUTOIP_ERROR", "autoip-error" },
+ { NM_DEVICE_STATE_REASON_AUTOIP_FAILED, "NM_DEVICE_STATE_REASON_AUTOIP_FAILED", "autoip-failed" },
+ { NM_DEVICE_STATE_REASON_MODEM_BUSY, "NM_DEVICE_STATE_REASON_MODEM_BUSY", "modem-busy" },
+ { NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE, "NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE", "modem-no-dial-tone" },
+ { NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER, "NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER", "modem-no-carrier" },
+ { NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT, "NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT", "modem-dial-timeout" },
+ { NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED, "NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED", "modem-dial-failed" },
+ { NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED, "NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED", "modem-init-failed" },
+ { NM_DEVICE_STATE_REASON_GSM_APN_FAILED, "NM_DEVICE_STATE_REASON_GSM_APN_FAILED", "gsm-apn-failed" },
+ { NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING, "NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING", "gsm-registration-not-searching" },
+ { NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED, "NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED", "gsm-registration-denied" },
+ { NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT, "NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT", "gsm-registration-timeout" },
+ { NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED, "NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED", "gsm-registration-failed" },
+ { NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED, "NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED", "gsm-pin-check-failed" },
+ { NM_DEVICE_STATE_REASON_FIRMWARE_MISSING, "NM_DEVICE_STATE_REASON_FIRMWARE_MISSING", "firmware-missing" },
+ { NM_DEVICE_STATE_REASON_REMOVED, "NM_DEVICE_STATE_REASON_REMOVED", "removed" },
+ { NM_DEVICE_STATE_REASON_SLEEPING, "NM_DEVICE_STATE_REASON_SLEEPING", "sleeping" },
+ { NM_DEVICE_STATE_REASON_CONNECTION_REMOVED, "NM_DEVICE_STATE_REASON_CONNECTION_REMOVED", "connection-removed" },
+ { NM_DEVICE_STATE_REASON_USER_REQUESTED, "NM_DEVICE_STATE_REASON_USER_REQUESTED", "user-requested" },
+ { NM_DEVICE_STATE_REASON_CARRIER, "NM_DEVICE_STATE_REASON_CARRIER", "carrier" },
+ { NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED, "NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED", "connection-assumed" },
+ { NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE, "NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE", "supplicant-available" },
+ { NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND, "NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND", "modem-not-found" },
+ { NM_DEVICE_STATE_REASON_BT_FAILED, "NM_DEVICE_STATE_REASON_BT_FAILED", "bt-failed" },
+ { NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED, "NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED", "gsm-sim-not-inserted" },
+ { NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED, "NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED", "gsm-sim-pin-required" },
+ { NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED, "NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED", "gsm-sim-puk-required" },
+ { NM_DEVICE_STATE_REASON_GSM_SIM_WRONG, "NM_DEVICE_STATE_REASON_GSM_SIM_WRONG", "gsm-sim-wrong" },
+ { NM_DEVICE_STATE_REASON_INFINIBAND_MODE, "NM_DEVICE_STATE_REASON_INFINIBAND_MODE", "infiniband-mode" },
+ { NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED, "NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED", "dependency-failed" },
+ { NM_DEVICE_STATE_REASON_BR2684_FAILED, "NM_DEVICE_STATE_REASON_BR2684_FAILED", "br2684-failed" },
+ { NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE, "NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE", "modem-manager-unavailable" },
+ { NM_DEVICE_STATE_REASON_SSID_NOT_FOUND, "NM_DEVICE_STATE_REASON_SSID_NOT_FOUND", "ssid-not-found" },
+ { NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED, "NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED", "secondary-connection-failed" },
+ { NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED, "NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED", "dcb-fcoe-failed" },
+ { NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED, "NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED", "teamd-control-failed" },
+ { NM_DEVICE_STATE_REASON_MODEM_FAILED, "NM_DEVICE_STATE_REASON_MODEM_FAILED", "modem-failed" },
+ { NM_DEVICE_STATE_REASON_MODEM_AVAILABLE, "NM_DEVICE_STATE_REASON_MODEM_AVAILABLE", "modem-available" },
+ { NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT, "NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT", "sim-pin-incorrect" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMDeviceStateReason"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_active_connection_state_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_ACTIVE_CONNECTION_STATE_UNKNOWN, "NM_ACTIVE_CONNECTION_STATE_UNKNOWN", "unknown" },
+ { NM_ACTIVE_CONNECTION_STATE_ACTIVATING, "NM_ACTIVE_CONNECTION_STATE_ACTIVATING", "activating" },
+ { NM_ACTIVE_CONNECTION_STATE_ACTIVATED, "NM_ACTIVE_CONNECTION_STATE_ACTIVATED", "activated" },
+ { NM_ACTIVE_CONNECTION_STATE_DEACTIVATING, "NM_ACTIVE_CONNECTION_STATE_DEACTIVATING", "deactivating" },
+ { NM_ACTIVE_CONNECTION_STATE_DEACTIVATED, "NM_ACTIVE_CONNECTION_STATE_DEACTIVATED", "deactivated" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMActiveConnectionState"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_secret_agent_get_secrets_flags_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GFlagsValue values[] = {
+ { NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE, "NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE", "none" },
+ { NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION, "NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION", "allow-interaction" },
+ { NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW, "NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW", "request-new" },
+ { NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED, "NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED", "user-requested" },
+ { NM_SECRET_AGENT_GET_SECRETS_FLAG_ONLY_SYSTEM, "NM_SECRET_AGENT_GET_SECRETS_FLAG_ONLY_SYSTEM", "only-system" },
+ { NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS, "NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS", "no-errors" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_flags_register_static (g_intern_static_string ("NMSecretAgentGetSecretsFlags"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_secret_agent_capabilities_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GFlagsValue values[] = {
+ { NM_SECRET_AGENT_CAPABILITY_NONE, "NM_SECRET_AGENT_CAPABILITY_NONE", "none" },
+ { NM_SECRET_AGENT_CAPABILITY_VPN_HINTS, "NM_SECRET_AGENT_CAPABILITY_VPN_HINTS", "vpn-hints" },
+ { NM_SECRET_AGENT_CAPABILITY_LAST, "NM_SECRET_AGENT_CAPABILITY_LAST", "last" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_flags_register_static (g_intern_static_string ("NMSecretAgentCapabilities"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_agent_manager_error_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_AGENT_MANAGER_ERROR_FAILED, "NM_AGENT_MANAGER_ERROR_FAILED", "Failed" },
+ { NM_AGENT_MANAGER_ERROR_PERMISSION_DENIED, "NM_AGENT_MANAGER_ERROR_PERMISSION_DENIED", "PermissionDenied" },
+ { NM_AGENT_MANAGER_ERROR_INVALID_IDENTIFIER, "NM_AGENT_MANAGER_ERROR_INVALID_IDENTIFIER", "InvalidIdentifier" },
+ { NM_AGENT_MANAGER_ERROR_NOT_REGISTERED, "NM_AGENT_MANAGER_ERROR_NOT_REGISTERED", "NotRegistered" },
+ { NM_AGENT_MANAGER_ERROR_NO_SECRETS, "NM_AGENT_MANAGER_ERROR_NO_SECRETS", "NoSecrets" },
+ { NM_AGENT_MANAGER_ERROR_USER_CANCELED, "NM_AGENT_MANAGER_ERROR_USER_CANCELED", "UserCanceled" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMAgentManagerError"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_connection_error_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_CONNECTION_ERROR_FAILED, "NM_CONNECTION_ERROR_FAILED", "Failed" },
+ { NM_CONNECTION_ERROR_SETTING_NOT_FOUND, "NM_CONNECTION_ERROR_SETTING_NOT_FOUND", "SettingNotFound" },
+ { NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND, "NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND", "PropertyNotFound" },
+ { NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET, "NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET", "PropertyNotSecret" },
+ { NM_CONNECTION_ERROR_MISSING_SETTING, "NM_CONNECTION_ERROR_MISSING_SETTING", "MissingSetting" },
+ { NM_CONNECTION_ERROR_INVALID_SETTING, "NM_CONNECTION_ERROR_INVALID_SETTING", "InvalidSetting" },
+ { NM_CONNECTION_ERROR_MISSING_PROPERTY, "NM_CONNECTION_ERROR_MISSING_PROPERTY", "MissingProperty" },
+ { NM_CONNECTION_ERROR_INVALID_PROPERTY, "NM_CONNECTION_ERROR_INVALID_PROPERTY", "InvalidProperty" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMConnectionError"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_crypto_error_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_CRYPTO_ERROR_FAILED, "NM_CRYPTO_ERROR_FAILED", "failed" },
+ { NM_CRYPTO_ERROR_INVALID_DATA, "NM_CRYPTO_ERROR_INVALID_DATA", "invalid-data" },
+ { NM_CRYPTO_ERROR_INVALID_PASSWORD, "NM_CRYPTO_ERROR_INVALID_PASSWORD", "invalid-password" },
+ { NM_CRYPTO_ERROR_UNKNOWN_CIPHER, "NM_CRYPTO_ERROR_UNKNOWN_CIPHER", "unknown-cipher" },
+ { NM_CRYPTO_ERROR_DECRYPTION_FAILED, "NM_CRYPTO_ERROR_DECRYPTION_FAILED", "decryption-failed" },
+ { NM_CRYPTO_ERROR_ENCRYPTION_FAILED, "NM_CRYPTO_ERROR_ENCRYPTION_FAILED", "encryption-failed" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMCryptoError"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_device_error_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_DEVICE_ERROR_FAILED, "NM_DEVICE_ERROR_FAILED", "Failed" },
+ { NM_DEVICE_ERROR_CREATION_FAILED, "NM_DEVICE_ERROR_CREATION_FAILED", "CreationFailed" },
+ { NM_DEVICE_ERROR_INVALID_CONNECTION, "NM_DEVICE_ERROR_INVALID_CONNECTION", "InvalidConnection" },
+ { NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, "NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION", "IncompatibleConnection" },
+ { NM_DEVICE_ERROR_NOT_ACTIVE, "NM_DEVICE_ERROR_NOT_ACTIVE", "NotActive" },
+ { NM_DEVICE_ERROR_NOT_SOFTWARE, "NM_DEVICE_ERROR_NOT_SOFTWARE", "NotSoftware" },
+ { NM_DEVICE_ERROR_NOT_ALLOWED, "NM_DEVICE_ERROR_NOT_ALLOWED", "NotAllowed" },
+ { NM_DEVICE_ERROR_SPECIFIC_OBJECT_NOT_FOUND, "NM_DEVICE_ERROR_SPECIFIC_OBJECT_NOT_FOUND", "SpecificObjectNotFound" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMDeviceError"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_manager_error_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_MANAGER_ERROR_FAILED, "NM_MANAGER_ERROR_FAILED", "Failed" },
+ { NM_MANAGER_ERROR_PERMISSION_DENIED, "NM_MANAGER_ERROR_PERMISSION_DENIED", "PermissionDenied" },
+ { NM_MANAGER_ERROR_UNKNOWN_CONNECTION, "NM_MANAGER_ERROR_UNKNOWN_CONNECTION", "UnknownConnection" },
+ { NM_MANAGER_ERROR_UNKNOWN_DEVICE, "NM_MANAGER_ERROR_UNKNOWN_DEVICE", "UnknownDevice" },
+ { NM_MANAGER_ERROR_CONNECTION_NOT_AVAILABLE, "NM_MANAGER_ERROR_CONNECTION_NOT_AVAILABLE", "ConnectionNotAvailable" },
+ { NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE, "NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE", "ConnectionNotActive" },
+ { NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE, "NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE", "ConnectionAlreadyActive" },
+ { NM_MANAGER_ERROR_DEPENDENCY_FAILED, "NM_MANAGER_ERROR_DEPENDENCY_FAILED", "DependencyFailed" },
+ { NM_MANAGER_ERROR_ALREADY_ASLEEP_OR_AWAKE, "NM_MANAGER_ERROR_ALREADY_ASLEEP_OR_AWAKE", "AlreadyAsleepOrAwake" },
+ { NM_MANAGER_ERROR_ALREADY_ENABLED_OR_DISABLED, "NM_MANAGER_ERROR_ALREADY_ENABLED_OR_DISABLED", "AlreadyEnabledOrDisabled" },
+ { NM_MANAGER_ERROR_UNKNOWN_LOG_LEVEL, "NM_MANAGER_ERROR_UNKNOWN_LOG_LEVEL", "UnknownLogLevel" },
+ { NM_MANAGER_ERROR_UNKNOWN_LOG_DOMAIN, "NM_MANAGER_ERROR_UNKNOWN_LOG_DOMAIN", "UnknownLogDomain" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMManagerError"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_secret_agent_error_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_SECRET_AGENT_ERROR_FAILED, "NM_SECRET_AGENT_ERROR_FAILED", "Failed" },
+ { NM_SECRET_AGENT_ERROR_PERMISSION_DENIED, "NM_SECRET_AGENT_ERROR_PERMISSION_DENIED", "PermissionDenied" },
+ { NM_SECRET_AGENT_ERROR_INVALID_CONNECTION, "NM_SECRET_AGENT_ERROR_INVALID_CONNECTION", "InvalidConnection" },
+ { NM_SECRET_AGENT_ERROR_USER_CANCELED, "NM_SECRET_AGENT_ERROR_USER_CANCELED", "UserCanceled" },
+ { NM_SECRET_AGENT_ERROR_AGENT_CANCELED, "NM_SECRET_AGENT_ERROR_AGENT_CANCELED", "AgentCanceled" },
+ { NM_SECRET_AGENT_ERROR_NO_SECRETS, "NM_SECRET_AGENT_ERROR_NO_SECRETS", "NoSecrets" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMSecretAgentError"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_settings_error_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_SETTINGS_ERROR_FAILED, "NM_SETTINGS_ERROR_FAILED", "Failed" },
+ { NM_SETTINGS_ERROR_PERMISSION_DENIED, "NM_SETTINGS_ERROR_PERMISSION_DENIED", "PermissionDenied" },
+ { NM_SETTINGS_ERROR_NOT_SUPPORTED, "NM_SETTINGS_ERROR_NOT_SUPPORTED", "NotSupported" },
+ { NM_SETTINGS_ERROR_INVALID_CONNECTION, "NM_SETTINGS_ERROR_INVALID_CONNECTION", "InvalidConnection" },
+ { NM_SETTINGS_ERROR_READ_ONLY_CONNECTION, "NM_SETTINGS_ERROR_READ_ONLY_CONNECTION", "ReadOnlyConnection" },
+ { NM_SETTINGS_ERROR_UUID_EXISTS, "NM_SETTINGS_ERROR_UUID_EXISTS", "UuidExists" },
+ { NM_SETTINGS_ERROR_INVALID_HOSTNAME, "NM_SETTINGS_ERROR_INVALID_HOSTNAME", "InvalidHostname" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMSettingsError"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_vpn_plugin_error_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_VPN_PLUGIN_ERROR_FAILED, "NM_VPN_PLUGIN_ERROR_FAILED", "Failed" },
+ { NM_VPN_PLUGIN_ERROR_STARTING_IN_PROGRESS, "NM_VPN_PLUGIN_ERROR_STARTING_IN_PROGRESS", "StartingInProgress" },
+ { NM_VPN_PLUGIN_ERROR_ALREADY_STARTED, "NM_VPN_PLUGIN_ERROR_ALREADY_STARTED", "AlreadyStarted" },
+ { NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS, "NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS", "StoppingInProgress" },
+ { NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED, "NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED", "AlreadyStopped" },
+ { NM_VPN_PLUGIN_ERROR_WRONG_STATE, "NM_VPN_PLUGIN_ERROR_WRONG_STATE", "WrongState" },
+ { NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, "NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS", "BadArguments" },
+ { NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, "NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED", "LaunchFailed" },
+ { NM_VPN_PLUGIN_ERROR_INVALID_CONNECTION, "NM_VPN_PLUGIN_ERROR_INVALID_CONNECTION", "InvalidConnection" },
+ { NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED, "NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED", "InteractiveNotSupported" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMVpnPluginError"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_setting_802_1x_ck_format_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_SETTING_802_1X_CK_FORMAT_UNKNOWN, "NM_SETTING_802_1X_CK_FORMAT_UNKNOWN", "unknown" },
+ { NM_SETTING_802_1X_CK_FORMAT_X509, "NM_SETTING_802_1X_CK_FORMAT_X509", "x509" },
+ { NM_SETTING_802_1X_CK_FORMAT_RAW_KEY, "NM_SETTING_802_1X_CK_FORMAT_RAW_KEY", "raw-key" },
+ { NM_SETTING_802_1X_CK_FORMAT_PKCS12, "NM_SETTING_802_1X_CK_FORMAT_PKCS12", "pkcs12" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMSetting8021xCKFormat"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_setting_802_1x_ck_scheme_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_SETTING_802_1X_CK_SCHEME_UNKNOWN, "NM_SETTING_802_1X_CK_SCHEME_UNKNOWN", "unknown" },
+ { NM_SETTING_802_1X_CK_SCHEME_BLOB, "NM_SETTING_802_1X_CK_SCHEME_BLOB", "blob" },
+ { NM_SETTING_802_1X_CK_SCHEME_PATH, "NM_SETTING_802_1X_CK_SCHEME_PATH", "path" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMSetting8021xCKScheme"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_setting_dcb_flags_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GFlagsValue values[] = {
+ { NM_SETTING_DCB_FLAG_NONE, "NM_SETTING_DCB_FLAG_NONE", "none" },
+ { NM_SETTING_DCB_FLAG_ENABLE, "NM_SETTING_DCB_FLAG_ENABLE", "enable" },
+ { NM_SETTING_DCB_FLAG_ADVERTISE, "NM_SETTING_DCB_FLAG_ADVERTISE", "advertise" },
+ { NM_SETTING_DCB_FLAG_WILLING, "NM_SETTING_DCB_FLAG_WILLING", "willing" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_flags_register_static (g_intern_static_string ("NMSettingDcbFlags"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_setting_ip6_config_privacy_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN, "NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN", "unknown" },
+ { NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED, "NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED", "disabled" },
+ { NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR, "NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR", "prefer-public-addr" },
+ { NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, "NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR", "prefer-temp-addr" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMSettingIP6ConfigPrivacy"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_setting_serial_parity_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_SETTING_SERIAL_PARITY_NONE, "NM_SETTING_SERIAL_PARITY_NONE", "none" },
+ { NM_SETTING_SERIAL_PARITY_EVEN, "NM_SETTING_SERIAL_PARITY_EVEN", "even" },
+ { NM_SETTING_SERIAL_PARITY_ODD, "NM_SETTING_SERIAL_PARITY_ODD", "odd" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMSettingSerialParity"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_vlan_priority_map_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_VLAN_INGRESS_MAP, "NM_VLAN_INGRESS_MAP", "ingress-map" },
+ { NM_VLAN_EGRESS_MAP, "NM_VLAN_EGRESS_MAP", "egress-map" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMVlanPriorityMap"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_vlan_flags_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GFlagsValue values[] = {
+ { NM_VLAN_FLAG_REORDER_HEADERS, "NM_VLAN_FLAG_REORDER_HEADERS", "reorder-headers" },
+ { NM_VLAN_FLAG_GVRP, "NM_VLAN_FLAG_GVRP", "gvrp" },
+ { NM_VLAN_FLAG_LOOSE_BINDING, "NM_VLAN_FLAG_LOOSE_BINDING", "loose-binding" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_flags_register_static (g_intern_static_string ("NMVlanFlags"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_wep_key_type_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_WEP_KEY_TYPE_UNKNOWN, "NM_WEP_KEY_TYPE_UNKNOWN", "unknown" },
+ { NM_WEP_KEY_TYPE_KEY, "NM_WEP_KEY_TYPE_KEY", "key" },
+ { NM_WEP_KEY_TYPE_PASSPHRASE, "NM_WEP_KEY_TYPE_PASSPHRASE", "passphrase" },
+ { NM_WEP_KEY_TYPE_LAST, "NM_WEP_KEY_TYPE_LAST", "last" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMWepKeyType"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_setting_secret_flags_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GFlagsValue values[] = {
+ { NM_SETTING_SECRET_FLAG_NONE, "NM_SETTING_SECRET_FLAG_NONE", "none" },
+ { NM_SETTING_SECRET_FLAG_AGENT_OWNED, "NM_SETTING_SECRET_FLAG_AGENT_OWNED", "agent-owned" },
+ { NM_SETTING_SECRET_FLAG_NOT_SAVED, "NM_SETTING_SECRET_FLAG_NOT_SAVED", "not-saved" },
+ { NM_SETTING_SECRET_FLAG_NOT_REQUIRED, "NM_SETTING_SECRET_FLAG_NOT_REQUIRED", "not-required" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_flags_register_static (g_intern_static_string ("NMSettingSecretFlags"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_setting_compare_flags_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_SETTING_COMPARE_FLAG_EXACT, "NM_SETTING_COMPARE_FLAG_EXACT", "exact" },
+ { NM_SETTING_COMPARE_FLAG_FUZZY, "NM_SETTING_COMPARE_FLAG_FUZZY", "fuzzy" },
+ { NM_SETTING_COMPARE_FLAG_IGNORE_ID, "NM_SETTING_COMPARE_FLAG_IGNORE_ID", "ignore-id" },
+ { NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, "NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS", "ignore-secrets" },
+ { NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS, "NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS", "ignore-agent-owned-secrets" },
+ { NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS, "NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS", "ignore-not-saved-secrets" },
+ { NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT, "NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT", "diff-result-with-default" },
+ { NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT, "NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT", "diff-result-no-default" },
+ { NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP, "NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP", "ignore-timestamp" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMSettingCompareFlags"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_setting_diff_result_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_SETTING_DIFF_RESULT_UNKNOWN, "NM_SETTING_DIFF_RESULT_UNKNOWN", "unknown" },
+ { NM_SETTING_DIFF_RESULT_IN_A, "NM_SETTING_DIFF_RESULT_IN_A", "in-a" },
+ { NM_SETTING_DIFF_RESULT_IN_B, "NM_SETTING_DIFF_RESULT_IN_B", "in-b" },
+ { NM_SETTING_DIFF_RESULT_IN_A_DEFAULT, "NM_SETTING_DIFF_RESULT_IN_A_DEFAULT", "in-a-default" },
+ { NM_SETTING_DIFF_RESULT_IN_B_DEFAULT, "NM_SETTING_DIFF_RESULT_IN_B_DEFAULT", "in-b-default" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMSettingDiffResult"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_utils_security_type_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NMU_SEC_INVALID, "NMU_SEC_INVALID", "invalid" },
+ { NMU_SEC_NONE, "NMU_SEC_NONE", "none" },
+ { NMU_SEC_STATIC_WEP, "NMU_SEC_STATIC_WEP", "static-wep" },
+ { NMU_SEC_LEAP, "NMU_SEC_LEAP", "leap" },
+ { NMU_SEC_DYNAMIC_WEP, "NMU_SEC_DYNAMIC_WEP", "dynamic-wep" },
+ { NMU_SEC_WPA_PSK, "NMU_SEC_WPA_PSK", "wpa-psk" },
+ { NMU_SEC_WPA_ENTERPRISE, "NMU_SEC_WPA_ENTERPRISE", "wpa-enterprise" },
+ { NMU_SEC_WPA2_PSK, "NMU_SEC_WPA2_PSK", "wpa2-psk" },
+ { NMU_SEC_WPA2_ENTERPRISE, "NMU_SEC_WPA2_ENTERPRISE", "wpa2-enterprise" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMUtilsSecurityType"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_vpn_service_state_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_VPN_SERVICE_STATE_UNKNOWN, "NM_VPN_SERVICE_STATE_UNKNOWN", "unknown" },
+ { NM_VPN_SERVICE_STATE_INIT, "NM_VPN_SERVICE_STATE_INIT", "init" },
+ { NM_VPN_SERVICE_STATE_SHUTDOWN, "NM_VPN_SERVICE_STATE_SHUTDOWN", "shutdown" },
+ { NM_VPN_SERVICE_STATE_STARTING, "NM_VPN_SERVICE_STATE_STARTING", "starting" },
+ { NM_VPN_SERVICE_STATE_STARTED, "NM_VPN_SERVICE_STATE_STARTED", "started" },
+ { NM_VPN_SERVICE_STATE_STOPPING, "NM_VPN_SERVICE_STATE_STOPPING", "stopping" },
+ { NM_VPN_SERVICE_STATE_STOPPED, "NM_VPN_SERVICE_STATE_STOPPED", "stopped" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMVpnServiceState"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_vpn_connection_state_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_VPN_CONNECTION_STATE_UNKNOWN, "NM_VPN_CONNECTION_STATE_UNKNOWN", "unknown" },
+ { NM_VPN_CONNECTION_STATE_PREPARE, "NM_VPN_CONNECTION_STATE_PREPARE", "prepare" },
+ { NM_VPN_CONNECTION_STATE_NEED_AUTH, "NM_VPN_CONNECTION_STATE_NEED_AUTH", "need-auth" },
+ { NM_VPN_CONNECTION_STATE_CONNECT, "NM_VPN_CONNECTION_STATE_CONNECT", "connect" },
+ { NM_VPN_CONNECTION_STATE_IP_CONFIG_GET, "NM_VPN_CONNECTION_STATE_IP_CONFIG_GET", "ip-config-get" },
+ { NM_VPN_CONNECTION_STATE_ACTIVATED, "NM_VPN_CONNECTION_STATE_ACTIVATED", "activated" },
+ { NM_VPN_CONNECTION_STATE_FAILED, "NM_VPN_CONNECTION_STATE_FAILED", "failed" },
+ { NM_VPN_CONNECTION_STATE_DISCONNECTED, "NM_VPN_CONNECTION_STATE_DISCONNECTED", "disconnected" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMVpnConnectionState"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_vpn_connection_state_reason_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_VPN_CONNECTION_STATE_REASON_UNKNOWN, "NM_VPN_CONNECTION_STATE_REASON_UNKNOWN", "unknown" },
+ { NM_VPN_CONNECTION_STATE_REASON_NONE, "NM_VPN_CONNECTION_STATE_REASON_NONE", "none" },
+ { NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED, "NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED", "user-disconnected" },
+ { NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED, "NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED", "device-disconnected" },
+ { NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED, "NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED", "service-stopped" },
+ { NM_VPN_CONNECTION_STATE_REASON_IP_CONFIG_INVALID, "NM_VPN_CONNECTION_STATE_REASON_IP_CONFIG_INVALID", "ip-config-invalid" },
+ { NM_VPN_CONNECTION_STATE_REASON_CONNECT_TIMEOUT, "NM_VPN_CONNECTION_STATE_REASON_CONNECT_TIMEOUT", "connect-timeout" },
+ { NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT, "NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT", "service-start-timeout" },
+ { NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED, "NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED", "service-start-failed" },
+ { NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS, "NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS", "no-secrets" },
+ { NM_VPN_CONNECTION_STATE_REASON_LOGIN_FAILED, "NM_VPN_CONNECTION_STATE_REASON_LOGIN_FAILED", "login-failed" },
+ { NM_VPN_CONNECTION_STATE_REASON_CONNECTION_REMOVED, "NM_VPN_CONNECTION_STATE_REASON_CONNECTION_REMOVED", "connection-removed" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMVpnConnectionStateReason"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+GType
+nm_vpn_plugin_failure_get_type (void)
+{
+ static volatile gsize g_define_type_id__volatile = 0;
+
+ if (g_once_init_enter (&g_define_type_id__volatile))
+ {
+ static const GEnumValue values[] = {
+ { NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED, "NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED", "login-failed" },
+ { NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED, "NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED", "connect-failed" },
+ { NM_VPN_PLUGIN_FAILURE_BAD_IP_CONFIG, "NM_VPN_PLUGIN_FAILURE_BAD_IP_CONFIG", "bad-ip-config" },
+ { 0, NULL, NULL }
+ };
+ GType g_define_type_id =
+ g_enum_register_static (g_intern_static_string ("NMVpnPluginFailure"), values);
+ g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+ }
+
+ return g_define_type_id__volatile;
+}
+
+
+
diff --git a/libnm-core/nm-core-enum-types.h b/libnm-core/nm-core-enum-types.h
new file mode 100644
index 000000000..162b704eb
--- /dev/null
+++ b/libnm-core/nm-core-enum-types.h
@@ -0,0 +1,97 @@
+
+
+
+/* Generated by glib-mkenums. Do not edit */
+
+#ifndef __NM_CORE_ENUM_TYPES_H__
+#define __NM_CORE_ENUM_TYPES_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+GType nm_connection_serialization_flags_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_CONNECTION_SERIALIZATION_FLAGS (nm_connection_serialization_flags_get_type ())
+GType nm_state_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_STATE (nm_state_get_type ())
+GType nm_connectivity_state_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_CONNECTIVITY_STATE (nm_connectivity_state_get_type ())
+GType nm_device_type_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_DEVICE_TYPE (nm_device_type_get_type ())
+GType nm_device_capabilities_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_DEVICE_CAPABILITIES (nm_device_capabilities_get_type ())
+GType nm_device_wifi_capabilities_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_DEVICE_WIFI_CAPABILITIES (nm_device_wifi_capabilities_get_type ())
+GType nm_802_11_ap_flags_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_802_11_AP_FLAGS (nm_802_11_ap_flags_get_type ())
+GType nm_802_11_ap_security_flags_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_802_11_AP_SECURITY_FLAGS (nm_802_11_ap_security_flags_get_type ())
+GType nm_802_11_mode_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_802_11_MODE (nm_802_11_mode_get_type ())
+GType nm_bluetooth_capabilities_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_BLUETOOTH_CAPABILITIES (nm_bluetooth_capabilities_get_type ())
+GType nm_device_modem_capabilities_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_DEVICE_MODEM_CAPABILITIES (nm_device_modem_capabilities_get_type ())
+GType nm_device_state_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_DEVICE_STATE (nm_device_state_get_type ())
+GType nm_device_state_reason_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_DEVICE_STATE_REASON (nm_device_state_reason_get_type ())
+GType nm_active_connection_state_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_ACTIVE_CONNECTION_STATE (nm_active_connection_state_get_type ())
+GType nm_secret_agent_get_secrets_flags_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_SECRET_AGENT_GET_SECRETS_FLAGS (nm_secret_agent_get_secrets_flags_get_type ())
+GType nm_secret_agent_capabilities_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_SECRET_AGENT_CAPABILITIES (nm_secret_agent_capabilities_get_type ())
+GType nm_agent_manager_error_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_AGENT_MANAGER_ERROR (nm_agent_manager_error_get_type ())
+GType nm_connection_error_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_CONNECTION_ERROR (nm_connection_error_get_type ())
+GType nm_crypto_error_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_CRYPTO_ERROR (nm_crypto_error_get_type ())
+GType nm_device_error_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_DEVICE_ERROR (nm_device_error_get_type ())
+GType nm_manager_error_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_MANAGER_ERROR (nm_manager_error_get_type ())
+GType nm_secret_agent_error_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_SECRET_AGENT_ERROR (nm_secret_agent_error_get_type ())
+GType nm_settings_error_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_SETTINGS_ERROR (nm_settings_error_get_type ())
+GType nm_vpn_plugin_error_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_VPN_PLUGIN_ERROR (nm_vpn_plugin_error_get_type ())
+GType nm_setting_802_1x_ck_format_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_SETTING_802_1X_CK_FORMAT (nm_setting_802_1x_ck_format_get_type ())
+GType nm_setting_802_1x_ck_scheme_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_SETTING_802_1X_CK_SCHEME (nm_setting_802_1x_ck_scheme_get_type ())
+GType nm_setting_dcb_flags_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_SETTING_DCB_FLAGS (nm_setting_dcb_flags_get_type ())
+GType nm_setting_ip6_config_privacy_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_SETTING_IP6_CONFIG_PRIVACY (nm_setting_ip6_config_privacy_get_type ())
+GType nm_setting_serial_parity_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_SETTING_SERIAL_PARITY (nm_setting_serial_parity_get_type ())
+GType nm_vlan_priority_map_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_VLAN_PRIORITY_MAP (nm_vlan_priority_map_get_type ())
+GType nm_vlan_flags_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_VLAN_FLAGS (nm_vlan_flags_get_type ())
+GType nm_wep_key_type_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_WEP_KEY_TYPE (nm_wep_key_type_get_type ())
+GType nm_setting_secret_flags_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_SETTING_SECRET_FLAGS (nm_setting_secret_flags_get_type ())
+GType nm_setting_compare_flags_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_SETTING_COMPARE_FLAGS (nm_setting_compare_flags_get_type ())
+GType nm_setting_diff_result_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_SETTING_DIFF_RESULT (nm_setting_diff_result_get_type ())
+GType nm_utils_security_type_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_UTILS_SECURITY_TYPE (nm_utils_security_type_get_type ())
+GType nm_vpn_service_state_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_VPN_SERVICE_STATE (nm_vpn_service_state_get_type ())
+GType nm_vpn_connection_state_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_VPN_CONNECTION_STATE (nm_vpn_connection_state_get_type ())
+GType nm_vpn_connection_state_reason_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_VPN_CONNECTION_STATE_REASON (nm_vpn_connection_state_reason_get_type ())
+GType nm_vpn_plugin_failure_get_type (void) G_GNUC_CONST;
+#define NM_TYPE_VPN_PLUGIN_FAILURE (nm_vpn_plugin_failure_get_type ())
+G_END_DECLS
+
+#endif /* __NM_CORE_ENUM_TYPES_H__ */
+
+
+
diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h
new file mode 100644
index 000000000..5af90267a
--- /dev/null
+++ b/libnm-core/nm-core-internal.h
@@ -0,0 +1,135 @@
+/* -*- 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.
+ *
+ * (C) Copyright 2014 Red Hat, Inc.
+ */
+
+#ifndef NM_CORE_NM_INTERNAL_H
+#define NM_CORE_NM_INTERNAL_H
+
+/* This header file contain functions that are provided as private API
+ * by libnm-core. It will contain functions to give privileged access to
+ * libnm-core. This can be useful for NetworkManager and libnm.so
+ * which both are special users of libnm-core.
+ * It also exposes some utility functions for reuse.
+ *
+ * These functions are not exported and are only available to components that link
+ * statically against libnm-core. This basically means libnm-core, libnm, NetworkManager
+ * and some test programs.
+ **/
+
+#include "nm-connection.h"
+#include "nm-core-enum-types.h"
+#include "nm-dbus-interface.h"
+#include "nm-setting-8021x.h"
+#include "nm-setting-adsl.h"
+#include "nm-setting-bluetooth.h"
+#include "nm-setting-bond.h"
+#include "nm-setting-bridge-port.h"
+#include "nm-setting-bridge.h"
+#include "nm-setting-cdma.h"
+#include "nm-setting-connection.h"
+#include "nm-setting-dcb.h"
+#include "nm-setting-generic.h"
+#include "nm-setting-gsm.h"
+#include "nm-setting-infiniband.h"
+#include "nm-setting-ip4-config.h"
+#include "nm-setting-ip6-config.h"
+#include "nm-setting-olpc-mesh.h"
+#include "nm-setting-ppp.h"
+#include "nm-setting-pppoe.h"
+#include "nm-setting-serial.h"
+#include "nm-setting-team-port.h"
+#include "nm-setting-team.h"
+#include "nm-setting-vlan.h"
+#include "nm-setting-vpn.h"
+#include "nm-setting-wimax.h"
+#include "nm-setting-wired.h"
+#include "nm-setting-wireless-security.h"
+#include "nm-setting-wireless.h"
+#include "nm-setting.h"
+#include "nm-simple-connection.h"
+#include "nm-utils.h"
+#include "nm-version.h"
+#include "nm-vpn-dbus-interface.h"
+
+#define NM_UTILS_CLEAR_CANCELLABLE(c) \
+ if (c) { \
+ g_cancellable_cancel (c); \
+ g_clear_object (&c); \
+ }
+
+/* NM_SETTING_COMPARE_FLAG_INFERRABLE: check whether a device-generated
+ * connection can be replaced by a already-defined connection. This flag only
+ * takes into account properties marked with the %NM_SETTING_PARAM_INFERRABLE
+ * flag.
+ */
+#define NM_SETTING_COMPARE_FLAG_INFERRABLE 0x80000000
+
+
+
+#define NM_SETTING_SECRET_FLAGS_ALL \
+ (NM_SETTING_SECRET_FLAG_NONE | \
+ NM_SETTING_SECRET_FLAG_AGENT_OWNED | \
+ NM_SETTING_SECRET_FLAG_NOT_SAVED | \
+ NM_SETTING_SECRET_FLAG_NOT_REQUIRED)
+
+guint32 _nm_setting_get_setting_priority (NMSetting *setting);
+
+gboolean _nm_setting_get_property (NMSetting *setting, const char *name, GValue *value);
+
+GSList * _nm_utils_hash_values_to_slist (GHashTable *hash);
+
+GHashTable *_nm_utils_copy_strdict (GHashTable *strdict);
+
+typedef gpointer (*NMUtilsCopyFunc) (gpointer);
+
+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);
+GPtrArray *_nm_utils_copy_object_array (const GPtrArray *array);
+
+gboolean _nm_utils_string_in_list (const char *str,
+ const char **valid_strings);
+
+char ** _nm_utils_strsplit_set (const char *str,
+ const char *delimiters,
+ int max_tokens);
+
+#define NM_UTILS_UUID_TYPE_LEGACY 0
+#define NM_UTILS_UUID_TYPE_VARIANT3 1
+
+char *nm_utils_uuid_generate_from_string (const char *s, gssize slen, int uuid_type, gpointer type_args);
+
+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);
+
+#endif
diff --git a/libnm-core/nm-core-types.h b/libnm-core/nm-core-types.h
new file mode 100644
index 000000000..524d6396c
--- /dev/null
+++ b/libnm-core/nm-core-types.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager -- Network link manager
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2014 Red Hat, Inc.
+ */
+
+#ifndef __NM_CORE_TYPES_H__
+#define __NM_CORE_TYPES_H__
+
+#include <glib-object.h>
+
+#include <nm-dbus-interface.h>
+#include <nm-core-enum-types.h>
+
+typedef struct _NMConnection NMConnection;
+typedef struct _NMSetting NMSetting;
+typedef struct _NMSetting8021x NMSetting8021x;
+typedef struct _NMSettingAdsl NMSettingAdsl;
+typedef struct _NMSettingBluetooth NMSettingBluetooth;
+typedef struct _NMSettingBond NMSettingBond;
+typedef struct _NMSettingBridge NMSettingBridge;
+typedef struct _NMSettingBridgePort NMSettingBridgePort;
+typedef struct _NMSettingCdma NMSettingCdma;
+typedef struct _NMSettingConnection NMSettingConnection;
+typedef struct _NMSettingDcb NMSettingDcb;
+typedef struct _NMSettingGeneric NMSettingGeneric;
+typedef struct _NMSettingGsm NMSettingGsm;
+typedef struct _NMSettingInfiniband NMSettingInfiniband;
+typedef struct _NMSettingIPConfig NMSettingIPConfig;
+typedef struct _NMSettingIP4Config NMSettingIP4Config;
+typedef struct _NMSettingIP6Config NMSettingIP6Config;
+typedef struct _NMSettingOlpcMesh NMSettingOlpcMesh;
+typedef struct _NMSettingPpp NMSettingPpp;
+typedef struct _NMSettingPppoe NMSettingPppoe;
+typedef struct _NMSettingSerial NMSettingSerial;
+typedef struct _NMSettingTeam NMSettingTeam;
+typedef struct _NMSettingTeamPort NMSettingTeamPort;
+typedef struct _NMSettingVlan NMSettingVlan;
+typedef struct _NMSettingVpn NMSettingVpn;
+typedef struct _NMSettingWimax NMSettingWimax;
+typedef struct _NMSettingWired NMSettingWired;
+typedef struct _NMSettingWireless NMSettingWireless;
+typedef struct _NMSettingWirelessSecurity NMSettingWirelessSecurity;
+typedef struct _NMSimpleConnection NMSimpleConnection;
+
+#endif /* __NM_CORE_TYPES_H__ */
diff --git a/libnm-core/nm-dbus-interface.h b/libnm-core/nm-dbus-interface.h
new file mode 100644
index 000000000..dd2b70a0d
--- /dev/null
+++ b/libnm-core/nm-dbus-interface.h
@@ -0,0 +1,611 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2004 - 2014 Red Hat, Inc.
+ */
+
+/* Definitions related to NetworkManager's D-Bus interfaces.
+ *
+ * Note that although this header is installed as part of libnm, it is also
+ * used by some external code that does not link to libnm.
+ */
+
+#ifndef __NM_DBUS_INTERFACE_H__
+#define __NM_DBUS_INTERFACE_H__
+
+#include "nm-version.h"
+
+/*
+ * dbus services details
+ */
+#define NM_DBUS_SERVICE "org.freedesktop.NetworkManager"
+
+#define NM_DBUS_PATH "/org/freedesktop/NetworkManager"
+#define NM_DBUS_INTERFACE "org.freedesktop.NetworkManager"
+#define NM_DBUS_INTERFACE_DEVICE NM_DBUS_INTERFACE ".Device"
+#define NM_DBUS_INTERFACE_DEVICE_WIRED NM_DBUS_INTERFACE_DEVICE ".Wired"
+#define NM_DBUS_INTERFACE_DEVICE_ADSL NM_DBUS_INTERFACE_DEVICE ".Adsl"
+#define NM_DBUS_INTERFACE_DEVICE_WIRELESS NM_DBUS_INTERFACE_DEVICE ".Wireless"
+#define NM_DBUS_INTERFACE_DEVICE_BLUETOOTH NM_DBUS_INTERFACE_DEVICE ".Bluetooth"
+#define NM_DBUS_INTERFACE_DEVICE_OLPC_MESH NM_DBUS_INTERFACE_DEVICE ".OlpcMesh"
+#define NM_DBUS_PATH_ACCESS_POINT NM_DBUS_PATH "/AccessPoint"
+#define NM_DBUS_INTERFACE_ACCESS_POINT NM_DBUS_INTERFACE ".AccessPoint"
+#define NM_DBUS_INTERFACE_DEVICE_MODEM NM_DBUS_INTERFACE_DEVICE ".Modem"
+#define NM_DBUS_INTERFACE_DEVICE_WIMAX NM_DBUS_INTERFACE_DEVICE ".WiMax"
+#define NM_DBUS_INTERFACE_WIMAX_NSP NM_DBUS_INTERFACE ".WiMax.Nsp"
+#define NM_DBUS_PATH_WIMAX_NSP NM_DBUS_PATH "/Nsp"
+#define NM_DBUS_INTERFACE_ACTIVE_CONNECTION NM_DBUS_INTERFACE ".Connection.Active"
+#define NM_DBUS_INTERFACE_IP4_CONFIG NM_DBUS_INTERFACE ".IP4Config"
+#define NM_DBUS_INTERFACE_DHCP4_CONFIG NM_DBUS_INTERFACE ".DHCP4Config"
+#define NM_DBUS_INTERFACE_IP6_CONFIG NM_DBUS_INTERFACE ".IP6Config"
+#define NM_DBUS_INTERFACE_DHCP6_CONFIG NM_DBUS_INTERFACE ".DHCP6Config"
+#define NM_DBUS_INTERFACE_DEVICE_INFINIBAND NM_DBUS_INTERFACE_DEVICE ".Infiniband"
+#define NM_DBUS_INTERFACE_DEVICE_BOND NM_DBUS_INTERFACE_DEVICE ".Bond"
+#define NM_DBUS_INTERFACE_DEVICE_TEAM NM_DBUS_INTERFACE_DEVICE ".Team"
+#define NM_DBUS_INTERFACE_DEVICE_VLAN NM_DBUS_INTERFACE_DEVICE ".Vlan"
+#define NM_DBUS_INTERFACE_DEVICE_BRIDGE NM_DBUS_INTERFACE_DEVICE ".Bridge"
+#define NM_DBUS_INTERFACE_DEVICE_GENERIC NM_DBUS_INTERFACE_DEVICE ".Generic"
+#define NM_DBUS_INTERFACE_DEVICE_VETH NM_DBUS_INTERFACE_DEVICE ".Veth"
+#define NM_DBUS_INTERFACE_DEVICE_TUN NM_DBUS_INTERFACE_DEVICE ".Tun"
+#define NM_DBUS_INTERFACE_DEVICE_MACVLAN NM_DBUS_INTERFACE_DEVICE ".Macvlan"
+#define NM_DBUS_INTERFACE_DEVICE_VXLAN NM_DBUS_INTERFACE_DEVICE ".Vxlan"
+#define NM_DBUS_INTERFACE_DEVICE_GRE NM_DBUS_INTERFACE_DEVICE ".Gre"
+
+
+#define NM_DBUS_INTERFACE_SETTINGS "org.freedesktop.NetworkManager.Settings"
+#define NM_DBUS_PATH_SETTINGS "/org/freedesktop/NetworkManager/Settings"
+
+#define NM_DBUS_INTERFACE_SETTINGS_CONNECTION "org.freedesktop.NetworkManager.Settings.Connection"
+#define NM_DBUS_PATH_SETTINGS_CONNECTION "/org/freedesktop/NetworkManager/Settings/Connection"
+#define NM_DBUS_INTERFACE_SETTINGS_CONNECTION_SECRETS "org.freedesktop.NetworkManager.Settings.Connection.Secrets"
+
+#define NM_DBUS_INTERFACE_AGENT_MANAGER NM_DBUS_INTERFACE ".AgentManager"
+#define NM_DBUS_PATH_AGENT_MANAGER "/org/freedesktop/NetworkManager/AgentManager"
+
+#define NM_DBUS_INTERFACE_SECRET_AGENT NM_DBUS_INTERFACE ".SecretAgent"
+#define NM_DBUS_PATH_SECRET_AGENT "/org/freedesktop/NetworkManager/SecretAgent"
+
+/**
+ * NMState:
+ * @NM_STATE_UNKNOWN: networking state is unknown
+ * @NM_STATE_ASLEEP: networking is not enabled
+ * @NM_STATE_DISCONNECTED: there is no active network connection
+ * @NM_STATE_DISCONNECTING: network connections are being cleaned up
+ * @NM_STATE_CONNECTING: a network connection is being started
+ * @NM_STATE_CONNECTED_LOCAL: there is only local IPv4 and/or IPv6 connectivity
+ * @NM_STATE_CONNECTED_SITE: there is only site-wide IPv4 and/or IPv6 connectivity
+ * @NM_STATE_CONNECTED_GLOBAL: there is global IPv4 and/or IPv6 Internet connectivity
+ *
+ * #NMState values indicate the current overall networking state.
+ *
+ * (Corresponds to the NM_STATE type in nm-manager.xml.)
+ **/
+typedef enum {
+ NM_STATE_UNKNOWN = 0,
+ NM_STATE_ASLEEP = 10,
+ NM_STATE_DISCONNECTED = 20,
+ NM_STATE_DISCONNECTING = 30,
+ NM_STATE_CONNECTING = 40,
+ NM_STATE_CONNECTED_LOCAL = 50,
+ NM_STATE_CONNECTED_SITE = 60,
+ NM_STATE_CONNECTED_GLOBAL = 70
+} NMState;
+
+/**
+ * NMConnectivityState:
+ * @NM_CONNECTIVITY_UNKNOWN: Network connectivity is unknown.
+ * @NM_CONNECTIVITY_NONE: The host is not connected to any network.
+ * @NM_CONNECTIVITY_PORTAL: The host is behind a captive portal and
+ * cannot reach the full Internet.
+ * @NM_CONNECTIVITY_LIMITED: The host is connected to a network, but
+ * does not appear to be able to reach the full Internet.
+ * @NM_CONNECTIVITY_FULL: The host is connected to a network, and
+ * appears to be able to reach the full Internet.
+ *
+ * (Corresponds to the NM_CONNECTIVITY type in nm-manager.xml.)
+ */
+typedef enum {
+ NM_CONNECTIVITY_UNKNOWN,
+ NM_CONNECTIVITY_NONE,
+ NM_CONNECTIVITY_PORTAL,
+ NM_CONNECTIVITY_LIMITED,
+ NM_CONNECTIVITY_FULL
+} NMConnectivityState;
+
+/**
+ * NMDeviceType:
+ * @NM_DEVICE_TYPE_UNKNOWN: unknown device
+ * @NM_DEVICE_TYPE_GENERIC: generic support for unrecognized device types
+ * @NM_DEVICE_TYPE_ETHERNET: a wired ethernet device
+ * @NM_DEVICE_TYPE_WIFI: an 802.11 WiFi device
+ * @NM_DEVICE_TYPE_UNUSED1: not used
+ * @NM_DEVICE_TYPE_UNUSED2: not used
+ * @NM_DEVICE_TYPE_BT: a Bluetooth device supporting PAN or DUN access protocols
+ * @NM_DEVICE_TYPE_OLPC_MESH: an OLPC XO mesh networking device
+ * @NM_DEVICE_TYPE_WIMAX: an 802.16e Mobile WiMAX broadband device
+ * @NM_DEVICE_TYPE_MODEM: a modem supporting analog telephone, CDMA/EVDO,
+ * GSM/UMTS, or LTE network access protocols
+ * @NM_DEVICE_TYPE_INFINIBAND: an IP-over-InfiniBand device
+ * @NM_DEVICE_TYPE_BOND: a bond master interface
+ * @NM_DEVICE_TYPE_VLAN: an 802.1Q VLAN interface
+ * @NM_DEVICE_TYPE_ADSL: ADSL modem
+ * @NM_DEVICE_TYPE_BRIDGE: a bridge master interface
+ * @NM_DEVICE_TYPE_TEAM: a team master interface
+ *
+ * #NMDeviceType values indicate the type of hardware represented by
+ * an #NMDevice.
+ *
+ * (Corresponds to the NM_DEVICE_TYPE type in nm-device.xml.)
+ **/
+typedef enum {
+ NM_DEVICE_TYPE_UNKNOWN = 0,
+ NM_DEVICE_TYPE_ETHERNET = 1,
+ NM_DEVICE_TYPE_WIFI = 2,
+ NM_DEVICE_TYPE_UNUSED1 = 3,
+ NM_DEVICE_TYPE_UNUSED2 = 4,
+ NM_DEVICE_TYPE_BT = 5, /* Bluetooth */
+ NM_DEVICE_TYPE_OLPC_MESH = 6,
+ NM_DEVICE_TYPE_WIMAX = 7,
+ NM_DEVICE_TYPE_MODEM = 8,
+ NM_DEVICE_TYPE_INFINIBAND = 9,
+ NM_DEVICE_TYPE_BOND = 10,
+ NM_DEVICE_TYPE_VLAN = 11,
+ NM_DEVICE_TYPE_ADSL = 12,
+ NM_DEVICE_TYPE_BRIDGE = 13,
+ NM_DEVICE_TYPE_GENERIC = 14,
+ NM_DEVICE_TYPE_TEAM = 15,
+} NMDeviceType;
+
+/**
+ * NMDeviceCapabilities:
+ * @NM_DEVICE_CAP_NONE: device has no special capabilities
+ * @NM_DEVICE_CAP_NM_SUPPORTED: NetworkManager supports this device
+ * @NM_DEVICE_CAP_CARRIER_DETECT: this device can indicate carrier status
+ * @NM_DEVICE_CAP_IS_SOFTWARE: this device is a software device
+ *
+ * General device capability flags.
+ *
+ * (Corresponds to the NM_DEVICE_CAP type in nm-device-wifi.xml.)
+ **/
+typedef enum { /*< flags >*/
+ NM_DEVICE_CAP_NONE = 0x00000000,
+ NM_DEVICE_CAP_NM_SUPPORTED = 0x00000001,
+ NM_DEVICE_CAP_CARRIER_DETECT = 0x00000002,
+ NM_DEVICE_CAP_IS_SOFTWARE = 0x00000004,
+} NMDeviceCapabilities;
+
+
+/**
+ * NMDeviceWifiCapabilities:
+ * @NM_WIFI_DEVICE_CAP_NONE: device has no encryption/authentication capabilities
+ * @NM_WIFI_DEVICE_CAP_CIPHER_WEP40: device supports 40/64-bit WEP encryption
+ * @NM_WIFI_DEVICE_CAP_CIPHER_WEP104: device supports 104/128-bit WEP encryption
+ * @NM_WIFI_DEVICE_CAP_CIPHER_TKIP: device supports TKIP encryption
+ * @NM_WIFI_DEVICE_CAP_CIPHER_CCMP: device supports AES/CCMP encryption
+ * @NM_WIFI_DEVICE_CAP_WPA: device supports WPA1 authentication
+ * @NM_WIFI_DEVICE_CAP_RSN: device supports WPA2/RSN authentication
+ * @NM_WIFI_DEVICE_CAP_AP: device supports Access Point mode
+ * @NM_WIFI_DEVICE_CAP_ADHOC: device supports Ad-Hoc mode
+ *
+ * 802.11 specific device encryption and authentication capabilities.
+ *
+ * (Corresponds to the NM_802_11_DEVICE_CAP type in nm-device-wifi.xml.)
+ **/
+typedef enum { /*< flags >*/
+ NM_WIFI_DEVICE_CAP_NONE = 0x00000000,
+ NM_WIFI_DEVICE_CAP_CIPHER_WEP40 = 0x00000001,
+ NM_WIFI_DEVICE_CAP_CIPHER_WEP104 = 0x00000002,
+ NM_WIFI_DEVICE_CAP_CIPHER_TKIP = 0x00000004,
+ NM_WIFI_DEVICE_CAP_CIPHER_CCMP = 0x00000008,
+ NM_WIFI_DEVICE_CAP_WPA = 0x00000010,
+ NM_WIFI_DEVICE_CAP_RSN = 0x00000020,
+ NM_WIFI_DEVICE_CAP_AP = 0x00000040,
+ NM_WIFI_DEVICE_CAP_ADHOC = 0x00000080
+} NMDeviceWifiCapabilities;
+
+
+/**
+ * NM80211ApFlags:
+ * @NM_802_11_AP_FLAGS_NONE: access point has no special capabilities
+ * @NM_802_11_AP_FLAGS_PRIVACY: access point requires authentication and
+ * encryption (usually means WEP)
+ *
+ * 802.11 access point flags.
+ *
+ * (Corresponds to the NM_802_11_AP_FLAGS type in nm-access-point.xml.)
+ **/
+typedef enum { /*< underscore_name=nm_802_11_ap_flags, flags >*/
+ NM_802_11_AP_FLAGS_NONE = 0x00000000,
+ NM_802_11_AP_FLAGS_PRIVACY = 0x00000001
+} NM80211ApFlags;
+
+/**
+ * NM80211ApSecurityFlags:
+ * @NM_802_11_AP_SEC_NONE: the access point has no special security requirements
+ * @NM_802_11_AP_SEC_PAIR_WEP40: 40/64-bit WEP is supported for
+ * pairwise/unicast encryption
+ * @NM_802_11_AP_SEC_PAIR_WEP104: 104/128-bit WEP is supported for
+ * pairwise/unicast encryption
+ * @NM_802_11_AP_SEC_PAIR_TKIP: TKIP is supported for pairwise/unicast encryption
+ * @NM_802_11_AP_SEC_PAIR_CCMP: AES/CCMP is supported for pairwise/unicast encryption
+ * @NM_802_11_AP_SEC_GROUP_WEP40: 40/64-bit WEP is supported for group/broadcast
+ * encryption
+ * @NM_802_11_AP_SEC_GROUP_WEP104: 104/128-bit WEP is supported for
+ * group/broadcast encryption
+ * @NM_802_11_AP_SEC_GROUP_TKIP: TKIP is supported for group/broadcast encryption
+ * @NM_802_11_AP_SEC_GROUP_CCMP: AES/CCMP is supported for group/broadcast
+ * encryption
+ * @NM_802_11_AP_SEC_KEY_MGMT_PSK: WPA/RSN Pre-Shared Key encryption is
+ * supported
+ * @NM_802_11_AP_SEC_KEY_MGMT_802_1X: 802.1x authentication and key management
+ * is supported
+ *
+ * 802.11 access point security and authentication flags. These flags describe
+ * the current security requirements of an access point as determined from the
+ * access point's beacon.
+ *
+ * (Corresponds to the NM_802_11_AP_SEC type in nm-access-point.xml.)
+ **/
+typedef enum { /*< underscore_name=nm_802_11_ap_security_flags, flags >*/
+ NM_802_11_AP_SEC_NONE = 0x00000000,
+ NM_802_11_AP_SEC_PAIR_WEP40 = 0x00000001,
+ NM_802_11_AP_SEC_PAIR_WEP104 = 0x00000002,
+ NM_802_11_AP_SEC_PAIR_TKIP = 0x00000004,
+ NM_802_11_AP_SEC_PAIR_CCMP = 0x00000008,
+ NM_802_11_AP_SEC_GROUP_WEP40 = 0x00000010,
+ NM_802_11_AP_SEC_GROUP_WEP104 = 0x00000020,
+ NM_802_11_AP_SEC_GROUP_TKIP = 0x00000040,
+ NM_802_11_AP_SEC_GROUP_CCMP = 0x00000080,
+ NM_802_11_AP_SEC_KEY_MGMT_PSK = 0x00000100,
+ NM_802_11_AP_SEC_KEY_MGMT_802_1X = 0x00000200
+} NM80211ApSecurityFlags;
+
+/**
+ * NM80211Mode:
+ * @NM_802_11_MODE_UNKNOWN: the device or access point mode is unknown
+ * @NM_802_11_MODE_ADHOC: for both devices and access point objects, indicates
+ * the object is part of an Ad-Hoc 802.11 network without a central
+ * coordinating access point.
+ * @NM_802_11_MODE_INFRA: the device or access point is in infrastructure mode.
+ * For devices, this indicates the device is an 802.11 client/station. For
+ * access point objects, this indicates the object is an access point that
+ * provides connectivity to clients.
+ * @NM_802_11_MODE_AP: the device is an access point/hotspot. Not valid for
+ * access point objects; used only for hotspot mode on the local machine.
+ *
+ * Indicates the 802.11 mode an access point or device is currently in.
+ *
+ * (Corresponds to the NM_802_11_MODE type in generic-types.xml.)
+ **/
+typedef enum { /*< underscore_name=nm_802_11_mode >*/
+ NM_802_11_MODE_UNKNOWN = 0,
+ NM_802_11_MODE_ADHOC,
+ NM_802_11_MODE_INFRA,
+ NM_802_11_MODE_AP
+} NM80211Mode;
+
+/**
+ * NMBluetoothCapabilities:
+ * @NM_BT_CAPABILITY_NONE: device has no usable capabilities
+ * @NM_BT_CAPABILITY_DUN: device provides Dial-Up Networking capability
+ * @NM_BT_CAPABILITY_NAP: device provides Network Access Point capability
+ *
+ * #NMBluetoothCapabilities values indicate the usable capabilities of a
+ * Bluetooth device.
+ *
+ * (Corresponds to the NM_BT_CAPABILITY type in nm-device-bt.xml.)
+ **/
+typedef enum { /*< flags >*/
+ NM_BT_CAPABILITY_NONE = 0x00000000,
+ NM_BT_CAPABILITY_DUN = 0x00000001,
+ NM_BT_CAPABILITY_NAP = 0x00000002,
+} NMBluetoothCapabilities;
+
+/**
+ * NMDeviceModemCapabilities:
+ * @NM_DEVICE_MODEM_CAPABILITY_NONE: modem has no usable capabilities
+ * @NM_DEVICE_MODEM_CAPABILITY_POTS: modem uses the analog wired telephone
+ * network and is not a wireless/cellular device
+ * @NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO: modem supports at least one of CDMA
+ * 1xRTT, EVDO revision 0, EVDO revision A, or EVDO revision B
+ * @NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS: modem supports at least one of GSM,
+ * GPRS, EDGE, UMTS, HSDPA, HSUPA, or HSPA+ packet switched data capability
+ * @NM_DEVICE_MODEM_CAPABILITY_LTE: modem has LTE data capability
+ *
+ * #NMDeviceModemCapabilities values indicate the generic radio access
+ * technology families a modem device supports. For more information on the
+ * specific access technologies the device supports use the ModemManager D-Bus
+ * API.
+ *
+ * (Corresponds to the NM_DEVICE_MODEM_CAPABILITY type in nm-device-modem.xml.)
+ **/
+typedef enum { /*< flags >*/
+ NM_DEVICE_MODEM_CAPABILITY_NONE = 0x00000000,
+ NM_DEVICE_MODEM_CAPABILITY_POTS = 0x00000001,
+ NM_DEVICE_MODEM_CAPABILITY_CDMA_EVDO = 0x00000002,
+ NM_DEVICE_MODEM_CAPABILITY_GSM_UMTS = 0x00000004,
+ NM_DEVICE_MODEM_CAPABILITY_LTE = 0x00000008,
+} NMDeviceModemCapabilities;
+
+
+/**
+ * NMDeviceState:
+ * @NM_DEVICE_STATE_UNKNOWN: the device's state is unknown
+ * @NM_DEVICE_STATE_UNMANAGED: the device is recognized, but not managed by
+ * NetworkManager
+ * @NM_DEVICE_STATE_UNAVAILABLE: the device is managed by NetworkManager, but
+ * is not available for use. Reasons may include the wireless switched off,
+ * missing firmware, no ethernet carrier, missing supplicant or modem manager,
+ * etc.
+ * @NM_DEVICE_STATE_DISCONNECTED: the device can be activated, but is currently
+ * idle and not connected to a network.
+ * @NM_DEVICE_STATE_PREPARE: the device is preparing the connection to the
+ * network. This may include operations like changing the MAC address,
+ * setting physical link properties, and anything else required to connect
+ * to the requested network.
+ * @NM_DEVICE_STATE_CONFIG: the device is connecting to the requested network.
+ * This may include operations like associating with the WiFi AP, dialing
+ * the modem, connecting to the remote Bluetooth device, etc.
+ * @NM_DEVICE_STATE_NEED_AUTH: the device requires more information to continue
+ * connecting to the requested network. This includes secrets like WiFi
+ * passphrases, login passwords, PIN codes, etc.
+ * @NM_DEVICE_STATE_IP_CONFIG: the device is requesting IPv4 and/or IPv6
+ * addresses and routing information from the network.
+ * @NM_DEVICE_STATE_IP_CHECK: the device is checking whether further action is
+ * required for the requested network connection. This may include checking
+ * whether only local network access is available, whether a captive portal
+ * is blocking access to the Internet, etc.
+ * @NM_DEVICE_STATE_SECONDARIES: the device is waiting for a secondary
+ * connection (like a VPN) which must activated before the device can be
+ * activated
+ * @NM_DEVICE_STATE_ACTIVATED: the device has a network connection, either local
+ * or global.
+ * @NM_DEVICE_STATE_DEACTIVATING: a disconnection from the current network
+ * connection was requested, and the device is cleaning up resources used for
+ * that connection. The network connection may still be valid.
+ * @NM_DEVICE_STATE_FAILED: the device failed to connect to the requested
+ * network and is cleaning up the connection request
+ *
+ * (Corresponds to the NM_DEVICE_STATE type in nm-device.xml.)
+ **/
+typedef enum {
+ NM_DEVICE_STATE_UNKNOWN = 0,
+ NM_DEVICE_STATE_UNMANAGED = 10,
+ NM_DEVICE_STATE_UNAVAILABLE = 20,
+ NM_DEVICE_STATE_DISCONNECTED = 30,
+ NM_DEVICE_STATE_PREPARE = 40,
+ NM_DEVICE_STATE_CONFIG = 50,
+ NM_DEVICE_STATE_NEED_AUTH = 60,
+ NM_DEVICE_STATE_IP_CONFIG = 70,
+ NM_DEVICE_STATE_IP_CHECK = 80,
+ NM_DEVICE_STATE_SECONDARIES = 90,
+ NM_DEVICE_STATE_ACTIVATED = 100,
+ NM_DEVICE_STATE_DEACTIVATING = 110,
+ NM_DEVICE_STATE_FAILED = 120
+} NMDeviceState;
+
+
+/**
+ * NMDeviceStateReason:
+ * @NM_DEVICE_STATE_REASON_NONE: No reason given
+ * @NM_DEVICE_STATE_REASON_UNKNOWN: Unknown error
+ * @NM_DEVICE_STATE_REASON_NOW_MANAGED: Device is now managed
+ * @NM_DEVICE_STATE_REASON_NOW_UNMANAGED: Device is now unmanaged
+ * @NM_DEVICE_STATE_REASON_CONFIG_FAILED: The device could not be readied for configuration
+ * @NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE: IP configuration could not be reserved (no available address, timeout, etc)
+ * @NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED: The IP config is no longer valid
+ * @NM_DEVICE_STATE_REASON_NO_SECRETS: Secrets were required, but not provided
+ * @NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT: 802.1x supplicant disconnected
+ * @NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED: 802.1x supplicant configuration failed
+ * @NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED: 802.1x supplicant failed
+ * @NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT: 802.1x supplicant took too long to authenticate
+ * @NM_DEVICE_STATE_REASON_PPP_START_FAILED: PPP service failed to start
+ * @NM_DEVICE_STATE_REASON_PPP_DISCONNECT: PPP service disconnected
+ * @NM_DEVICE_STATE_REASON_PPP_FAILED: PPP failed
+ * @NM_DEVICE_STATE_REASON_DHCP_START_FAILED: DHCP client failed to start
+ * @NM_DEVICE_STATE_REASON_DHCP_ERROR: DHCP client error
+ * @NM_DEVICE_STATE_REASON_DHCP_FAILED: DHCP client failed
+ * @NM_DEVICE_STATE_REASON_SHARED_START_FAILED: Shared connection service failed to start
+ * @NM_DEVICE_STATE_REASON_SHARED_FAILED: Shared connection service failed
+ * @NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED: AutoIP service failed to start
+ * @NM_DEVICE_STATE_REASON_AUTOIP_ERROR: AutoIP service error
+ * @NM_DEVICE_STATE_REASON_AUTOIP_FAILED: AutoIP service failed
+ * @NM_DEVICE_STATE_REASON_MODEM_BUSY: The line is busy
+ * @NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE: No dial tone
+ * @NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER: No carrier could be established
+ * @NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT: The dialing request timed out
+ * @NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED: The dialing attempt failed
+ * @NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED: Modem initialization failed
+ * @NM_DEVICE_STATE_REASON_GSM_APN_FAILED: Failed to select the specified APN
+ * @NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING: Not searching for networks
+ * @NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED: Network registration denied
+ * @NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT: Network registration timed out
+ * @NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED: Failed to register with the requested network
+ * @NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED: PIN check failed
+ * @NM_DEVICE_STATE_REASON_FIRMWARE_MISSING: Necessary firmware for the device may be missing
+ * @NM_DEVICE_STATE_REASON_REMOVED: The device was removed
+ * @NM_DEVICE_STATE_REASON_SLEEPING: NetworkManager went to sleep
+ * @NM_DEVICE_STATE_REASON_CONNECTION_REMOVED: The device's active connection disappeared
+ * @NM_DEVICE_STATE_REASON_USER_REQUESTED: Device disconnected by user or client
+ * @NM_DEVICE_STATE_REASON_CARRIER: Carrier/link changed
+ * @NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED: The device's existing connection was assumed
+ * @NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE: The supplicant is now available
+ * @NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND: The modem could not be found
+ * @NM_DEVICE_STATE_REASON_BT_FAILED: The Bluetooth connection failed or timed out
+ * @NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED: GSM Modem's SIM Card not inserted
+ * @NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED: GSM Modem's SIM Pin required
+ * @NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED: GSM Modem's SIM Puk required
+ * @NM_DEVICE_STATE_REASON_GSM_SIM_WRONG: GSM Modem's SIM wrong
+ * @NM_DEVICE_STATE_REASON_INFINIBAND_MODE: InfiniBand device does not support connected mode
+ * @NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED: A dependency of the connection failed
+ * @NM_DEVICE_STATE_REASON_BR2684_FAILED: Problem with the RFC 2684 Ethernet over ADSL bridge
+ * @NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE: ModemManager not running
+ * @NM_DEVICE_STATE_REASON_SSID_NOT_FOUND: The WiFi network could not be found
+ * @NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED: A secondary connection of the base connection failed
+ * @NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED: DCB or FCoE setup failed
+ * @NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED: teamd control failed
+ * @NM_DEVICE_STATE_REASON_MODEM_FAILED: Modem failed or no longer available
+ * @NM_DEVICE_STATE_REASON_MODEM_AVAILABLE: Modem now ready and available
+ * @NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT: SIM PIN was incorrect
+ *
+ * Device state change reason codes
+ *
+ * (Corresponds to the NM_DEVICE_STATE_REASON type in nm-device.xml.)
+ */
+typedef enum {
+ NM_DEVICE_STATE_REASON_NONE = 0,
+ NM_DEVICE_STATE_REASON_UNKNOWN = 1,
+ NM_DEVICE_STATE_REASON_NOW_MANAGED = 2,
+ NM_DEVICE_STATE_REASON_NOW_UNMANAGED = 3,
+ NM_DEVICE_STATE_REASON_CONFIG_FAILED = 4,
+ NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE = 5,
+ NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED = 6,
+ NM_DEVICE_STATE_REASON_NO_SECRETS = 7,
+ NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT = 8,
+ NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED = 9,
+ NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED = 10,
+ NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT = 11,
+ NM_DEVICE_STATE_REASON_PPP_START_FAILED = 12,
+ NM_DEVICE_STATE_REASON_PPP_DISCONNECT = 13,
+ NM_DEVICE_STATE_REASON_PPP_FAILED = 14,
+ NM_DEVICE_STATE_REASON_DHCP_START_FAILED = 15,
+ NM_DEVICE_STATE_REASON_DHCP_ERROR = 16,
+ NM_DEVICE_STATE_REASON_DHCP_FAILED = 17,
+ NM_DEVICE_STATE_REASON_SHARED_START_FAILED = 18,
+ NM_DEVICE_STATE_REASON_SHARED_FAILED = 19,
+ NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED = 20,
+ NM_DEVICE_STATE_REASON_AUTOIP_ERROR = 21,
+ NM_DEVICE_STATE_REASON_AUTOIP_FAILED = 22,
+ NM_DEVICE_STATE_REASON_MODEM_BUSY = 23,
+ NM_DEVICE_STATE_REASON_MODEM_NO_DIAL_TONE = 24,
+ NM_DEVICE_STATE_REASON_MODEM_NO_CARRIER = 25,
+ NM_DEVICE_STATE_REASON_MODEM_DIAL_TIMEOUT = 26,
+ NM_DEVICE_STATE_REASON_MODEM_DIAL_FAILED = 27,
+ NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED = 28,
+ NM_DEVICE_STATE_REASON_GSM_APN_FAILED = 29,
+ NM_DEVICE_STATE_REASON_GSM_REGISTRATION_NOT_SEARCHING = 30,
+ NM_DEVICE_STATE_REASON_GSM_REGISTRATION_DENIED = 31,
+ NM_DEVICE_STATE_REASON_GSM_REGISTRATION_TIMEOUT = 32,
+ NM_DEVICE_STATE_REASON_GSM_REGISTRATION_FAILED = 33,
+ NM_DEVICE_STATE_REASON_GSM_PIN_CHECK_FAILED = 34,
+ NM_DEVICE_STATE_REASON_FIRMWARE_MISSING = 35,
+ NM_DEVICE_STATE_REASON_REMOVED = 36,
+ NM_DEVICE_STATE_REASON_SLEEPING = 37,
+ NM_DEVICE_STATE_REASON_CONNECTION_REMOVED = 38,
+ NM_DEVICE_STATE_REASON_USER_REQUESTED = 39,
+ NM_DEVICE_STATE_REASON_CARRIER = 40,
+ NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED = 41,
+ NM_DEVICE_STATE_REASON_SUPPLICANT_AVAILABLE = 42,
+ NM_DEVICE_STATE_REASON_MODEM_NOT_FOUND = 43,
+ NM_DEVICE_STATE_REASON_BT_FAILED = 44,
+ NM_DEVICE_STATE_REASON_GSM_SIM_NOT_INSERTED = 45,
+ NM_DEVICE_STATE_REASON_GSM_SIM_PIN_REQUIRED = 46,
+ NM_DEVICE_STATE_REASON_GSM_SIM_PUK_REQUIRED = 47,
+ NM_DEVICE_STATE_REASON_GSM_SIM_WRONG = 48,
+ NM_DEVICE_STATE_REASON_INFINIBAND_MODE = 49,
+ NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED = 50,
+ NM_DEVICE_STATE_REASON_BR2684_FAILED = 51,
+ NM_DEVICE_STATE_REASON_MODEM_MANAGER_UNAVAILABLE = 52,
+ NM_DEVICE_STATE_REASON_SSID_NOT_FOUND = 53,
+ NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED = 54,
+ NM_DEVICE_STATE_REASON_DCB_FCOE_FAILED = 55,
+ NM_DEVICE_STATE_REASON_TEAMD_CONTROL_FAILED = 56,
+ NM_DEVICE_STATE_REASON_MODEM_FAILED = 57,
+ NM_DEVICE_STATE_REASON_MODEM_AVAILABLE = 58,
+ NM_DEVICE_STATE_REASON_SIM_PIN_INCORRECT = 59,
+} NMDeviceStateReason;
+
+
+/**
+ * NMActiveConnectionState:
+ * @NM_ACTIVE_CONNECTION_STATE_UNKNOWN: the state of the connection is unknown
+ * @NM_ACTIVE_CONNECTION_STATE_ACTIVATING: a network connection is being prepared
+ * @NM_ACTIVE_CONNECTION_STATE_ACTIVATED: there is a connection to the network
+ * @NM_ACTIVE_CONNECTION_STATE_DEACTIVATING: the network connection is being
+ * torn down and cleaned up
+ * @NM_ACTIVE_CONNECTION_STATE_DEACTIVATED: the network connection is disconnected
+ * and will be removed
+ *
+ * #NMActiveConnectionState values indicate the state of a connection to a
+ * specific network while it is starting, connected, or disconnecting from that
+ * network.
+ *
+ * (Corresponds to the NM_ACTIVE_CONNECTION_STATE type in nm-active-connection.xml.)
+ **/
+typedef enum {
+ NM_ACTIVE_CONNECTION_STATE_UNKNOWN = 0,
+ NM_ACTIVE_CONNECTION_STATE_ACTIVATING,
+ NM_ACTIVE_CONNECTION_STATE_ACTIVATED,
+ NM_ACTIVE_CONNECTION_STATE_DEACTIVATING,
+ NM_ACTIVE_CONNECTION_STATE_DEACTIVATED
+} NMActiveConnectionState;
+
+/**
+ * NMSecretAgentGetSecretsFlags:
+ * @NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE: no special behavior; by default no
+ * user interaction is allowed and requests for secrets are fulfilled from
+ * persistent storage, or if no secrets are available an error is returned.
+ * @NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION: allows the request to
+ * interact with the user, possibly prompting via UI for secrets if any are
+ * required, or if none are found in persistent storage.
+ * @NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW: explicitly prompt for new
+ * secrets from the user. This flag signals that NetworkManager thinks any
+ * existing secrets are invalid or wrong. This flag implies that interaction
+ * is allowed.
+ * @NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED: set if the request was
+ * initiated by user-requested action via the D-Bus interface, as opposed to
+ * automatically initiated by NetworkManager in response to (for example) scan
+ * results or carrier changes.
+ * @NM_SECRET_AGENT_GET_SECRETS_FLAG_ONLY_SYSTEM: Internal flag, not part of
+ * the D-Bus API.
+ * @NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS: Internal flag, not part of
+ * the D-Bus API.
+ *
+ * #NMSecretAgentGetSecretsFlags values modify the behavior of a GetSecrets request.
+ *
+ * (Corresponds to the NM_SECRET_AGENT_GET_SECRETS_FLAGS type in nm-secret-agent.xml.)
+ */
+typedef enum { /*< flags >*/
+ NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE = 0x0,
+ NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION = 0x1,
+ NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW = 0x2,
+ NM_SECRET_AGENT_GET_SECRETS_FLAG_USER_REQUESTED = 0x4,
+
+ /* Internal to NM; not part of the D-Bus API */
+ NM_SECRET_AGENT_GET_SECRETS_FLAG_ONLY_SYSTEM = 0x80000000,
+ NM_SECRET_AGENT_GET_SECRETS_FLAG_NO_ERRORS = 0x40000000,
+} NMSecretAgentGetSecretsFlags;
+
+/**
+ * NMSecretAgentCapabilities:
+ * @NM_SECRET_AGENT_CAPABILITY_NONE: the agent supports no special capabilities
+ * @NM_SECRET_AGENT_CAPABILITY_VPN_HINTS: the agent supports passing hints to
+ * VPN plugin authentication dialogs.
+ * @NM_SECRET_AGENT_CAPABILITY_LAST: bounds checking value; should not be used.
+ *
+ * #NMSecretAgentCapabilities indicate various capabilities of the agent.
+ *
+ * (Corresponds to the NM_SECRET_AGENT_CAPABILITIES type in nm-secret-agent.xml.)
+ */
+typedef enum /*< flags >*/ {
+ NM_SECRET_AGENT_CAPABILITY_NONE = 0x0,
+ NM_SECRET_AGENT_CAPABILITY_VPN_HINTS = 0x1,
+
+ /* boundary value */
+ NM_SECRET_AGENT_CAPABILITY_LAST = NM_SECRET_AGENT_CAPABILITY_VPN_HINTS
+} NMSecretAgentCapabilities;
+
+#endif /* __NM_DBUS_INTERFACE_H__ */
diff --git a/libnm-core/nm-errors.c b/libnm-core/nm-errors.c
new file mode 100644
index 000000000..229f14a00
--- /dev/null
+++ b/libnm-core/nm-errors.c
@@ -0,0 +1,90 @@
+/* -*- 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 2004 - 2014 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <gio/gio.h>
+
+#include "nm-errors.h"
+#include "nm-glib-compat.h"
+#include "nm-dbus-interface.h"
+#include "nm-vpn-dbus-interface.h"
+#include "nm-core-internal.h"
+
+G_DEFINE_QUARK (nm-agent-manager-error-quark, nm_agent_manager_error)
+G_DEFINE_QUARK (nm-connection-error-quark, nm_connection_error)
+G_DEFINE_QUARK (nm-crypto-error-quark, nm_crypto_error)
+G_DEFINE_QUARK (nm-device-error-quark, nm_device_error)
+G_DEFINE_QUARK (nm-manager-error-quark, nm_manager_error)
+G_DEFINE_QUARK (nm-secret-agent-error-quark, nm_secret_agent_error)
+G_DEFINE_QUARK (nm-settings-error-quark, nm_settings_error)
+G_DEFINE_QUARK (nm-vpn-plugin-error-quark, nm_vpn_plugin_error)
+
+static void
+register_error_domain (GQuark domain,
+ const char *interface,
+ GType enum_type)
+{
+ GEnumClass *enum_class;
+ GEnumValue *e;
+ char *error_name;
+ int i;
+
+ enum_class = g_type_class_ref (enum_type);
+ for (i = 0; i < enum_class->n_values; i++) {
+ e = &enum_class->values[i];
+ g_assert (strchr (e->value_nick, '-') == NULL);
+ error_name = g_strdup_printf ("%s.%s", interface, e->value_nick);
+ g_dbus_error_register_error (domain, e->value, error_name);
+ g_free (error_name);
+ }
+
+ g_type_class_unref (enum_class);
+}
+
+void
+_nm_dbus_errors_init (void)
+{
+ register_error_domain (NM_AGENT_MANAGER_ERROR,
+ NM_DBUS_INTERFACE_AGENT_MANAGER,
+ NM_TYPE_AGENT_MANAGER_ERROR);
+ register_error_domain (NM_CONNECTION_ERROR,
+ NM_DBUS_INTERFACE_SETTINGS_CONNECTION,
+ NM_TYPE_CONNECTION_ERROR);
+ register_error_domain (NM_DEVICE_ERROR,
+ NM_DBUS_INTERFACE_DEVICE,
+ NM_TYPE_DEVICE_ERROR);
+ register_error_domain (NM_MANAGER_ERROR,
+ NM_DBUS_INTERFACE,
+ NM_TYPE_MANAGER_ERROR);
+ register_error_domain (NM_SECRET_AGENT_ERROR,
+ NM_DBUS_INTERFACE_SECRET_AGENT,
+ NM_TYPE_SECRET_AGENT_ERROR);
+ register_error_domain (NM_SETTINGS_ERROR,
+ NM_DBUS_INTERFACE_SETTINGS,
+ NM_TYPE_SETTINGS_ERROR);
+ register_error_domain (NM_SETTINGS_ERROR,
+ NM_DBUS_INTERFACE_SETTINGS,
+ NM_TYPE_SETTINGS_ERROR);
+ register_error_domain (NM_VPN_PLUGIN_ERROR,
+ NM_VPN_DBUS_PLUGIN_INTERFACE,
+ NM_TYPE_VPN_PLUGIN_ERROR);
+}
diff --git a/libnm-core/nm-errors.h b/libnm-core/nm-errors.h
new file mode 100644
index 000000000..a9857445b
--- /dev/null
+++ b/libnm-core/nm-errors.h
@@ -0,0 +1,319 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2004 - 2014 Red Hat, Inc.
+ */
+
+#ifndef __NM_ERRORS_H__
+#define __NM_ERRORS_H__
+
+/**
+ * NMAgentManagerError:
+ * @NM_AGENT_MANAGER_ERROR_FAILED: unknown or unspecified error
+ * @NM_AGENT_MANAGER_ERROR_PERMISSION_DENIED: The caller does not have permission
+ * to register a secret agent, or is trying to register the same secret agent
+ * twice.
+ * @NM_AGENT_MANAGER_ERROR_INVALID_IDENTIFIER: The identifier is not a valid
+ * secret agent identifier.
+ * @NM_AGENT_MANAGER_ERROR_NOT_REGISTERED: The caller tried to unregister an agent
+ * that was not registered.
+ * @NM_AGENT_MANAGER_ERROR_NO_SECRETS: No secret agent returned secrets for this
+ * request
+ * @NM_AGENT_MANAGER_ERROR_USER_CANCELED: The user canceled the secrets request.
+ *
+ * Errors returned from the secret-agent manager.
+ *
+ * These errors may be returned from operations that could cause secrets to be
+ * requested (such as nm_client_activate_connection()), and correspond to D-Bus
+ * errors in the "org.freedesktop.NetworkManager.AgentManager" namespace.
+ */
+typedef enum {
+ NM_AGENT_MANAGER_ERROR_FAILED = 0, /*< nick=Failed >*/
+ NM_AGENT_MANAGER_ERROR_PERMISSION_DENIED, /*< nick=PermissionDenied >*/
+ NM_AGENT_MANAGER_ERROR_INVALID_IDENTIFIER, /*< nick=InvalidIdentifier >*/
+ NM_AGENT_MANAGER_ERROR_NOT_REGISTERED, /*< nick=NotRegistered >*/
+ NM_AGENT_MANAGER_ERROR_NO_SECRETS, /*< nick=NoSecrets >*/
+ NM_AGENT_MANAGER_ERROR_USER_CANCELED, /*< nick=UserCanceled >*/
+} NMAgentManagerError;
+
+GQuark nm_agent_manager_error_quark (void);
+#define NM_AGENT_MANAGER_ERROR (nm_agent_manager_error_quark ())
+
+/**
+ * NMConnectionError:
+ * @NM_CONNECTION_ERROR_FAILED: unknown or unclassified error
+ * @NM_CONNECTION_ERROR_SETTING_NOT_FOUND: the #NMConnection object
+ * did not contain the specified #NMSetting object
+ * @NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND: the #NMConnection did not contain the
+ * requested #NMSetting property
+ * @NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET: an operation which requires a secret
+ * was attempted on a non-secret property
+ * @NM_CONNECTION_ERROR_MISSING_SETTING: the #NMConnection object is missing an
+ * #NMSetting which is required for its configuration. The error message will
+ * always be prefixed with "&lt;setting-name>: ", where "&lt;setting-name>" is the
+ * name of the setting that is missing.
+ * @NM_CONNECTION_ERROR_INVALID_SETTING: the #NMConnection object contains an
+ * invalid or inappropriate #NMSetting. The error message will always be
+ * prefixed with "&lt;setting-name>: ", where "&lt;setting-name>" is the name of the
+ * setting that is invalid.
+ * @NM_CONNECTION_ERROR_MISSING_PROPERTY: the #NMConnection object is invalid
+ * because it is missing a required property. The error message will always be
+ * prefixed with "&lt;setting-name>.&lt;property-name>: ", where "&lt;setting-name>" is
+ * the name of the setting with the missing property, and "&lt;property-name>" is
+ * the property that is missing.
+ * @NM_CONNECTION_ERROR_INVALID_PROPERTY: the #NMConnection object is invalid
+ * because a property has an invalid value. The error message will always be
+ * prefixed with "&lt;setting-name>.&lt;property-name>: ", where "&lt;setting-name>" is
+ * the name of the setting with the invalid property, and "&lt;property-name>" is
+ * the property that is invalid.
+ *
+ * Describes errors that may result from operations involving a #NMConnection
+ * or its #NMSettings.
+ *
+ * These errors may be returned directly from #NMConnection and #NMSetting
+ * methods, or may be returned from D-Bus operations (eg on #NMClient or
+ * #NMDevice), where they correspond to errors in the
+ * "org.freedesktop.NetworkManager.Settings.Connection" namespace.
+ */
+typedef enum {
+ NM_CONNECTION_ERROR_FAILED = 0, /*< nick=Failed >*/
+ NM_CONNECTION_ERROR_SETTING_NOT_FOUND, /*< nick=SettingNotFound >*/
+ NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND, /*< nick=PropertyNotFound >*/
+ NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET, /*< nick=PropertyNotSecret >*/
+ NM_CONNECTION_ERROR_MISSING_SETTING, /*< nick=MissingSetting >*/
+ NM_CONNECTION_ERROR_INVALID_SETTING, /*< nick=InvalidSetting >*/
+ NM_CONNECTION_ERROR_MISSING_PROPERTY, /*< nick=MissingProperty >*/
+ NM_CONNECTION_ERROR_INVALID_PROPERTY, /*< nick=InvalidProperty >*/
+} NMConnectionError;
+
+#define NM_CONNECTION_ERROR nm_connection_error_quark ()
+GQuark nm_connection_error_quark (void);
+
+/**
+ * NMCryptoError:
+ * @NM_CRYPTO_ERROR_FAILED: generic failure
+ * @NM_CRYPTO_ERROR_INVALID_DATA: the certificate or key data provided
+ * was invalid
+ * @NM_CRYPTO_ERROR_INVALID_PASSWORD: the password was invalid
+ * @NM_CRYPTO_ERROR_UNKNOWN_CIPHER: the data uses an unknown cipher
+ * @NM_CRYPTO_ERROR_DECRYPTION_FAILED: decryption failed
+ * @NM_CRYPTO_ERROR_ENCRYPTION_FAILED: encryption failed
+ *
+ * Cryptography-related errors that can be returned from some nm-utils methods,
+ * and some #NMSetting8021x operations.
+ */
+typedef enum {
+ NM_CRYPTO_ERROR_FAILED = 0,
+ NM_CRYPTO_ERROR_INVALID_DATA,
+ NM_CRYPTO_ERROR_INVALID_PASSWORD,
+ NM_CRYPTO_ERROR_UNKNOWN_CIPHER,
+ NM_CRYPTO_ERROR_DECRYPTION_FAILED,
+ NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
+} NMCryptoError;
+
+#define NM_CRYPTO_ERROR nm_crypto_error_quark ()
+GQuark nm_crypto_error_quark (void);
+
+/**
+ * NMDeviceError:
+ * @NM_DEVICE_ERROR_FAILED: unknown or unclassified error
+ * @NM_DEVICE_ERROR_CREATION_FAILED: NetworkManager failed to create the device
+ * @NM_DEVICE_ERROR_INVALID_CONNECTION: the specified connection is not valid
+ * @NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION: the specified connection is not
+ * compatible with this device.
+ * @NM_DEVICE_ERROR_NOT_ACTIVE: the device does not have an active connection
+ * @NM_DEVICE_ERROR_NOT_SOFTWARE: the requested operation is only valid on
+ * software devices.
+ * @NM_DEVICE_ERROR_NOT_ALLOWED: the requested operation is not allowed at
+ * this time.
+ * @NM_DEVICE_ERROR_SPECIFIC_OBJECT_NOT_FOUND: the "specific object" in the
+ * activation request (eg, the #NMAccessPoint or #NMWimaxNsp) was not
+ * found.
+ *
+ * Device-related errors.
+ *
+ * These errors may be returned directly from #NMDevice methods, or may be
+ * returned from D-Bus operations (where they correspond to errors in the
+ * "org.freedesktop.NetworkManager.Device" namespace).
+ */
+typedef enum {
+ NM_DEVICE_ERROR_FAILED = 0, /*< nick=Failed >*/
+ NM_DEVICE_ERROR_CREATION_FAILED, /*< nick=CreationFailed >*/
+ NM_DEVICE_ERROR_INVALID_CONNECTION, /*< nick=InvalidConnection >*/
+ NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, /*< nick=IncompatibleConnection >*/
+ NM_DEVICE_ERROR_NOT_ACTIVE, /*< nick=NotActive >*/
+ NM_DEVICE_ERROR_NOT_SOFTWARE, /*< nick=NotSoftware >*/
+ NM_DEVICE_ERROR_NOT_ALLOWED, /*< nick=NotAllowed >*/
+ NM_DEVICE_ERROR_SPECIFIC_OBJECT_NOT_FOUND, /*< nick=SpecificObjectNotFound >*/
+} NMDeviceError;
+
+#define NM_DEVICE_ERROR nm_device_error_quark ()
+GQuark nm_device_error_quark (void);
+
+/**
+ * NMManagerError:
+ * @NM_MANAGER_ERROR_FAILED: unknown or unclassified error
+ * @NM_MANAGER_ERROR_PERMISSION_DENIED: Permission denied.
+ * @NM_MANAGER_ERROR_UNKNOWN_CONNECTION: The requested connection is not known.
+ * @NM_MANAGER_ERROR_UNKNOWN_DEVICE: The requested device is not known.
+ * @NM_MANAGER_ERROR_CONNECTION_NOT_AVAILABLE: The requested connection cannot be
+ * activated at this time.
+ * @NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE: The request could not be completed
+ * because a required connection is not active.
+ * @NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE: The connection to be activated was
+ * already active on another device.
+ * @NM_MANAGER_ERROR_DEPENDENCY_FAILED: An activation request failed due to a
+ * dependency being unavailable.
+ * @NM_MANAGER_ERROR_ALREADY_ASLEEP_OR_AWAKE: The manager is already in the requested
+ * sleep/wake state.
+ * @NM_MANAGER_ERROR_ALREADY_ENABLED_OR_DISABLED: The network is already
+ * enabled/disabled.
+ * @NM_MANAGER_ERROR_UNKNOWN_LOG_LEVEL: Unknown log level in SetLogging
+ * @NM_MANAGER_ERROR_UNKNOWN_LOG_DOMAIN: Unknown log domain in SetLogging
+ *
+ * Errors related to the main "network management" interface of NetworkManager.
+ * These may be returned from #NMClient methods that invoke D-Bus operations on
+ * the "org.freedesktop.NetworkManager" interface, and correspond to D-Bus
+ * errors in that namespace.
+ */
+typedef enum {
+ NM_MANAGER_ERROR_FAILED = 0, /*< nick=Failed >*/
+ NM_MANAGER_ERROR_PERMISSION_DENIED, /*< nick=PermissionDenied >*/
+ NM_MANAGER_ERROR_UNKNOWN_CONNECTION, /*< nick=UnknownConnection >*/
+ NM_MANAGER_ERROR_UNKNOWN_DEVICE, /*< nick=UnknownDevice >*/
+ NM_MANAGER_ERROR_CONNECTION_NOT_AVAILABLE, /*< nick=ConnectionNotAvailable >*/
+ NM_MANAGER_ERROR_CONNECTION_NOT_ACTIVE, /*< nick=ConnectionNotActive >*/
+ NM_MANAGER_ERROR_CONNECTION_ALREADY_ACTIVE, /*< nick=ConnectionAlreadyActive >*/
+ NM_MANAGER_ERROR_DEPENDENCY_FAILED, /*< nick=DependencyFailed >*/
+ NM_MANAGER_ERROR_ALREADY_ASLEEP_OR_AWAKE, /*< nick=AlreadyAsleepOrAwake >*/
+ NM_MANAGER_ERROR_ALREADY_ENABLED_OR_DISABLED, /*< nick=AlreadyEnabledOrDisabled >*/
+ NM_MANAGER_ERROR_UNKNOWN_LOG_LEVEL, /*< nick=UnknownLogLevel >*/
+ NM_MANAGER_ERROR_UNKNOWN_LOG_DOMAIN, /*< nick=UnknownLogDomain >*/
+} NMManagerError;
+
+GQuark nm_manager_error_quark (void);
+#define NM_MANAGER_ERROR (nm_manager_error_quark ())
+
+/**
+ * NMSecretAgentError:
+ * @NM_SECRET_AGENT_ERROR_FAILED: unknown or unclassified error
+ * @NM_SECRET_AGENT_ERROR_PERMISSION_DENIED: the caller (ie, NetworkManager) is
+ * not authorized to make this request
+ * @NM_SECRET_AGENT_ERROR_INVALID_CONNECTION: the connection for which secrets
+ * were requested is invalid
+ * @NM_SECRET_AGENT_ERROR_USER_CANCELED: the request was canceled by the user
+ * @NM_SECRET_AGENT_ERROR_AGENT_CANCELED: the agent canceled the request
+ * because it was requested to do so by NetworkManager
+ * @NM_SECRET_AGENT_ERROR_NO_SECRETS: the agent cannot find any secrets for this
+ * connection
+ *
+ * #NMSecretAgentError values are passed by secret agents back to NetworkManager
+ * when they encounter problems retrieving secrets on behalf of NM. They
+ * correspond to errors in the "org.freedesktop.NetworkManager.SecretManager"
+ * namespace.
+ *
+ * Client APIs such as nm_client_activate_connection() will not see these error
+ * codes; instead, the secret agent manager will translate them to the
+ * corresponding #NMAgentManagerError codes.
+ */
+typedef enum {
+ NM_SECRET_AGENT_ERROR_FAILED = 0, /*< nick=Failed >*/
+ NM_SECRET_AGENT_ERROR_PERMISSION_DENIED, /*< nick=PermissionDenied >*/
+ NM_SECRET_AGENT_ERROR_INVALID_CONNECTION, /*< nick=InvalidConnection >*/
+ NM_SECRET_AGENT_ERROR_USER_CANCELED, /*< nick=UserCanceled >*/
+ NM_SECRET_AGENT_ERROR_AGENT_CANCELED, /*< nick=AgentCanceled >*/
+ NM_SECRET_AGENT_ERROR_NO_SECRETS, /*< nick=NoSecrets >*/
+} NMSecretAgentError;
+
+GQuark nm_secret_agent_error_quark (void);
+#define NM_SECRET_AGENT_ERROR (nm_secret_agent_error_quark ())
+
+/**
+ * NMSettingsError:
+ * @NM_SETTINGS_ERROR_FAILED: unknown or unclassified error
+ * @NM_SETTINGS_ERROR_PERMISSION_DENIED: permission denied
+ * @NM_SETTINGS_ERROR_NOT_SUPPORTED: the requested operation is not supported by any
+ * active settings backend
+ * @NM_SETTINGS_ERROR_INVALID_CONNECTION: the connection was invalid
+ * @NM_SETTINGS_ERROR_READ_ONLY_CONNECTION: attempted to modify a read-only connection
+ * @NM_SETTINGS_ERROR_UUID_EXISTS: a connection with that UUID already exists
+ * @NM_SETTINGS_ERROR_INVALID_HOSTNAME: attempted to set an invalid hostname
+ *
+ * Errors related to the settings/persistent configuration interface of
+ * NetworkManager.
+ *
+ * These may be returned from #NMClient methods that invoke D-Bus operations on
+ * the "org.freedesktop.NetworkManager.Settings" interface, and correspond to
+ * D-Bus errors in that namespace.
+ */
+typedef enum {
+ NM_SETTINGS_ERROR_FAILED = 0, /*< nick=Failed >*/
+ NM_SETTINGS_ERROR_PERMISSION_DENIED, /*< nick=PermissionDenied >*/
+ NM_SETTINGS_ERROR_NOT_SUPPORTED, /*< nick=NotSupported >*/
+ NM_SETTINGS_ERROR_INVALID_CONNECTION, /*< nick=InvalidConnection >*/
+ NM_SETTINGS_ERROR_READ_ONLY_CONNECTION, /*< nick=ReadOnlyConnection >*/
+ NM_SETTINGS_ERROR_UUID_EXISTS, /*< nick=UuidExists >*/
+ NM_SETTINGS_ERROR_INVALID_HOSTNAME, /*< nick=InvalidHostname >*/
+} NMSettingsError;
+
+GQuark nm_settings_error_quark (void);
+#define NM_SETTINGS_ERROR (nm_settings_error_quark ())
+
+/**
+ * NMVpnPluginError:
+ * @NM_VPN_PLUGIN_ERROR_FAILED: unknown or unclassified error
+ * @NM_VPN_PLUGIN_ERROR_STARTING_IN_PROGRESS: the plugin is already starting,
+ * and another connect request was received
+ * @NM_VPN_PLUGIN_ERROR_ALREADY_STARTED: the plugin is already connected, and
+ * another connect request was received
+ * @NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS: the plugin is already stopping,
+ * and another stop request was received
+ * @NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED: the plugin is already stopped, and
+ * another disconnect request was received
+ * @NM_VPN_PLUGIN_ERROR_WRONG_STATE: the operation could not be performed in
+ * this state
+ * @NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS: the operation could not be performed as
+ * the request contained malformed arguments, or arguments of unexpected type.
+ * Usually means that one of the VPN setting data items or secrets was not of
+ * the expected type (ie int, string, bool, etc).
+ * @NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED: a child process failed to launch
+ * @NM_VPN_PLUGIN_ERROR_INVALID_CONNECTION: the operation could not be performed
+ * because the connection was invalid. Usually means that the connection's
+ * VPN setting was missing some required data item or secret.
+ * @NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED: the operation could not be
+ * performed as the plugin does not support interactive operations, such as
+ * ConnectInteractive() or NewSecrets()
+ *
+ * Returned by the VPN service plugin to indicate errors. These codes correspond
+ * to errors in the "org.freedesktop.NetworkManager.VPN.Error" namespace.
+ **/
+typedef enum {
+ NM_VPN_PLUGIN_ERROR_FAILED, /*< nick=Failed >*/
+ NM_VPN_PLUGIN_ERROR_STARTING_IN_PROGRESS, /*< nick=StartingInProgress >*/
+ NM_VPN_PLUGIN_ERROR_ALREADY_STARTED, /*< nick=AlreadyStarted >*/
+ NM_VPN_PLUGIN_ERROR_STOPPING_IN_PROGRESS, /*< nick=StoppingInProgress >*/
+ NM_VPN_PLUGIN_ERROR_ALREADY_STOPPED, /*< nick=AlreadyStopped >*/
+ NM_VPN_PLUGIN_ERROR_WRONG_STATE, /*< nick=WrongState >*/
+ NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, /*< nick=BadArguments >*/
+ NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, /*< nick=LaunchFailed >*/
+ NM_VPN_PLUGIN_ERROR_INVALID_CONNECTION, /*< nick=InvalidConnection >*/
+ NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED, /*< nick=InteractiveNotSupported >*/
+} NMVpnPluginError;
+
+#define NM_VPN_PLUGIN_ERROR (nm_vpn_plugin_error_quark ())
+GQuark nm_vpn_plugin_error_quark (void);
+
+#endif /* __NM_ERRORS_H__ */
diff --git a/libnm-core/nm-property-compare.c b/libnm-core/nm-property-compare.c
new file mode 100644
index 000000000..5d270706e
--- /dev/null
+++ b/libnm-core/nm-property-compare.c
@@ -0,0 +1,122 @@
+/* -*- 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 2007 - 2014 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#include "config.h"
+
+#include "nm-property-compare.h"
+#include "nm-glib-compat.h"
+
+#include <string.h>
+#include <math.h>
+#include <netinet/in.h>
+#include <gio/gio.h>
+
+static gint
+_nm_property_compare_collection (GVariant *value1, GVariant *value2)
+{
+ GVariant *child1, *child2;
+ int i, len1, len2;
+ int ret;
+
+ len1 = g_variant_n_children (value1);
+ len2 = g_variant_n_children (value2);
+
+ if (len1 != len2)
+ return len1 < len2 ? -1 : len1 > len2;
+
+ for (i = 0; i < len1; i++) {
+ child1 = g_variant_get_child_value (value1, i);
+ child2 = g_variant_get_child_value (value2, i);
+
+ ret = nm_property_compare (child1, child2);
+ g_variant_unref (child1);
+ g_variant_unref (child2);
+
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static gint
+_nm_property_compare_strdict (GVariant *value1, GVariant *value2)
+{
+ GVariantIter iter;
+ int len1, len2;
+ const char *key, *val1, *val2;
+ int ret;
+
+ len1 = g_variant_n_children (value1);
+ len2 = g_variant_n_children (value2);
+
+ if (len1 != len2)
+ return len1 < len2 ? -1 : len1 > len2;
+
+ g_variant_iter_init (&iter, value1);
+ while (g_variant_iter_next (&iter, "{&s&s}", &key, &val1)) {
+ if (!g_variant_lookup (value2, key, "&s", &val2))
+ return -1;
+
+ ret = strcmp (val1, val2);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+int
+nm_property_compare (GVariant *value1, GVariant *value2)
+{
+ const GVariantType *type1;
+ const GVariantType *type2;
+ gint ret;
+
+ if (value1 == value2)
+ return 0;
+ if (!value1)
+ return 1;
+ if (!value2)
+ return -1;
+
+ type1 = g_variant_get_type (value1);
+ type2 = g_variant_get_type (value2);
+
+ if (!g_variant_type_equal (type1, type2))
+ return type1 < type2 ? -1 : type1 > type2;
+
+ if (g_variant_type_is_basic (type1))
+ ret = g_variant_compare (value1, value2);
+ else if (g_variant_is_of_type (value1, G_VARIANT_TYPE ("a{ss}")))
+ ret = _nm_property_compare_strdict (value1, value2);
+ else if (g_variant_type_is_array (type1))
+ ret = _nm_property_compare_collection (value1, value2);
+ else if (g_variant_type_is_tuple (type1))
+ ret = _nm_property_compare_collection (value1, value2);
+ else {
+ g_warning ("Don't know how to compare variant type '%s'", (const char *) type1);
+ ret = value1 == value2;
+ }
+
+ return ret;
+}
diff --git a/libnm-core/nm-property-compare.h b/libnm-core/nm-property-compare.h
new file mode 100644
index 000000000..33016787f
--- /dev/null
+++ b/libnm-core/nm-property-compare.h
@@ -0,0 +1,30 @@
+/* -*- 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 2007 - 2014 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#ifndef __NM_PROPERTY_COMPARE_H__
+#define __NM_PROPERTY_COMPARE_H__
+
+#include <glib.h>
+
+int nm_property_compare (GVariant *value1, GVariant *value2);
+
+#endif /* __NM_PROPERTY_COMPARE_H__ */
diff --git a/libnm-core/nm-setting-8021x.c b/libnm-core/nm-setting-8021x.c
new file mode 100644
index 000000000..f739f2c72
--- /dev/null
+++ b/libnm-core/nm-setting-8021x.c
@@ -0,0 +1,3864 @@
+/* -*- 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 2007 - 2013 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-8021x.h"
+#include "nm-utils.h"
+#include "crypto.h"
+#include "nm-utils-private.h"
+#include "nm-setting-private.h"
+#include "nm-core-enum-types.h"
+
+/**
+ * SECTION:nm-setting-8021x
+ * @short_description: Describes 802.1x-authenticated connection properties
+ *
+ * The #NMSetting8021x object is a #NMSetting subclass that describes
+ * properties necessary for connection to 802.1x-authenticated networks, such as
+ * WPA and WPA2 Enterprise Wi-Fi networks and wired 802.1x networks. 802.1x
+ * connections typically use certificates and/or EAP authentication methods to
+ * securely verify, identify, and authenticate the client to the network itself,
+ * instead of simply relying on a widely shared static key.
+ *
+ * It's a good idea to read up on wpa_supplicant configuration before using this
+ * setting extensively, since most of the options here correspond closely with
+ * the relevant wpa_supplicant configuration options.
+ *
+ * Furthermore, to get a good idea of 802.1x, EAP, TLS, TTLS, etc and their
+ * applications to Wi-Fi and wired networks, you'll want to get copies of the
+ * following books.
+ *
+ * 802.11 Wireless Networks: The Definitive Guide, Second Edition
+ * Author: Matthew Gast
+ * ISBN: 978-0596100520
+ *
+ * Cisco Wireless LAN Security
+ * Authors: Krishna Sankar, Sri Sundaralingam, Darrin Miller, and Andrew Balinsky
+ * ISBN: 978-1587051548
+ **/
+
+#define SCHEME_PATH "file://"
+
+G_DEFINE_TYPE_WITH_CODE (NMSetting8021x, nm_setting_802_1x, NM_TYPE_SETTING,
+ _nm_register_setting (802_1X, 2))
+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))
+
+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 struct {
+ GSList *eap; /* GSList of strings */
+ char *identity;
+ char *anonymous_identity;
+ char *pac_file;
+ GBytes *ca_cert;
+ char *ca_path;
+ char *subject_match;
+ GSList *altsubject_matches;
+ GBytes *client_cert;
+ char *phase1_peapver;
+ char *phase1_peaplabel;
+ char *phase1_fast_provisioning;
+ char *phase2_auth;
+ char *phase2_autheap;
+ GBytes *phase2_ca_cert;
+ char *phase2_ca_path;
+ char *phase2_subject_match;
+ GSList *phase2_altsubject_matches;
+ GBytes *phase2_client_cert;
+ 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;
+} NMSetting8021xPrivate;
+
+enum {
+ PROP_0,
+ PROP_EAP,
+ PROP_IDENTITY,
+ PROP_ANONYMOUS_IDENTITY,
+ PROP_PAC_FILE,
+ PROP_CA_CERT,
+ PROP_CA_PATH,
+ PROP_SUBJECT_MATCH,
+ PROP_ALTSUBJECT_MATCHES,
+ PROP_CLIENT_CERT,
+ PROP_PHASE1_PEAPVER,
+ PROP_PHASE1_PEAPLABEL,
+ PROP_PHASE1_FAST_PROVISIONING,
+ PROP_PHASE2_AUTH,
+ PROP_PHASE2_AUTHEAP,
+ PROP_PHASE2_CA_CERT,
+ PROP_PHASE2_CA_PATH,
+ PROP_PHASE2_SUBJECT_MATCH,
+ PROP_PHASE2_ALTSUBJECT_MATCHES,
+ PROP_PHASE2_CLIENT_CERT,
+ PROP_PASSWORD,
+ PROP_PASSWORD_FLAGS,
+ PROP_PASSWORD_RAW,
+ PROP_PASSWORD_RAW_FLAGS,
+ PROP_PRIVATE_KEY,
+ PROP_PRIVATE_KEY_PASSWORD,
+ PROP_PRIVATE_KEY_PASSWORD_FLAGS,
+ PROP_PHASE2_PRIVATE_KEY,
+ PROP_PHASE2_PRIVATE_KEY_PASSWORD,
+ PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS,
+ PROP_PIN,
+ PROP_PIN_FLAGS,
+ PROP_SYSTEM_CA_CERTS,
+
+ LAST_PROP
+};
+
+/**
+ * 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);
+}
+
+/**
+ * nm_setting_802_1x_get_num_eap_methods:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the number of eap methods allowed for use when connecting to the
+ * network. Generally only one EAP method is used. Use the functions
+ * nm_setting_802_1x_get_eap_method(), nm_setting_802_1x_add_eap_method(),
+ * and nm_setting_802_1x_remove_eap_method() for adding, removing, and retrieving
+ * allowed EAP methods.
+ *
+ * Returns: the number of allowed EAP methods
+ **/
+guint32
+nm_setting_802_1x_get_num_eap_methods (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), 0);
+
+ return g_slist_length (NM_SETTING_802_1X_GET_PRIVATE (setting)->eap);
+}
+
+/**
+ * nm_setting_802_1x_get_eap_method:
+ * @setting: the #NMSetting8021x
+ * @i: the index of the EAP method name to return
+ *
+ * Returns the name of the allowed EAP method at index @i.
+ *
+ * Returns: the name of the allowed EAP method at index @i
+ **/
+const char *
+nm_setting_802_1x_get_eap_method (NMSetting8021x *setting, guint32 i)
+{
+ NMSetting8021xPrivate *priv;
+
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+ priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+ g_return_val_if_fail (i <= g_slist_length (priv->eap), NULL);
+
+ return (const char *) g_slist_nth_data (priv->eap, i);
+}
+
+/**
+ * nm_setting_802_1x_add_eap_method:
+ * @setting: the #NMSetting8021x
+ * @eap: the name of the EAP method to allow for this connection
+ *
+ * Adds an allowed EAP method. The setting is not valid until at least one
+ * EAP method has been added. See #NMSetting8021x:eap property for a list of
+ * allowed EAP methods.
+ *
+ * Returns: %TRUE if the EAP method was successfully added, %FALSE if it was
+ * not a valid method or if it was already allowed.
+ **/
+gboolean
+nm_setting_802_1x_add_eap_method (NMSetting8021x *setting, const char *eap)
+{
+ NMSetting8021xPrivate *priv;
+ GSList *iter;
+
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
+ g_return_val_if_fail (eap != NULL, FALSE);
+
+ priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+ for (iter = priv->eap; iter; iter = g_slist_next (iter)) {
+ if (!strcmp (eap, (char *) iter->data))
+ return FALSE;
+ }
+
+ priv->eap = g_slist_append (priv->eap, g_ascii_strdown (eap, -1));
+ g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_EAP);
+ return TRUE;
+}
+
+/**
+ * nm_setting_802_1x_remove_eap_method:
+ * @setting: the #NMSetting8021x
+ * @i: the index of the EAP method to remove
+ *
+ * Removes the allowed EAP method at the specified index.
+ **/
+void
+nm_setting_802_1x_remove_eap_method (NMSetting8021x *setting, guint32 i)
+{
+ NMSetting8021xPrivate *priv;
+ GSList *elt;
+
+ g_return_if_fail (NM_IS_SETTING_802_1X (setting));
+
+ priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+ elt = g_slist_nth (priv->eap, i);
+ g_return_if_fail (elt != NULL);
+
+ g_free (elt->data);
+ priv->eap = g_slist_delete_link (priv->eap, elt);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_EAP);
+}
+
+/**
+ * nm_setting_802_1x_remove_eap_method_by_value:
+ * @setting: the #NMSetting8021x
+ * @eap: the name of the EAP method to remove
+ *
+ * Removes the allowed EAP method @method.
+ *
+ * Returns: %TRUE if the EAP method was founs and removed, %FALSE if it was not.
+ **/
+gboolean
+nm_setting_802_1x_remove_eap_method_by_value (NMSetting8021x *setting,
+ const char *eap)
+{
+ NMSetting8021xPrivate *priv;
+ GSList *iter;
+
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
+ g_return_val_if_fail (eap != NULL, FALSE);
+
+ priv = NM_SETTING_802_1X_GET_PRIVATE (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);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * nm_setting_802_1x_clear_eap_methods:
+ * @setting: the #NMSetting8021x
+ *
+ * Clears all allowed EAP methods.
+ **/
+void
+nm_setting_802_1x_clear_eap_methods (NMSetting8021x *setting)
+{
+ NMSetting8021xPrivate *priv;
+
+ g_return_if_fail (NM_IS_SETTING_802_1X (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);
+}
+
+/**
+ * nm_setting_802_1x_get_identity:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the identifier used by some EAP methods (like TLS) to
+ * authenticate the user. Often this is a username or login name.
+ *
+ * Returns: the user identifier
+ **/
+const char *
+nm_setting_802_1x_get_identity (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+ return NM_SETTING_802_1X_GET_PRIVATE (setting)->identity;
+}
+
+/**
+ * nm_setting_802_1x_get_anonymous_identity:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the anonymous identifier used by some EAP methods (like TTLS) to
+ * authenticate the user in the outer unencrypted "phase 1" authentication. The
+ * inner "phase 2" authentication will use the #NMSetting8021x:identity in
+ * a secure form, if applicable for that EAP method.
+ *
+ * Returns: the anonymous identifier
+ **/
+const char *
+nm_setting_802_1x_get_anonymous_identity (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+ return NM_SETTING_802_1X_GET_PRIVATE (setting)->anonymous_identity;
+}
+
+/**
+ * nm_setting_802_1x_get_pac_file:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the file containing PAC credentials used by EAP-FAST method.
+ *
+ * Returns: the PAC file
+ **/
+const char *
+nm_setting_802_1x_get_pac_file (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+ return NM_SETTING_802_1X_GET_PRIVATE (setting)->pac_file;
+}
+
+/**
+ * nm_setting_802_1x_get_ca_path:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the path of the CA certificate directory if previously set. Systems
+ * will often have a directory that contains multiple individual CA certificates
+ * which the supplicant can then add to the verification chain. This may be
+ * used in addition to the #NMSetting8021x:ca-cert property to add more CA
+ * certificates for verifying the network to client.
+ *
+ * Returns: the CA certificate directory path
+ **/
+const char *
+nm_setting_802_1x_get_ca_path (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+ return NM_SETTING_802_1X_GET_PRIVATE (setting)->ca_path;
+}
+
+/**
+ * nm_setting_802_1x_get_system_ca_certs:
+ * @setting: the #NMSetting8021x
+ *
+ * Sets the #NMSetting8021x:system-ca-certs property. The
+ * #NMSetting8021x:ca-path and #NMSetting8021x:phase2-ca-path
+ * properties are ignored if the #NMSetting8021x:system-ca-certs property is
+ * %TRUE, in which case a system-wide CA certificate directory specified at
+ * compile time (using the --system-ca-path configure option) is used in place
+ * of these properties.
+ *
+ * Returns: %TRUE if a system CA certificate path should be used, %FALSE if not
+ **/
+gboolean
+nm_setting_802_1x_get_system_ca_certs (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
+
+ return NM_SETTING_802_1X_GET_PRIVATE (setting)->system_ca_certs;
+}
+
+static NMSetting8021xCKScheme
+get_cert_scheme (GBytes *bytes)
+{
+ gconstpointer data;
+ gsize length;
+
+ if (!bytes)
+ return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
+
+ data = g_bytes_get_data (bytes, &length);
+ if (!length)
+ return NM_SETTING_802_1X_CK_SCHEME_UNKNOWN;
+
+ if ( (length > strlen (SCHEME_PATH))
+ && !memcmp (data, SCHEME_PATH, strlen (SCHEME_PATH)))
+ return NM_SETTING_802_1X_CK_SCHEME_PATH;
+
+ return NM_SETTING_802_1X_CK_SCHEME_BLOB;
+}
+
+/**
+ * nm_setting_802_1x_get_ca_cert_scheme:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the scheme used to store the CA certificate. If the returned scheme
+ * is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use nm_setting_802_1x_get_ca_cert_blob();
+ * if %NM_SETTING_802_1X_CK_SCHEME_PATH, use nm_setting_802_1x_get_ca_cert_path().
+ *
+ * Returns: scheme used to store the CA certificate (blob or 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);
+}
+
+/**
+ * nm_setting_802_1x_get_ca_cert_blob:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the CA certificate blob if the CA certificate is stored using the
+ * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme. Not all EAP methods use a
+ * CA certificate (LEAP for example), and those that can take advantage of the
+ * CA certificate allow it to be unset. Note that lack of a CA certificate
+ * reduces security by allowing man-in-the-middle attacks, because the identity
+ * of the network cannot be confirmed by the client.
+ *
+ * Returns: (transfer none): the CA certificate data
+ **/
+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;
+}
+
+/**
+ * nm_setting_802_1x_get_ca_cert_path:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the CA certificate path if the CA certificate is stored using the
+ * %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. Not all EAP methods use a
+ * CA certificate (LEAP for example), and those that can take advantage of the
+ * CA certificate allow it to be unset. Note that lack of a CA certificate
+ * reduces security by allowing man-in-the-middle attacks, because the identity
+ * of the network cannot be confirmed by the client.
+ *
+ * Returns: path to the CA certificate file
+ **/
+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 (SCHEME_PATH);
+}
+
+static GBytes *
+path_to_scheme_value (const char *path)
+{
+ GByteArray *array;
+
+ g_return_val_if_fail (path != NULL, NULL);
+
+ /* Add the path scheme tag to the front, then the fielname */
+ array = g_byte_array_sized_new (strlen (path) + strlen (SCHEME_PATH) + 1);
+ g_byte_array_append (array, (const guint8 *) SCHEME_PATH, strlen (SCHEME_PATH));
+ g_byte_array_append (array, (const guint8 *) path, strlen (path));
+ g_byte_array_append (array, (const guint8 *) "\0", 1);
+
+ return g_byte_array_free_to_bytes (array);
+}
+
+/**
+ * nm_setting_802_1x_set_ca_cert:
+ * @setting: the #NMSetting8021x
+ * @cert_path: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH
+ * or %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the CA certificate
+ * file (PEM or DER format). The path must be UTF-8 encoded; use
+ * g_filename_to_utf8() to convert if needed. Passing %NULL with any @scheme
+ * clears the CA certificate.
+ * @scheme: desired storage scheme for the certificate
+ * @out_format: on successful return, the type of the certificate added
+ * @error: on unsuccessful return, an error
+ *
+ * Reads a certificate from disk and sets the #NMSetting8021x:ca-cert property
+ * with the raw certificate data if using the %NM_SETTING_802_1X_CK_SCHEME_BLOB
+ * scheme, or with the path to the certificate file if using the
+ * %NM_SETTING_802_1X_CK_SCHEME_PATH scheme.
+ *
+ * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful
+ **/
+gboolean
+nm_setting_802_1x_set_ca_cert (NMSetting8021x *setting,
+ const char *cert_path,
+ NMSetting8021xCKScheme scheme,
+ 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 (cert_path) {
+ g_return_val_if_fail (g_utf8_validate (cert_path, -1, NULL), FALSE);
+ g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
+ || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH,
+ 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 (!cert_path) {
+ g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_CA_CERT);
+ return TRUE;
+ }
+
+ data = crypto_load_and_verify_certificate (cert_path, &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 (cert_path);
+ 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;
+}
+
+/**
+ * nm_setting_802_1x_get_subject_match:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the #NMSetting8021x:subject-match property. This is the
+ * substring to be matched against the subject of the authentication
+ * server certificate, or %NULL no subject verification is to be
+ * performed.
+ **/
+const char *
+nm_setting_802_1x_get_subject_match (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+ return NM_SETTING_802_1X_GET_PRIVATE (setting)->subject_match;
+}
+
+/**
+ * nm_setting_802_1x_get_num_altsubject_matches:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the number of entries in the
+ * #NMSetting8021x:altsubject-matches property of this setting.
+ *
+ * Returns: the number of altsubject-matches entries.
+ **/
+guint32
+nm_setting_802_1x_get_num_altsubject_matches (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), 0);
+
+ return g_slist_length (NM_SETTING_802_1X_GET_PRIVATE (setting)->altsubject_matches);
+}
+
+/**
+ * nm_setting_802_1x_get_altsubject_match:
+ * @setting: the #NMSettingConnection
+ * @i: the zero-based index of the array of altSubjectName matches
+ *
+ * Returns the altSubjectName match at index @i.
+ *
+ * Returns: the altSubjectName match at index @i
+ **/
+const char *
+nm_setting_802_1x_get_altsubject_match (NMSetting8021x *setting, guint32 i)
+{
+ NMSetting8021xPrivate *priv;
+
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+ priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+ g_return_val_if_fail (i <= g_slist_length (priv->altsubject_matches), NULL);
+
+ return (const char *) g_slist_nth_data (priv->altsubject_matches, i);
+}
+
+/**
+ * nm_setting_802_1x_add_altsubject_match:
+ * @setting: the #NMSetting8021x
+ * @altsubject_match: the altSubjectName to allow for this connection
+ *
+ * Adds an allowed alternate subject name match. Until at least one
+ * match is added, the altSubjectName of the remote authentication
+ * server is not verified.
+ *
+ * Returns: %TRUE if the alternative subject name match was
+ * successfully added, %FALSE if it was already allowed.
+ **/
+gboolean
+nm_setting_802_1x_add_altsubject_match (NMSetting8021x *setting,
+ const char *altsubject_match)
+{
+ NMSetting8021xPrivate *priv;
+ GSList *iter;
+
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
+ g_return_val_if_fail (altsubject_match != NULL, FALSE);
+
+ priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+ for (iter = priv->altsubject_matches; iter; iter = g_slist_next (iter)) {
+ if (!strcmp (altsubject_match, (char *) iter->data))
+ return FALSE;
+ }
+
+ 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);
+ return TRUE;
+}
+
+/**
+ * nm_setting_802_1x_remove_altsubject_match:
+ * @setting: the #NMSetting8021x
+ * @i: the index of the altSubjectName match to remove
+ *
+ * Removes the allowed altSubjectName at the specified index.
+ **/
+void
+nm_setting_802_1x_remove_altsubject_match (NMSetting8021x *setting, guint32 i)
+{
+ NMSetting8021xPrivate *priv;
+ GSList *elt;
+
+ g_return_if_fail (NM_IS_SETTING_802_1X (setting));
+
+ priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+ elt = g_slist_nth (priv->altsubject_matches, i);
+ g_return_if_fail (elt != NULL);
+
+ 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);
+}
+
+/**
+ * nm_setting_802_1x_remove_altsubject_match_by_value:
+ * @setting: the #NMSetting8021x
+ * @altsubject_match: the altSubjectName to remove
+ *
+ * Removes the allowed altSubjectName @altsubject_match.
+ *
+ * Returns: %TRUE if the alternative subject name match was found and removed,
+ * %FALSE if it was not.
+ **/
+gboolean
+nm_setting_802_1x_remove_altsubject_match_by_value (NMSetting8021x *setting,
+ const char *altsubject_match)
+{
+ NMSetting8021xPrivate *priv;
+ GSList *iter;
+
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
+ g_return_val_if_fail (altsubject_match != NULL, FALSE);
+
+ priv = NM_SETTING_802_1X_GET_PRIVATE (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);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * nm_setting_802_1x_clear_altsubject_matches:
+ * @setting: the #NMSetting8021x
+ *
+ * Clears all altSubjectName matches.
+ **/
+void
+nm_setting_802_1x_clear_altsubject_matches (NMSetting8021x *setting)
+{
+ NMSetting8021xPrivate *priv;
+
+ g_return_if_fail (NM_IS_SETTING_802_1X (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);
+}
+
+/**
+ * nm_setting_802_1x_get_client_cert_scheme:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the scheme used to store the client certificate. If the returned scheme
+ * is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use nm_setting_802_1x_get_client_cert_blob();
+ * if %NM_SETTING_802_1X_CK_SCHEME_PATH, use nm_setting_802_1x_get_client_cert_path().
+ *
+ * Returns: scheme used to store the client certificate (blob or path)
+ **/
+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);
+}
+
+/**
+ * nm_setting_802_1x_get_client_cert_blob:
+ * @setting: the #NMSetting8021x
+ *
+ * Client certificates are used to identify the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: (transfer none): the client certificate data
+ **/
+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;
+}
+
+/**
+ * nm_setting_802_1x_get_client_cert_path:
+ * @setting: the #NMSetting8021x
+ *
+ * Client certificates are used to identify the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: path to the client certificate file
+ **/
+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 (SCHEME_PATH);
+}
+
+/**
+ * nm_setting_802_1x_set_client_cert:
+ * @setting: the #NMSetting8021x
+ * @cert_path: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH
+ * or %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the client
+ * certificate file (PEM, DER, or PKCS#<!-- -->12 format). The path must be UTF-8
+ * encoded; use g_filename_to_utf8() to convert if needed. Passing %NULL with
+ * any @scheme clears the client certificate.
+ * @scheme: desired storage scheme for the certificate
+ * @out_format: on successful return, the type of the certificate added
+ * @error: on unsuccessful return, an error
+ *
+ * Reads a certificate from disk and sets the #NMSetting8021x:client-cert
+ * property with the raw certificate data if using the
+ * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the certificate
+ * file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme.
+ *
+ * Client certificates are used to identify the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful
+ **/
+gboolean
+nm_setting_802_1x_set_client_cert (NMSetting8021x *setting,
+ const char *cert_path,
+ NMSetting8021xCKScheme scheme,
+ 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 (cert_path) {
+ g_return_val_if_fail (g_utf8_validate (cert_path, -1, NULL), FALSE);
+ g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
+ || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH,
+ 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 (!cert_path) {
+ g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_CLIENT_CERT);
+ return TRUE;
+ }
+
+ data = crypto_load_and_verify_certificate (cert_path, &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 (cert_path);
+ 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;
+}
+
+/**
+ * nm_setting_802_1x_get_phase1_peapver:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the "phase 1" PEAP version to be used when authenticating with
+ * EAP-PEAP as contained in the #NMSetting8021x:phase1-peapver property. Valid
+ * values are %NULL (unset), "0" (PEAP version 0), and "1" (PEAP version 1).
+ **/
+const char *
+nm_setting_802_1x_get_phase1_peapver (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+ return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase1_peapver;
+}
+
+/**
+ * nm_setting_802_1x_get_phase1_peaplabel:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: whether the "phase 1" PEAP label is new-style or old-style, to be
+ * used when authenticating with EAP-PEAP, as contained in the
+ * #NMSetting8021x:phase1-peaplabel property. Valid values are %NULL (unset),
+ * "0" (use old-style label), and "1" (use new-style label). See the
+ * wpa_supplicant documentation for more details.
+ **/
+const char *
+nm_setting_802_1x_get_phase1_peaplabel (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+ return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase1_peaplabel;
+}
+
+/**
+ * nm_setting_802_1x_get_phase1_fast_provisioning:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: whether "phase 1" PEAP fast provisioning should be used, as specified
+ * by the #NMSetting8021x:phase1-fast-provisioning property. See the
+ * wpa_supplicant documentation for more details.
+ **/
+const char *
+nm_setting_802_1x_get_phase1_fast_provisioning (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+ return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase1_fast_provisioning;
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_auth:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the "phase 2" non-EAP (ex MD5) allowed authentication method as
+ * specified by the #NMSetting8021x:phase2-auth property.
+ **/
+const char *
+nm_setting_802_1x_get_phase2_auth (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+ return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_auth;
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_autheap:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the "phase 2" EAP-based (ex TLS) allowed authentication method as
+ * specified by the #NMSetting8021x:phase2-autheap property.
+ **/
+const char *
+nm_setting_802_1x_get_phase2_autheap (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+ return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_autheap;
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_ca_path:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the path of the "phase 2" CA certificate directory if previously set.
+ * Systems will often have a directory that contains multiple individual CA
+ * certificates which the supplicant can then add to the verification chain.
+ * This may be used in addition to the #NMSetting8021x:phase2-ca-cert property
+ * to add more CA certificates for verifying the network to client.
+ *
+ * Returns: the "phase 2" CA certificate directory path
+ **/
+const char *
+nm_setting_802_1x_get_phase2_ca_path (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+ return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_ca_path;
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_ca_cert_scheme:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the scheme used to store the "phase 2" CA certificate. If the
+ * returned scheme is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use
+ * nm_setting_802_1x_get_ca_cert_blob(); if %NM_SETTING_802_1X_CK_SCHEME_PATH,
+ * use nm_setting_802_1x_get_ca_cert_path().
+ *
+ * Returns: scheme used to store the "phase 2" CA certificate (blob or path)
+ **/
+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);
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_ca_cert_blob:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the "phase 2" CA certificate blob if the CA certificate is stored
+ * using the %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme. Not all EAP methods use
+ * a CA certificate (LEAP for example), and those that can take advantage of the
+ * CA certificate allow it to be unset. Note that lack of a CA certificate
+ * reduces security by allowing man-in-the-middle attacks, because the identity
+ * of the network cannot be confirmed by the client.
+ *
+ * Returns: (transfer none): the "phase 2" CA certificate data
+ **/
+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;
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_ca_cert_path:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the "phase 2" CA certificate path if the CA certificate is stored
+ * using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme. Not all EAP methods use
+ * a CA certificate (LEAP for example), and those that can take advantage of the
+ * CA certificate allow it to be unset. Note that lack of a CA certificate
+ * reduces security by allowing man-in-the-middle attacks, because the identity
+ * of the network cannot be confirmed by the client.
+ *
+ * Returns: path to the "phase 2" CA certificate file
+ **/
+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 (SCHEME_PATH);
+}
+
+/**
+ * nm_setting_802_1x_set_phase2_ca_cert:
+ * @setting: the #NMSetting8021x
+ * @cert_path: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH
+ * or %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the "phase2" CA
+ * certificate file (PEM or DER format). The path must be UTF-8 encoded; use
+ * g_filename_to_utf8() to convert if needed. Passing %NULL with any @scheme
+ * clears the "phase2" CA certificate.
+ * @scheme: desired storage scheme for the certificate
+ * @out_format: on successful return, the type of the certificate added
+ * @error: on unsuccessful return, an error
+ *
+ * Reads a certificate from disk and sets the #NMSetting8021x:phase2-ca-cert
+ * property with the raw certificate data if using the
+ * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the certificate
+ * file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme.
+ *
+ * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful
+ **/
+gboolean
+nm_setting_802_1x_set_phase2_ca_cert (NMSetting8021x *setting,
+ const char *cert_path,
+ NMSetting8021xCKScheme scheme,
+ 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 (cert_path) {
+ g_return_val_if_fail (g_utf8_validate (cert_path, -1, NULL), FALSE);
+ g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
+ || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH,
+ 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 (!cert_path) {
+ g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_CA_CERT);
+ return TRUE;
+ }
+
+ data = crypto_load_and_verify_certificate (cert_path, &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 (cert_path);
+ 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;
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_subject_match:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the #NMSetting8021x:phase2-subject-match property. This is
+ * the substring to be matched against the subject of the "phase 2"
+ * authentication server certificate, or %NULL no subject verification
+ * is to be performed.
+ **/
+const char *
+nm_setting_802_1x_get_phase2_subject_match (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+ return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_subject_match;
+}
+
+/**
+ * nm_setting_802_1x_get_num_phase2_altsubject_matches:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the number of entries in the
+ * #NMSetting8021x:phase2-altsubject-matches property of this setting.
+ *
+ * Returns: the number of phase2-altsubject-matches entries.
+ **/
+guint32
+nm_setting_802_1x_get_num_phase2_altsubject_matches (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), 0);
+
+ return g_slist_length (NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_altsubject_matches);
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_altsubject_match:
+ * @setting: the #NMSettingConnection
+ * @i: the zero-based index of the array of "phase 2" altSubjectName matches
+ *
+ * Returns the "phase 2" altSubjectName match at index @i.
+ *
+ * Returns: the "phase 2" altSubjectName match at index @i
+ **/
+const char *
+nm_setting_802_1x_get_phase2_altsubject_match (NMSetting8021x *setting, guint32 i)
+{
+ NMSetting8021xPrivate *priv;
+
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+ priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+ g_return_val_if_fail (i <= g_slist_length (priv->phase2_altsubject_matches), NULL);
+
+ return (const char *) g_slist_nth_data (priv->phase2_altsubject_matches, i);
+}
+
+/**
+ * nm_setting_802_1x_add_phase2_altsubject_match:
+ * @setting: the #NMSetting8021x
+ * @phase2_altsubject_match: the "phase 2" altSubjectName to allow for this
+ * connection
+ *
+ * Adds an allowed alternate subject name match for "phase 2". Until
+ * at least one match is added, the altSubjectName of the "phase 2"
+ * remote authentication server is not verified.
+ *
+ * Returns: %TRUE if the "phase 2" alternative subject name match was
+ * successfully added, %FALSE if it was already allowed.
+ **/
+gboolean
+nm_setting_802_1x_add_phase2_altsubject_match (NMSetting8021x *setting,
+ const char *phase2_altsubject_match)
+{
+ NMSetting8021xPrivate *priv;
+ GSList *iter;
+
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
+ g_return_val_if_fail (phase2_altsubject_match != NULL, FALSE);
+
+ priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+ for (iter = priv->phase2_altsubject_matches; iter; iter = g_slist_next (iter)) {
+ if (!strcmp (phase2_altsubject_match, (char *) iter->data))
+ return FALSE;
+ }
+
+ 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);
+ return TRUE;
+}
+
+/**
+ * nm_setting_802_1x_remove_phase2_altsubject_match:
+ * @setting: the #NMSetting8021x
+ * @i: the index of the "phase 2" altSubjectName match to remove
+ *
+ * Removes the allowed "phase 2" altSubjectName at the specified index.
+ **/
+void
+nm_setting_802_1x_remove_phase2_altsubject_match (NMSetting8021x *setting, guint32 i)
+{
+ NMSetting8021xPrivate *priv;
+ GSList *elt;
+
+ g_return_if_fail (NM_IS_SETTING_802_1X (setting));
+
+ priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+ elt = g_slist_nth (priv->phase2_altsubject_matches, i);
+ g_return_if_fail (elt != NULL);
+
+ 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);
+}
+
+
+/**
+ * nm_setting_802_1x_remove_phase2_altsubject_match_by_value:
+ * @setting: the #NMSetting8021x
+ * @phase2_altsubject_match: the "phase 2" altSubjectName to remove
+ *
+ * Removes the allowed "phase 2" altSubjectName @phase2_altsubject_match.
+ *
+ * Returns: %TRUE if the alternative subject name match for "phase 2" was found and removed,
+ * %FALSE if it was not.
+ **/
+gboolean
+nm_setting_802_1x_remove_phase2_altsubject_match_by_value (NMSetting8021x *setting,
+ const char *phase2_altsubject_match)
+{
+ NMSetting8021xPrivate *priv;
+ GSList *iter;
+
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
+ g_return_val_if_fail (phase2_altsubject_match != NULL, FALSE);
+
+ priv = NM_SETTING_802_1X_GET_PRIVATE (setting);
+ 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);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * nm_setting_802_1x_clear_phase2_altsubject_matches:
+ * @setting: the #NMSetting8021x
+ *
+ * Clears all "phase 2" altSubjectName matches.
+ **/
+void
+nm_setting_802_1x_clear_phase2_altsubject_matches (NMSetting8021x *setting)
+{
+ NMSetting8021xPrivate *priv;
+
+ g_return_if_fail (NM_IS_SETTING_802_1X (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);
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_client_cert_scheme:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the scheme used to store the "phase 2" client certificate. If the
+ * returned scheme is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use
+ * nm_setting_802_1x_get_client_cert_blob(); if
+ * %NM_SETTING_802_1X_CK_SCHEME_PATH, use
+ * nm_setting_802_1x_get_client_cert_path().
+ *
+ * Returns: scheme used to store the "phase 2" client certificate (blob or path)
+ **/
+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);
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_client_cert_blob:
+ * @setting: the #NMSetting8021x
+ *
+ * Client certificates are used to identify the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: (transfer none): the "phase 2" client certificate data
+ **/
+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;
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_client_cert_path:
+ * @setting: the #NMSetting8021x
+ *
+ * Client certificates are used to identify the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: path to the "phase 2" client certificate file
+ **/
+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 (SCHEME_PATH);
+}
+
+/**
+ * nm_setting_802_1x_set_phase2_client_cert:
+ * @setting: the #NMSetting8021x
+ * @cert_path: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH
+ * or %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the "phase2" client
+ * certificate file (PEM, DER, or PKCS#<!-- -->12 format). The path must be UTF-8
+ * encoded; use g_filename_to_utf8() to convert if needed. Passing %NULL with
+ * any @scheme clears the "phase2" client certificate.
+ * @scheme: desired storage scheme for the certificate
+ * @out_format: on successful return, the type of the certificate added
+ * @error: on unsuccessful return, an error
+ *
+ * Reads a certificate from disk and sets the #NMSetting8021x:phase2-client-cert
+ * property with the raw certificate data if using the
+ * %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the certificate
+ * file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme.
+ *
+ * Client certificates are used to identify the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful
+ **/
+gboolean
+nm_setting_802_1x_set_phase2_client_cert (NMSetting8021x *setting,
+ const char *cert_path,
+ NMSetting8021xCKScheme scheme,
+ 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 (cert_path) {
+ g_return_val_if_fail (g_utf8_validate (cert_path, -1, NULL), FALSE);
+ g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
+ || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH,
+ 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 (!cert_path) {
+ g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
+ return TRUE;
+ }
+
+ data = crypto_load_and_verify_certificate (cert_path, &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 (cert_path);
+ 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;
+}
+
+/**
+ * nm_setting_802_1x_get_password:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the password used by the authentication method, if any, as specified
+ * by the #NMSetting8021x:password property
+ **/
+const char *
+nm_setting_802_1x_get_password (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+ return NM_SETTING_802_1X_GET_PRIVATE (setting)->password;
+}
+
+/**
+ * nm_setting_802_1x_get_password_flags:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the #NMSettingSecretFlags pertaining to the #NMSetting8021x:password
+ **/
+NMSettingSecretFlags
+nm_setting_802_1x_get_password_flags (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_SECRET_FLAG_NONE);
+
+ return NM_SETTING_802_1X_GET_PRIVATE (setting)->password_flags;
+}
+
+/**
+ * nm_setting_802_1x_get_password_raw:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: (transfer none): the password used by the authentication method as a
+ * UTF-8-encoded array of bytes, as specified by the
+ * #NMSetting8021x:password-raw property
+ **/
+GBytes *
+nm_setting_802_1x_get_password_raw (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+ return NM_SETTING_802_1X_GET_PRIVATE (setting)->password_raw;
+}
+
+/**
+ * nm_setting_802_1x_get_password_raw_flags:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the #NMSettingSecretFlags pertaining to the
+ * #NMSetting8021x:password-raw
+ **/
+NMSettingSecretFlags
+nm_setting_802_1x_get_password_raw_flags (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_SECRET_FLAG_NONE);
+
+ return NM_SETTING_802_1X_GET_PRIVATE (setting)->password_raw_flags;
+}
+
+/**
+ * nm_setting_802_1x_get_pin:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the PIN used by the authentication method, if any, as specified
+ * by the #NMSetting8021x:pin property
+ **/
+const char *
+nm_setting_802_1x_get_pin (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+ return NM_SETTING_802_1X_GET_PRIVATE (setting)->pin;
+}
+
+/**
+ * nm_setting_802_1x_get_pin_flags:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the #NMSettingSecretFlags pertaining to the
+ * #NMSetting8021x:pin
+ **/
+NMSettingSecretFlags
+nm_setting_802_1x_get_pin_flags (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_SECRET_FLAG_NONE);
+
+ return NM_SETTING_802_1X_GET_PRIVATE (setting)->pin_flags;
+}
+
+/**
+ * nm_setting_802_1x_get_private_key_scheme:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the scheme used to store the private key. If the returned scheme is
+ * %NM_SETTING_802_1X_CK_SCHEME_BLOB, use
+ * nm_setting_802_1x_get_client_cert_blob(); if
+ * %NM_SETTING_802_1X_CK_SCHEME_PATH, use
+ * nm_setting_802_1x_get_client_cert_path().
+ *
+ * Returns: scheme used to store the private key (blob or path)
+ **/
+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);
+}
+
+/**
+ * nm_setting_802_1x_get_private_key_blob:
+ * @setting: the #NMSetting8021x
+ *
+ * Private keys are used to authenticate the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * WARNING: the private key property is not a "secret" property, and thus
+ * unencrypted private key data may be readable by unprivileged users. Private
+ * keys should always be encrypted with a private key password.
+ *
+ * Returns: (transfer none): the private key data
+ **/
+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;
+}
+
+/**
+ * nm_setting_802_1x_get_private_key_path:
+ * @setting: the #NMSetting8021x
+ *
+ * Private keys are used to authenticate the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: path to the private key file
+ **/
+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 (SCHEME_PATH);
+}
+
+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);
+ g_assert (array->len == length);
+ g_free (contents);
+ return g_bytes_new_with_free_func (array->data, array->len, free_secure_bytes, array);
+ }
+ return NULL;
+}
+
+/**
+ * nm_setting_802_1x_set_private_key:
+ * @setting: the #NMSetting8021x
+ * @key_path: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH or
+ * %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the private key file
+ * (PEM, DER, or PKCS#<!-- -->12 format). The path must be UTF-8 encoded; use
+ * g_filename_to_utf8() to convert if needed. Passing %NULL with any @scheme
+ * clears the private key.
+ * @password: password used to decrypt the private key, or %NULL if the password
+ * is unknown. If the password is given but fails to decrypt the private key,
+ * an error is returned.
+ * @scheme: desired storage scheme for the private key
+ * @out_format: on successful return, the type of the private key added
+ * @error: on unsuccessful return, an error
+ *
+ * Private keys are used to authenticate the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * This function reads a private key from disk and sets the
+ * #NMSetting8021x:private-key property with the private key file data if using
+ * the %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the private
+ * key file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme.
+ *
+ * If @password is given, this function attempts to decrypt the private key to
+ * verify that @password is correct, and if it is, updates the
+ * #NMSetting8021x:private-key-password property with the given @password. If
+ * the decryption is unsuccessful, %FALSE is returned, @error is set, and no
+ * internal data is changed. If no @password is given, the private key is
+ * assumed to be valid, no decryption is performed, and the password may be set
+ * at a later time.
+ *
+ * WARNING: the private key property is not a "secret" property, and thus
+ * unencrypted private key data using the BLOB scheme may be readable by
+ * unprivileged users. Private keys should always be encrypted with a private
+ * key password to prevent unauthorized access to unencrypted private key data.
+ *
+ * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful
+ **/
+gboolean
+nm_setting_802_1x_set_private_key (NMSetting8021x *setting,
+ const char *key_path,
+ const char *password,
+ NMSetting8021xCKScheme scheme,
+ NMSetting8021xCKFormat *out_format,
+ GError **error)
+{
+ NMSetting8021xPrivate *priv;
+ NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+ gboolean key_cleared = FALSE, password_cleared = FALSE;
+ GError *local_err = NULL;
+
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
+
+ if (key_path) {
+ g_return_val_if_fail (g_utf8_validate (key_path, -1, NULL), FALSE);
+ g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
+ || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH,
+ 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 (key_path) {
+ format = crypto_verify_private_key (key_path, 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);
+
+ /* Clear out any previous private key data */
+ if (priv->private_key) {
+ g_bytes_unref (priv->private_key);
+ priv->private_key = NULL;
+ key_cleared = TRUE;
+ }
+
+ if (priv->private_key_password) {
+ g_free (priv->private_key_password);
+ priv->private_key_password = NULL;
+ password_cleared = TRUE;
+ }
+
+ if (key_path == NULL) {
+ if (key_cleared)
+ g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PRIVATE_KEY);
+ if (password_cleared)
+ g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD);
+ return TRUE;
+ }
+
+ priv->private_key_password = g_strdup (password);
+ if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
+ /* Shouldn't fail this since we just verified the private key above */
+ priv->private_key = file_to_secure_bytes (key_path);
+ g_assert (priv->private_key);
+ } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
+ priv->private_key = path_to_scheme_value (key_path);
+ else
+ g_assert_not_reached ();
+
+ /* As required by NM and wpa_supplicant, set the client-cert
+ * property to the same PKCS#12 data.
+ */
+ g_assert (format != NM_CRYPTO_FILE_FORMAT_UNKNOWN);
+ 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_cleared || password)
+ g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD);
+
+ if (out_format)
+ *out_format = (NMSetting8021xCKFormat) format;
+ return priv->private_key != NULL;
+}
+
+/**
+ * nm_setting_802_1x_get_private_key_password:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the private key password used to decrypt the private key if
+ * previously set with nm_setting_802_1x_set_private_key(), or the
+ * #NMSetting8021x:private-key-password property.
+ **/
+const char *
+nm_setting_802_1x_get_private_key_password (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+ return NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key_password;
+}
+
+/**
+ * nm_setting_802_1x_get_private_key_password_flags:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the #NMSettingSecretFlags pertaining to the
+ * #NMSetting8021x:private-key-password
+ **/
+NMSettingSecretFlags
+nm_setting_802_1x_get_private_key_password_flags (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_SECRET_FLAG_NONE);
+
+ return NM_SETTING_802_1X_GET_PRIVATE (setting)->private_key_password_flags;
+}
+
+/**
+ * nm_setting_802_1x_get_private_key_format:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the data format of the private key data stored in the
+ * #NMSetting8021x:private-key property
+ **/
+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;
+ }
+ return NM_SETTING_802_1X_CK_FORMAT_RAW_KEY;
+ default:
+ break;
+ }
+
+ return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_private_key_password:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the private key password used to decrypt the private key if
+ * previously set with nm_setting_802_1x_set_phase2_private_key() or the
+ * #NMSetting8021x:phase2-private-key-password property.
+ **/
+const char *
+nm_setting_802_1x_get_phase2_private_key_password (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NULL);
+
+ return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key_password;
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_private_key_password_flags:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the #NMSettingSecretFlags pertaining to the
+ * #NMSetting8021x:phase2-private-key-password
+ **/
+NMSettingSecretFlags
+nm_setting_802_1x_get_phase2_private_key_password_flags (NMSetting8021x *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), NM_SETTING_SECRET_FLAG_NONE);
+
+ return NM_SETTING_802_1X_GET_PRIVATE (setting)->phase2_private_key_password_flags;
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_private_key_scheme:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns the scheme used to store the "phase 2" private key. If the returned
+ * scheme is %NM_SETTING_802_1X_CK_SCHEME_BLOB, use
+ * nm_setting_802_1x_get_client_cert_blob(); if
+ * %NM_SETTING_802_1X_CK_SCHEME_PATH, use
+ * nm_setting_802_1x_get_client_cert_path().
+ *
+ * Returns: scheme used to store the "phase 2" private key (blob or path)
+ **/
+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);
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_private_key_blob:
+ * @setting: the #NMSetting8021x
+ *
+ * Private keys are used to authenticate the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * WARNING: the phase2 private key property is not a "secret" property, and thus
+ * unencrypted private key data may be readable by unprivileged users. Private
+ * keys should always be encrypted with a private key password.
+ *
+ * Returns: (transfer none): the "phase 2" private key data
+ **/
+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;
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_private_key_path:
+ * @setting: the #NMSetting8021x
+ *
+ * Private keys are used to authenticate the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * Returns: path to the "phase 2" private key file
+ **/
+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 (SCHEME_PATH);
+}
+
+/**
+ * nm_setting_802_1x_set_phase2_private_key:
+ * @setting: the #NMSetting8021x
+ * @key_path: when @scheme is set to either %NM_SETTING_802_1X_CK_SCHEME_PATH or
+ * %NM_SETTING_802_1X_CK_SCHEME_BLOB, pass the path of the "phase2" private
+ * key file (PEM, DER, or PKCS#<!-- -->12 format). The path must be UTF-8 encoded;
+ * use g_filename_to_utf8() to convert if needed. Passing %NULL with any
+ * @scheme clears the private key.
+ * @password: password used to decrypt the private key, or %NULL if the password
+ * is unknown. If the password is given but fails to decrypt the private key,
+ * an error is returned.
+ * @scheme: desired storage scheme for the private key
+ * @out_format: on successful return, the type of the private key added
+ * @error: on unsuccessful return, an error
+ *
+ * Private keys are used to authenticate the connecting client to the network
+ * when EAP-TLS is used as either the "phase 1" or "phase 2" 802.1x
+ * authentication method.
+ *
+ * This function reads a private key from disk and sets the
+ * #NMSetting8021x:phase2-private-key property with the private key file data if
+ * using the %NM_SETTING_802_1X_CK_SCHEME_BLOB scheme, or with the path to the
+ * private key file if using the %NM_SETTING_802_1X_CK_SCHEME_PATH scheme.
+ *
+ * If @password is given, this function attempts to decrypt the private key to
+ * verify that @password is correct, and if it is, updates the
+ * #NMSetting8021x:phase2-private-key-password property with the given
+ * @password. If the decryption is unsuccessful, %FALSE is returned, @error is
+ * set, and no internal data is changed. If no @password is given, the private
+ * key is assumed to be valid, no decryption is performed, and the password may
+ * be set at a later time.
+ *
+ * WARNING: the "phase2" private key property is not a "secret" property, and
+ * thus unencrypted private key data using the BLOB scheme may be readable by
+ * unprivileged users. Private keys should always be encrypted with a private
+ * key password to prevent unauthorized access to unencrypted private key data.
+ *
+ * Returns: %TRUE if the operation succeeded, %FALSE if it was unsuccessful
+ **/
+gboolean
+nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *setting,
+ const char *key_path,
+ const char *password,
+ NMSetting8021xCKScheme scheme,
+ NMSetting8021xCKFormat *out_format,
+ GError **error)
+{
+ NMSetting8021xPrivate *priv;
+ NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+ gboolean key_cleared = FALSE, password_cleared = FALSE;
+ GError *local_err = NULL;
+
+ g_return_val_if_fail (NM_IS_SETTING_802_1X (setting), FALSE);
+
+ if (key_path) {
+ g_return_val_if_fail (g_utf8_validate (key_path, -1, NULL), FALSE);
+ g_return_val_if_fail ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
+ || scheme == NM_SETTING_802_1X_CK_SCHEME_PATH,
+ 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 (key_path) {
+ format = crypto_verify_private_key (key_path, 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);
+
+ /* Clear out any previous private key data */
+ if (priv->phase2_private_key) {
+ g_bytes_unref (priv->phase2_private_key);
+ priv->phase2_private_key = NULL;
+ key_cleared = TRUE;
+ }
+
+ if (priv->phase2_private_key_password) {
+ g_free (priv->phase2_private_key_password);
+ priv->phase2_private_key_password = NULL;
+ password_cleared = TRUE;
+ }
+
+ if (key_path == NULL) {
+ if (key_cleared)
+ g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
+ if (password_cleared)
+ g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD);
+ return TRUE;
+ }
+
+ priv->phase2_private_key_password = g_strdup (password);
+ if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
+ /* Shouldn't fail this since we just verified the private key above */
+ priv->phase2_private_key = file_to_secure_bytes (key_path);
+ g_assert (priv->phase2_private_key);
+ } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
+ priv->phase2_private_key = path_to_scheme_value (key_path);
+ else
+ g_assert_not_reached ();
+
+ /* As required by NM and wpa_supplicant, set the client-cert
+ * property to the same PKCS#12 data.
+ */
+ g_assert (format != NM_CRYPTO_FILE_FORMAT_UNKNOWN);
+ 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_cleared || password)
+ g_object_notify (G_OBJECT (setting), NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD);
+
+ if (out_format)
+ *out_format = (NMSetting8021xCKFormat) format;
+ return priv->phase2_private_key != NULL;
+}
+
+/**
+ * nm_setting_802_1x_get_phase2_private_key_format:
+ * @setting: the #NMSetting8021x
+ *
+ * Returns: the data format of the "phase 2" private key data stored in the
+ * #NMSetting8021x:phase2-private-key property
+ **/
+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;
+ }
+ return NM_SETTING_802_1X_CK_FORMAT_RAW_KEY;
+ default:
+ break;
+ }
+
+ return NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+}
+
+static void
+need_secrets_password (NMSetting8021x *self,
+ GPtrArray *secrets,
+ gboolean phase2)
+{
+ NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self);
+
+ if ( (!priv->password || !strlen (priv->password))
+ && (!priv->password_raw || !g_bytes_get_size (priv->password_raw))) {
+ g_ptr_array_add (secrets, NM_SETTING_802_1X_PASSWORD);
+ g_ptr_array_add (secrets, NM_SETTING_802_1X_PASSWORD_RAW);
+ }
+}
+
+static void
+need_secrets_sim (NMSetting8021x *self,
+ GPtrArray *secrets,
+ gboolean phase2)
+{
+ NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self);
+
+ if (!priv->pin || !strlen (priv->pin))
+ g_ptr_array_add (secrets, NM_SETTING_802_1X_PIN);
+}
+
+static gboolean
+need_private_key_password (GBytes *blob,
+ const char *path,
+ const char *password)
+{
+ NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+
+ /* Private key password is required */
+ if (password) {
+ if (path)
+ format = 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);
+ else
+ g_warning ("%s: unknown private key password scheme", __func__);
+ }
+
+ return (format == NM_CRYPTO_FILE_FORMAT_UNKNOWN);
+}
+
+static void
+need_secrets_tls (NMSetting8021x *self,
+ GPtrArray *secrets,
+ gboolean phase2)
+{
+ NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self);
+ NMSetting8021xCKScheme scheme;
+ GBytes *blob = NULL;
+ const char *path = NULL;
+
+ if (phase2) {
+ scheme = nm_setting_802_1x_get_phase2_private_key_scheme (self);
+ if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
+ path = nm_setting_802_1x_get_phase2_private_key_path (self);
+ else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB)
+ blob = nm_setting_802_1x_get_phase2_private_key_blob (self);
+ else {
+ g_warning ("%s: unknown phase2 private key scheme %d", __func__, scheme);
+ g_ptr_array_add (secrets, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
+ return;
+ }
+
+ if (need_private_key_password (blob, path, priv->phase2_private_key_password))
+ g_ptr_array_add (secrets, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD);
+ } else {
+ scheme = nm_setting_802_1x_get_private_key_scheme (self);
+ if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH)
+ path = nm_setting_802_1x_get_private_key_path (self);
+ else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB)
+ blob = nm_setting_802_1x_get_private_key_blob (self);
+ else {
+ g_warning ("%s: unknown private key scheme %d", __func__, scheme);
+ g_ptr_array_add (secrets, NM_SETTING_802_1X_PRIVATE_KEY);
+ return;
+ }
+
+ if (need_private_key_password (blob, path, priv->private_key_password))
+ g_ptr_array_add (secrets, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD);
+ }
+}
+
+static gboolean
+verify_tls (NMSetting8021x *self, gboolean phase2, GError **error)
+{
+ NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self);
+
+ if (phase2) {
+ if (!priv->phase2_client_cert) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
+ return FALSE;
+ } else if (!g_bytes_get_size (priv->phase2_client_cert)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
+ return FALSE;
+ }
+
+ /* Private key is required for TLS */
+ if (!priv->phase2_private_key) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
+ return FALSE;
+ } else if (!g_bytes_get_size (priv->phase2_private_key)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
+ return FALSE;
+ }
+
+ /* 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 (!g_bytes_equal (priv->phase2_private_key, priv->phase2_client_cert)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("has to match '%s' property for PKCS#12"),
+ NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
+ return FALSE;
+ }
+ }
+ } else {
+ if (!priv->client_cert) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_CLIENT_CERT);
+ return FALSE;
+ } else if (!g_bytes_get_size (priv->client_cert)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_CLIENT_CERT);
+ return FALSE;
+ }
+
+ /* Private key is required for TLS */
+ if (!priv->private_key) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PRIVATE_KEY);
+ return FALSE;
+ } else if (!g_bytes_get_size (priv->private_key)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PRIVATE_KEY);
+ return FALSE;
+ }
+
+ /* 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 (!g_bytes_equal (priv->private_key, priv->client_cert)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("has to match '%s' property for PKCS#12"),
+ NM_SETTING_802_1X_PRIVATE_KEY);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_CLIENT_CERT);
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+verify_ttls (NMSetting8021x *self, gboolean phase2, GError **error)
+{
+ NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self);
+
+ if ( (!priv->identity || !strlen (priv->identity))
+ && (!priv->anonymous_identity || !strlen (priv->anonymous_identity))) {
+ if (!priv->identity) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_IDENTITY);
+ } else if (!strlen (priv->identity)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_IDENTITY);
+ } else if (!priv->anonymous_identity) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_ANONYMOUS_IDENTITY);
+ } else {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_ANONYMOUS_IDENTITY);
+ }
+ return FALSE;
+ }
+
+ if ( (!priv->phase2_auth || !strlen (priv->phase2_auth))
+ && (!priv->phase2_autheap || !strlen (priv->phase2_autheap))) {
+ if (!priv->phase2_auth) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_AUTH);
+ } else if (!strlen (priv->phase2_auth)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_AUTH);
+ } else if (!priv->phase2_autheap) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_AUTHEAP);
+ } else {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_AUTHEAP);
+ }
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+verify_identity (NMSetting8021x *self, gboolean phase2, GError **error)
+{
+ NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self);
+
+ if (!priv->identity) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_IDENTITY);
+ return FALSE;
+ } else if (!strlen (priv->identity)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_IDENTITY);
+ return FALSE;
+ }
+
+ 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,
+ gboolean phase2)
+{
+ NMSetting8021xPrivate *priv = NM_SETTING_802_1X_GET_PRIVATE (self);
+ char *method = NULL;
+ int i;
+
+ g_return_if_fail (phase2 == FALSE);
+
+ /* Check phase2_auth and phase2_autheap */
+ method = priv->phase2_auth;
+ if (!method && priv->phase2_autheap)
+ method = priv->phase2_autheap;
+
+ if (!method) {
+ g_warning ("Couldn't find EAP method.");
+ g_assert_not_reached();
+ return;
+ }
+
+ /* Ask the configured phase2 method if it needs secrets */
+ 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, TRUE);
+ break;
+ }
+ }
+}
+
+
+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, GError **error)
+{
+ gconstpointer data;
+ gsize length;
+
+ if (!bytes)
+ return TRUE;
+
+ switch (get_cert_scheme (bytes)) {
+ case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+ return TRUE;
+ case NM_SETTING_802_1X_CK_SCHEME_PATH:
+ /* For path-based schemes, verify that the path is zero-terminated */
+ data = g_bytes_get_data (bytes, &length);
+ if (((const guchar *)data)[length - 1] == '\0') {
+ /* And ensure it's UTF-8 valid too so we can pass it through
+ * D-Bus and stuff like that.
+ */
+ if (g_utf8_validate ((const char *)data + strlen (SCHEME_PATH), -1, NULL))
+ return TRUE;
+ }
+ break;
+ default:
+ break;
+ }
+
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, prop_name);
+ return FALSE;
+}
+
+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 };
+ GSList *iter;
+
+ if (error)
+ g_return_val_if_fail (*error == NULL, FALSE);
+
+ if (!priv->eap) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_EAP);
+ return FALSE;
+ }
+
+ if (!_nm_utils_string_slist_validate (priv->eap, valid_eap)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_EAP);
+ return FALSE;
+ }
+
+ /* Ask each configured EAP method if its valid */
+ for (iter = priv->eap; iter; 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].v_func == NULL)
+ continue;
+ if (!strcmp (eap_methods_table[i].method, method)) {
+ if (!(*eap_methods_table[i].v_func) (self, FALSE, error))
+ return FALSE;
+ break;
+ }
+ }
+ }
+
+ if (priv->phase1_peapver && !_nm_utils_string_in_list (priv->phase1_peapver, valid_phase1_peapver)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid value for the property"),
+ priv->phase1_peapver);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE1_PEAPVER);
+ return FALSE;
+ }
+
+ if (priv->phase1_peaplabel && !_nm_utils_string_in_list (priv->phase1_peaplabel, valid_phase1_peaplabel)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid value for the property"),
+ priv->phase1_peaplabel);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE1_PEAPLABEL);
+ return FALSE;
+ }
+
+ if (priv->phase1_fast_provisioning && !_nm_utils_string_in_list (priv->phase1_fast_provisioning, valid_phase1_fast_pac)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid value for the property"),
+ priv->phase1_fast_provisioning);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING);
+ return FALSE;
+ }
+
+ if (priv->phase2_auth && !_nm_utils_string_in_list (priv->phase2_auth, valid_phase2_auth)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid value for the property"),
+ priv->phase2_auth);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_AUTH);
+ return FALSE;
+ }
+
+ if (priv->phase2_autheap && !_nm_utils_string_in_list (priv->phase2_autheap, valid_phase2_autheap)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid value for the property"),
+ priv->phase2_autheap);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_802_1X_SETTING_NAME, NM_SETTING_802_1X_PHASE2_AUTHEAP);
+ return FALSE;
+ }
+
+ if (!verify_cert (priv->ca_cert, NM_SETTING_802_1X_CA_CERT, error))
+ return FALSE;
+ if (!verify_cert (priv->phase2_ca_cert, NM_SETTING_802_1X_PHASE2_CA_CERT, error))
+ return FALSE;
+
+ if (!verify_cert (priv->client_cert, NM_SETTING_802_1X_CLIENT_CERT, error))
+ return FALSE;
+ if (!verify_cert (priv->phase2_client_cert, NM_SETTING_802_1X_PHASE2_CLIENT_CERT, error))
+ return FALSE;
+
+ if (!verify_cert (priv->private_key, NM_SETTING_802_1X_PRIVATE_KEY, error))
+ return FALSE;
+ if (!verify_cert (priv->phase2_private_key, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, error))
+ return FALSE;
+
+ /* FIXME: finish */
+
+ return TRUE;
+}
+
+static void
+nm_setting_802_1x_init (NMSetting8021x *setting)
+{
+}
+
+static void
+finalize (GObject *object)
+{
+ 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_free (priv->identity);
+ g_free (priv->anonymous_identity);
+ g_free (priv->ca_path);
+ g_free (priv->subject_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->password);
+ if (priv->password_raw)
+ 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);
+
+ if (priv->ca_cert)
+ g_bytes_unref (priv->ca_cert);
+ if (priv->client_cert)
+ g_bytes_unref (priv->client_cert);
+ 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);
+ if (priv->phase2_client_cert)
+ g_bytes_unref (priv->phase2_client_cert);
+ if (priv->phase2_private_key)
+ g_bytes_unref (priv->phase2_private_key);
+ g_free (priv->phase2_private_key_password);
+
+ G_OBJECT_CLASS (nm_setting_802_1x_parent_class)->finalize (object);
+}
+
+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, error);
+ if (!valid)
+ g_clear_pointer (&bytes, g_bytes_unref);
+ }
+ return bytes;
+}
+
+static void
+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);
+ 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));
+ break;
+ case PROP_IDENTITY:
+ g_free (priv->identity);
+ priv->identity = g_value_dup_string (value);
+ break;
+ case PROP_ANONYMOUS_IDENTITY:
+ g_free (priv->anonymous_identity);
+ priv->anonymous_identity = g_value_dup_string (value);
+ break;
+ case PROP_PAC_FILE:
+ g_free (priv->pac_file);
+ priv->pac_file = g_value_dup_string (value);
+ 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): (%d) %s",
+ error->code, error->message);
+ g_error_free (error);
+ }
+ break;
+ case PROP_CA_PATH:
+ g_free (priv->ca_path);
+ priv->ca_path = g_value_dup_string (value);
+ break;
+ case PROP_SUBJECT_MATCH:
+ g_free (priv->subject_match);
+ priv->subject_match = g_value_dup_string (value);
+ 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));
+ 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): (%d) %s",
+ error->code, error->message);
+ g_error_free (error);
+ }
+ break;
+ case PROP_PHASE1_PEAPVER:
+ g_free (priv->phase1_peapver);
+ priv->phase1_peapver = g_value_dup_string (value);
+ break;
+ case PROP_PHASE1_PEAPLABEL:
+ g_free (priv->phase1_peaplabel);
+ priv->phase1_peaplabel = g_value_dup_string (value);
+ break;
+ case PROP_PHASE1_FAST_PROVISIONING:
+ g_free (priv->phase1_fast_provisioning);
+ priv->phase1_fast_provisioning = g_value_dup_string (value);
+ break;
+ case PROP_PHASE2_AUTH:
+ g_free (priv->phase2_auth);
+ priv->phase2_auth = g_value_dup_string (value);
+ break;
+ case PROP_PHASE2_AUTHEAP:
+ g_free (priv->phase2_autheap);
+ priv->phase2_autheap = g_value_dup_string (value);
+ 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): (%d) %s",
+ error->code, error->message);
+ g_error_free (error);
+ }
+ break;
+ case PROP_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_free (priv->phase2_subject_match);
+ priv->phase2_subject_match = g_value_dup_string (value);
+ 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));
+ 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): (%d) %s",
+ error->code, error->message);
+ g_error_free (error);
+ }
+ break;
+ case PROP_PASSWORD:
+ g_free (priv->password);
+ priv->password = g_value_dup_string (value);
+ break;
+ case PROP_PASSWORD_FLAGS:
+ priv->password_flags = g_value_get_flags (value);
+ break;
+ case PROP_PASSWORD_RAW:
+ if (priv->password_raw)
+ g_bytes_unref (priv->password_raw);
+ priv->password_raw = g_value_dup_boxed (value);
+ break;
+ case PROP_PASSWORD_RAW_FLAGS:
+ priv->password_raw_flags = g_value_get_flags (value);
+ 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): (%d) %s",
+ error->code, error->message);
+ g_error_free (error);
+ }
+ break;
+ case PROP_PRIVATE_KEY_PASSWORD:
+ g_free (priv->private_key_password);
+ priv->private_key_password = g_value_dup_string (value);
+ break;
+ case PROP_PRIVATE_KEY_PASSWORD_FLAGS:
+ priv->private_key_password_flags = g_value_get_flags (value);
+ 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): (%d) %s",
+ error->code, error->message);
+ g_error_free (error);
+ }
+ break;
+ case PROP_PHASE2_PRIVATE_KEY_PASSWORD:
+ g_free (priv->phase2_private_key_password);
+ priv->phase2_private_key_password = g_value_dup_string (value);
+ break;
+ case PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS:
+ priv->phase2_private_key_password_flags = g_value_get_flags (value);
+ break;
+ case PROP_PIN:
+ g_free (priv->pin);
+ priv->pin = g_value_dup_string (value);
+ break;
+ case PROP_PIN_FLAGS:
+ priv->pin_flags = g_value_get_flags (value);
+ break;
+ case PROP_SYSTEM_CA_CERTS:
+ priv->system_ca_certs = g_value_get_boolean (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)
+{
+ 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));
+ break;
+ case PROP_IDENTITY:
+ g_value_set_string (value, priv->identity);
+ break;
+ case PROP_ANONYMOUS_IDENTITY:
+ g_value_set_string (value, priv->anonymous_identity);
+ break;
+ case PROP_PAC_FILE:
+ g_value_set_string (value, priv->pac_file);
+ break;
+ case PROP_CA_CERT:
+ g_value_set_boxed (value, priv->ca_cert);
+ break;
+ case PROP_CA_PATH:
+ g_value_set_string (value, priv->ca_path);
+ break;
+ case PROP_SUBJECT_MATCH:
+ g_value_set_string (value, priv->subject_match);
+ break;
+ case PROP_ALTSUBJECT_MATCHES:
+ g_value_take_boxed (value, _nm_utils_slist_to_strv (priv->altsubject_matches));
+ break;
+ case PROP_CLIENT_CERT:
+ g_value_set_boxed (value, priv->client_cert);
+ break;
+ case PROP_PHASE1_PEAPVER:
+ g_value_set_string (value, priv->phase1_peapver);
+ break;
+ case PROP_PHASE1_PEAPLABEL:
+ g_value_set_string (value, priv->phase1_peaplabel);
+ break;
+ case PROP_PHASE1_FAST_PROVISIONING:
+ g_value_set_string (value, priv->phase1_fast_provisioning);
+ break;
+ case PROP_PHASE2_AUTH:
+ g_value_set_string (value, priv->phase2_auth);
+ break;
+ case PROP_PHASE2_AUTHEAP:
+ g_value_set_string (value, priv->phase2_autheap);
+ break;
+ case PROP_PHASE2_CA_CERT:
+ g_value_set_boxed (value, priv->phase2_ca_cert);
+ break;
+ case PROP_PHASE2_CA_PATH:
+ g_value_set_string (value, priv->phase2_ca_path);
+ break;
+ case PROP_PHASE2_SUBJECT_MATCH:
+ g_value_set_string (value, priv->phase2_subject_match);
+ break;
+ case PROP_PHASE2_ALTSUBJECT_MATCHES:
+ g_value_take_boxed (value, _nm_utils_slist_to_strv (priv->phase2_altsubject_matches));
+ break;
+ case PROP_PHASE2_CLIENT_CERT:
+ g_value_set_boxed (value, priv->phase2_client_cert);
+ break;
+ case PROP_PASSWORD:
+ g_value_set_string (value, priv->password);
+ break;
+ case PROP_PASSWORD_FLAGS:
+ g_value_set_flags (value, priv->password_flags);
+ break;
+ case PROP_PASSWORD_RAW:
+ g_value_set_boxed (value, priv->password_raw);
+ break;
+ case PROP_PASSWORD_RAW_FLAGS:
+ g_value_set_flags (value, priv->password_raw_flags);
+ break;
+ case PROP_PRIVATE_KEY:
+ g_value_set_boxed (value, priv->private_key);
+ break;
+ case PROP_PRIVATE_KEY_PASSWORD:
+ g_value_set_string (value, priv->private_key_password);
+ break;
+ case PROP_PRIVATE_KEY_PASSWORD_FLAGS:
+ g_value_set_flags (value, priv->private_key_password_flags);
+ break;
+ case PROP_PHASE2_PRIVATE_KEY:
+ g_value_set_boxed (value, priv->phase2_private_key);
+ break;
+ case PROP_PHASE2_PRIVATE_KEY_PASSWORD:
+ g_value_set_string (value, priv->phase2_private_key_password);
+ break;
+ case PROP_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS:
+ g_value_set_flags (value, priv->phase2_private_key_password_flags);
+ break;
+ case PROP_PIN:
+ g_value_set_string (value, priv->pin);
+ break;
+ case PROP_PIN_FLAGS:
+ g_value_set_flags (value, priv->pin_flags);
+ break;
+ case PROP_SYSTEM_CA_CERTS:
+ g_value_set_boolean (value, priv->system_ca_certs);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_setting_802_1x_class_init (NMSetting8021xClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+ NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+ g_type_class_add_private (setting_class, 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 */
+
+ /**
+ * NMSetting8021x:eap:
+ *
+ * The allowed EAP method to be used when authenticating to the network with
+ * 802.1x. Valid methods are: "leap", "md5", "tls", "peap", "ttls", "pwd",
+ * and "fast". Each method requires different configuration using the
+ * properties of this setting; refer to wpa_supplicant documentation for the
+ * allowed combinations.
+ **/
+ /* ---ifcfg-rh---
+ * property: eap
+ * variable: IEEE_8021X_EAP_METHODS(+)
+ * values: "LEAP", "PWD", "TLS", "PEAP", "TTLS", "FAST"
+ * description: EAP method for 802.1X authentication.
+ * 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));
+
+ /**
+ * NMSetting8021x:identity:
+ *
+ * Identity string for EAP authentication methods. Often the user's user or
+ * login name.
+ **/
+ /* ---ifcfg-rh---
+ * property: identity
+ * variable: IEEE_8021X_IDENTITY(+)
+ * description: Identity for EAP authentication methods.
+ * 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));
+
+ /**
+ * NMSetting8021x:anonymous-identity:
+ *
+ * Anonymous identity string for EAP authentication methods. Used as the
+ * unencrypted identity with EAP types that support different tunneled
+ * identity like EAP-TTLS.
+ **/
+ /* ---ifcfg-rh---
+ * property: anonymous-identity
+ * variable: IEEE_8021X_ANON_IDENTITY(+)
+ * 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));
+
+ /**
+ * NMSetting8021x:pac-file:
+ *
+ * UTF-8 encoded file path containing PAC for EAP-FAST.
+ **/
+ /* ---ifcfg-rh---
+ * property: pac-file
+ * variable: IEEE_8021X_PAC_FILE(+)
+ * description: File with PAC (Protected Access Credential) for EAP-FAST.
+ * 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));
+
+ /**
+ * NMSetting8021x:ca-cert:
+ *
+ * Contains the CA certificate if used by the EAP method specified in the
+ * #NMSetting8021x:eap property.
+ *
+ * Certificate data is specified using a "scheme"; two are currently
+ * supported: blob and path. When using the blob scheme (which is backwards
+ * compatible with NM 0.7.x) this property should be set to the
+ * certificate's DER encoded data. When using the path scheme, this property
+ * should be set to the full UTF-8 encoded path of the certificate, prefixed
+ * with the string "file://" and ending with a terminating NUL byte. This
+ * property can be unset even if the EAP method supports CA certificates,
+ * but this allows man-in-the-middle attacks and is NOT recommended.
+ *
+ * Setting this property directly is discouraged; use the
+ * nm_setting_802_1x_set_ca_cert() function instead.
+ **/
+ /* ---ifcfg-rh---
+ * property: ca-cert
+ * variable: IEEE_8021X_CA_CERT(+)
+ * description: CA certificate for EAP.
+ * 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));
+
+ /**
+ * NMSetting8021x:ca-path:
+ *
+ * UTF-8 encoded path to a directory containing PEM or DER formatted
+ * certificates to be added to the verification chain in addition to the
+ * certificate specified in the #NMSetting8021x:ca-cert property.
+ **/
+ /* ---ifcfg-rh---
+ * property: ca-path
+ * variable: (none)
+ * 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));
+
+ /**
+ * NMSetting8021x:subject-match:
+ *
+ * Substring to be matched against the subject of the certificate presented
+ * by the authentication server. When unset, no verification of the
+ * authentication server certificate's subject is performed.
+ **/
+ /* ---ifcfg-rh---
+ * property: subject-match
+ * variable: IEEE_8021X_SUBJECT_MATCH(+)
+ * description: Substring to match subject of server certificate against.
+ * 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));
+
+ /**
+ * NMSetting8021x:altsubject-matches:
+ *
+ * List of strings to be matched against the altSubjectName of the
+ * certificate presented by the authentication server. If the list is empty,
+ * no verification of the server certificate's altSubjectName is performed.
+ **/
+ /* ---ifcfg-rh---
+ * property: altubject-matches
+ * variable: IEEE_8021X_AlTSUBJECT_MATCHES(+)
+ * description: List of strings to be matched against the altSubjectName.
+ * 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));
+
+ /**
+ * NMSetting8021x:client-cert:
+ *
+ * Contains the client certificate if used by the EAP method specified in
+ * the #NMSetting8021x:eap property.
+ *
+ * Certificate data is specified using a "scheme"; two are currently
+ * supported: blob and path. When using the blob scheme (which is backwards
+ * compatible with NM 0.7.x) this property should be set to the
+ * certificate's DER encoded data. When using the path scheme, this property
+ * should be set to the full UTF-8 encoded path of the certificate, prefixed
+ * with the string "file://" and ending with a terminating NUL byte.
+ *
+ * Setting this property directly is discouraged; use the
+ * nm_setting_802_1x_set_client_cert() function instead.
+ **/
+ /* ---ifcfg-rh---
+ * property: client-cert
+ * variable: IEEE_8021X_CLIENT_CERT(+)
+ * description: Client certificate for EAP.
+ * 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));
+
+ /**
+ * NMSetting8021x:phase1-peapver:
+ *
+ * Forces which PEAP version is used when PEAP is set as the EAP method in
+ * the #NMSetting8021x:eap property. When unset, the version reported by
+ * the server will be used. Sometimes when using older RADIUS servers, it
+ * is necessary to force the client to use a particular PEAP version. To do
+ * so, this property may be set to "0" or "1" to force that specific PEAP
+ * version.
+ **/
+ /* ---ifcfg-rh---
+ * property: phase1-peapver
+ * variable: IEEE_8021X_PEAP_VERSION(+)
+ * values: 0, 1
+ * 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));
+
+ /**
+ * NMSetting8021x:phase1-peaplabel:
+ *
+ * Forces use of the new PEAP label during key derivation. Some RADIUS
+ * servers may require forcing the new PEAP label to interoperate with
+ * PEAPv1. Set to "1" to force use of the new PEAP label. See the
+ * wpa_supplicant documentation for more details.
+ **/
+ /* ---ifcfg-rh---
+ * property: phase1-peaplabel
+ * variable: IEEE_8021X_PEAP_FORCE_NEW_LABEL(+)
+ * values: yes, no
+ * default: no
+ * 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));
+
+ /**
+ * NMSetting8021x:phase1-fast-provisioning:
+ *
+ * Enables or disables in-line provisioning of EAP-FAST credentials when
+ * FAST is specified as the EAP method in the #NMSetting8021x:eap property.
+ * Recognized values are "0" (disabled), "1" (allow unauthenticated
+ * provisioning), "2" (allow authenticated provisioning), and "3" (allow
+ * both authenticated and unauthenticated provisioning). See the
+ * wpa_supplicant documentation for more details.
+ **/
+ /* ---ifcfg-rh---
+ * property: phase1-fast-provisioning
+ * variable: IEEE_8021X_FAST_PROVISIONING(+)
+ * values: space-separated list of these values [allow-auth, allow-unauth]
+ * description: Enable in-line provisioning of EAP-FAST credentials.
+ * 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));
+
+ /**
+ * NMSetting8021x:phase2-auth:
+ *
+ * Specifies the allowed "phase 2" inner non-EAP authentication methods when
+ * an EAP method that uses an inner TLS tunnel is specified in the
+ * #NMSetting8021x:eap property. Recognized non-EAP "phase 2" methods are
+ * "pap", "chap", "mschap", "mschapv2", "gtc", "otp", "md5", and "tls".
+ * Each "phase 2" inner method requires specific parameters for successful
+ * authentication; see the wpa_supplicant documentation for more details.
+ **/
+ /* ---ifcfg-rh---
+ * property: phase2-auth
+ * variable: IEEE_8021X_INNER_AUTH_METHODS(+)
+ * values: "PAP", "CHAP", "MSCHAP", "MSCHAPV2", "GTC", "OTP", "MD5" and "TLS"
+ * description: Inner non-EAP authentication methods. IEEE_8021X_INNER_AUTH_METHODS
+ * can contain values both for 'phase2-auth' and 'phase2-autheap' properties.
+ * 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));
+
+ /**
+ * NMSetting8021x:phase2-autheap:
+ *
+ * Specifies the allowed "phase 2" inner EAP-based authentication methods
+ * when an EAP method that uses an inner TLS tunnel is specified in the
+ * #NMSetting8021x:eap property. Recognized EAP-based "phase 2" methods are
+ * "md5", "mschapv2", "otp", "gtc", and "tls". Each "phase 2" inner method
+ * requires specific parameters for successful authentication; see the
+ * wpa_supplicant documentation for more details.
+ **/
+ /* ---ifcfg-rh---
+ * property: phase2-autheap
+ * variable: IEEE_8021X_INNER_AUTH_METHODS(+)
+ * values: "EAP-MD5", "EAP-MSCHAPV2", "EAP-GTC", "EAP-OTP" and "EAP-TLS"
+ * description: Inner EAP-based authentication methods. Note that
+ * IEEE_8021X_INNER_AUTH_METHODS is also used for 'phase2-auth' values.
+ * 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));
+
+ /**
+ * NMSetting8021x:phase2-ca-cert:
+ *
+ * Contains the "phase 2" CA certificate if used by the EAP method specified
+ * in the #NMSetting8021x:phase2-auth or #NMSetting8021x:phase2-autheap
+ * properties.
+ *
+ * Certificate data is specified using a "scheme"; two are currently
+ * supported: blob and path. When using the blob scheme (which is backwards
+ * compatible with NM 0.7.x) this property should be set to the
+ * certificate's DER encoded data. When using the path scheme, this property
+ * should be set to the full UTF-8 encoded path of the certificate, prefixed
+ * with the string "file://" and ending with a terminating NUL byte. This
+ * property can be unset even if the EAP method supports CA certificates,
+ * but this allows man-in-the-middle attacks and is NOT recommended.
+ *
+ * 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));
+
+ /**
+ * NMSetting8021x:phase2-ca-path:
+ *
+ * UTF-8 encoded path to a directory containing PEM or DER formatted
+ * 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));
+
+ /**
+ * NMSetting8021x:phase2-subject-match:
+ *
+ * Substring to be matched against the subject of the certificate presented
+ * by the authentication server during the inner "phase 2"
+ * authentication. When unset, no verification of the authentication server
+ * certificate's subject is performed.
+ **/
+ /* ---ifcfg-rh---
+ * property: phase2-subject-match
+ * variable: IEEE_8021X_PHASE2_SUBJECT_MATCH(+)
+ * description: Substring to match subject of server certificate against.
+ * 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));
+
+ /**
+ * NMSetting8021x:phase2-altsubject-matches:
+ *
+ * List of strings to be matched against the altSubjectName of the
+ * certificate presented by the authentication server during the inner
+ * "phase 2" authentication. If the list is empty, no verification of the
+ * server certificate's altSubjectName is performed.
+ **/
+ /* ---ifcfg-rh---
+ * property: phase2-altsubject-matches
+ * 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));
+
+ /**
+ * NMSetting8021x:phase2-client-cert:
+ *
+ * Contains the "phase 2" client certificate if used by the EAP method
+ * specified in the #NMSetting8021x:phase2-auth or
+ * #NMSetting8021x:phase2-autheap properties.
+ *
+ * Certificate data is specified using a "scheme"; two are currently
+ * supported: blob and path. When using the blob scheme (which is backwards
+ * compatible with NM 0.7.x) this property should be set to the
+ * certificate's DER encoded data. When using the path scheme, this property
+ * should be set to the full UTF-8 encoded path of the certificate, prefixed
+ * with the string "file://" and ending with a terminating NUL byte. This
+ * property can be unset even if the EAP method supports CA certificates,
+ * but this allows man-in-the-middle attacks and is NOT recommended.
+ *
+ * Setting this property directly is discouraged; use the
+ * nm_setting_802_1x_set_phase2_client_cert() function instead.
+ **/
+ /* ---ifcfg-rh---
+ * property: phase2-client-cert
+ * variable: IEEE_8021X_INNER_CLIENT_CERT(+)
+ * description: Client certificate for inner EAP method.
+ * 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));
+
+ /**
+ * NMSetting8021x:password:
+ *
+ * UTF-8 encoded password used for EAP authentication methods. If both the
+ * #NMSetting8021x:password property and the #NMSetting8021x:password-raw
+ * property are specified, #NMSetting8021x:password is preferred.
+ **/
+ /* ---ifcfg-rh---
+ * property: password
+ * variable: IEEE_8021X_PASSWORD(+)
+ * description: UTF-8 encoded password used for EAP. It can also go to "key-"
+ * 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));
+
+ /**
+ * NMSetting8021x:password-flags:
+ *
+ * Flags indicating how to handle the #NMSetting8021x:password property.
+ **/
+ /* ---ifcfg-rh---
+ * property: password-flags
+ * variable: IEEE_8021X_PASSWORD_FLAGS(+)
+ * format: NMSettingSecretFlags
+ * 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));
+
+ /**
+ * NMSetting8021x:password-raw:
+ *
+ * Password used for EAP authentication methods, given as a byte array to
+ * allow passwords in other encodings than UTF-8 to be used. If both the
+ * #NMSetting8021x:password property and the #NMSetting8021x:password-raw
+ * property are specified, #NMSetting8021x:password is preferred.
+ **/
+ /* ---ifcfg-rh---
+ * property: password-raw
+ * variable: (none)
+ * description: The property is not handled by ifcfg-rh plugin.
+ * ---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));
+
+ /**
+ * NMSetting8021x:password-raw-flags:
+ *
+ * Flags indicating how to handle the #NMSetting8021x:password-raw property.
+ **/
+ /* ---ifcfg-rh---
+ * property: password-raw-flags
+ * variable: (none)
+ * 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));
+
+ /**
+ * NMSetting8021x:private-key:
+ *
+ * Contains the private key when the #NMSetting8021x:eap property is set to
+ * "tls".
+ *
+ * Key data is specified using a "scheme"; two are currently supported: blob
+ * and path. When using the blob scheme and private keys, this property
+ * should be set to the key's encrypted PEM encoded data. When using private
+ * keys with the path scheme, this property should be set to the full UTF-8
+ * encoded path of the key, prefixed with the string "file://" and ending
+ * with a terminating NUL byte. When using PKCS#<!-- -->12 format private
+ * keys and the blob scheme, this property should be set to the
+ * PKCS#<!-- -->12 data and the #NMSetting8021x:private-key-password
+ * property must be set to password used to decrypt the PKCS#<!-- -->12
+ * certificate and key. When using PKCS#<!-- -->12 files and the path
+ * scheme, this property should be set to the full UTF-8 encoded path of the
+ * key, prefixed with the string "file://" and and ending with a terminating
+ * NUL byte, and as with the blob scheme the "private-key-password" property
+ * must be set to the password used to decode the PKCS#<!-- -->12 private
+ * key and certificate.
+ *
+ * Setting this property directly is discouraged; use the
+ * nm_setting_802_1x_set_private_key() function instead.
+ *
+ * WARNING: #NMSetting8021x:private-key is not a "secret" property, and thus
+ * unencrypted private key data using the BLOB scheme may be readable by
+ * unprivileged users. Private keys should always be encrypted with a
+ * private key password to prevent unauthorized access to unencrypted
+ * private key data.
+ **/
+ /* ---ifcfg-rh---
+ * property: private-key
+ * variable: IEEE_8021X_PRIVATE_KEY(+)
+ * description: Private key for EAP-TLS.
+ * 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));
+
+ /**
+ * NMSetting8021x:private-key-password:
+ *
+ * The password used to decrypt the private key specified in the
+ * #NMSetting8021x:private-key property when the private key either uses the
+ * path scheme, or if the private key is a PKCS#<!-- -->12 format key. Setting this
+ * property directly is not generally necessary except when returning
+ * secrets to NetworkManager; it is generally set automatically when setting
+ * the private key by the nm_setting_802_1x_set_private_key() function.
+ **/
+ /* ---ifcfg-rh---
+ * property: private-key-password
+ * variable: IEEE_8021X_PRIVATE_KEY_PASSWORD(+)
+ * description: Password for IEEE_8021X_PRIVATE_KEY. It can also go to "key-"
+ * 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));
+
+ /**
+ * NMSetting8021x:private-key-password-flags:
+ *
+ * Flags indicating how to handle the #NMSetting8021x:private-key-password
+ * property.
+ **/
+ /* ---ifcfg-rh---
+ * property: private-key-password-flags
+ * variable: IEEE_8021X_PRIVATE_KEY_PASSWORD_FLAGS(+)
+ * format: NMSettingSecretFlags
+ * 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));
+
+ /**
+ * NMSetting8021x:phase2-private-key:
+ *
+ * Contains the "phase 2" inner private key when the
+ * #NMSetting8021x:phase2-auth or #NMSetting8021x:phase2-autheap property is
+ * set to "tls".
+ *
+ * Key data is specified using a "scheme"; two are currently supported: blob
+ * and path. When using the blob scheme and private keys, this property
+ * should be set to the key's encrypted PEM encoded data. When using private
+ * keys with the path scheme, this property should be set to the full UTF-8
+ * encoded path of the key, prefixed with the string "file://" and ending
+ * with a terminating NUL byte. When using PKCS#<!-- -->12 format private
+ * keys and the blob scheme, this property should be set to the
+ * PKCS#<!-- -->12 data and the #NMSetting8021x:phase2-private-key-password
+ * property must be set to password used to decrypt the PKCS#<!-- -->12
+ * certificate and key. When using PKCS#<!-- -->12 files and the path
+ * scheme, this property should be set to the full UTF-8 encoded path of the
+ * key, prefixed with the string "file://" and and ending with a terminating
+ * NUL byte, and as with the blob scheme the
+ * #NMSetting8021x:phase2-private-key-password property must be set to the
+ * password used to decode the PKCS#<!-- -->12 private key and certificate.
+ *
+ * Setting this property directly is discouraged; use the
+ * nm_setting_802_1x_set_phase2_private_key() function instead.
+ **/
+ /* ---ifcfg-rh---
+ * property: phase2-private-key
+ * variable: IEEE_8021X_INNER_PRIVATE_KEY(+)
+ * 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));
+
+ /**
+ * NMSetting8021x:phase2-private-key-password:
+ *
+ * The password used to decrypt the "phase 2" private key specified in the
+ * #NMSetting8021x:phase2-private-key property when the private key either
+ * uses the path scheme, or is a PKCS#<!-- -->12 format key. Setting this
+ * property directly is not generally necessary except when returning
+ * secrets to NetworkManager; it is generally set automatically when setting
+ * the private key by the nm_setting_802_1x_set_phase2_private_key()
+ * function.
+ **/
+ /* ---ifcfg-rh---
+ * property: phase2-private-key-password
+ * variable: IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD(+)
+ * description: Password for IEEE_8021X_INNER_PRIVATE_KEY. It can also go to "key-"
+ * 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));
+
+ /**
+ * NMSetting8021x:phase2-private-key-password-flags:
+ *
+ * Flags indicating how to handle the
+ * #NMSetting8021x:phase2-private-key-password property.
+ **/
+ /* ---ifcfg-rh---
+ * property: phase2-private-key-password-flags
+ * variable: IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD_FLAGS(+)
+ * format: NMSettingSecretFlags
+ * 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));
+
+ /**
+ * NMSetting8021x:pin:
+ *
+ * PIN used for EAP authentication methods.
+ **/
+ /* ---ifcfg-rh---
+ * property: pin
+ * variable: (none)
+ * 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));
+
+ /**
+ * NMSetting8021x:pin-flags:
+ *
+ * Flags indicating how to handle the #NMSetting8021x:pin property.
+ **/
+ /* ---ifcfg-rh---
+ * property: pin-flags
+ * variable: (none)
+ * 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));
+
+ /**
+ * NMSetting8021x:system-ca-certs:
+ *
+ * When %TRUE, overrides the #NMSetting8021x:ca-path and
+ * #NMSetting8021x:phase2-ca-path properties using the system CA directory
+ * specified at configure time with the --system-ca-path switch. The
+ * certificates in this directory are added to the verification chain in
+ * addition to any certificates specified by the #NMSetting8021x:ca-cert and
+ * #NMSetting8021x:phase2-ca-cert properties.
+ **/
+ /* ---ifcfg-rh---
+ * property: system-ca-certs
+ * variable: (none)
+ * 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));
+}
diff --git a/libnm-core/nm-setting-8021x.h b/libnm-core/nm-setting-8021x.h
new file mode 100644
index 000000000..43885daaa
--- /dev/null
+++ b/libnm-core/nm-setting-8021x.h
@@ -0,0 +1,278 @@
+/* -*- 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 2007 - 2014 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#ifndef __NM_SETTING_8021X_H__
+#define __NM_SETTING_8021X_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
+
+/**
+ * NMSetting8021xCKFormat:
+ * @NM_SETTING_802_1X_CK_FORMAT_UNKNOWN: unknown file format
+ * @NM_SETTING_802_1X_CK_FORMAT_X509: file contains an X.509 format certificate
+ * @NM_SETTING_802_1X_CK_FORMAT_RAW_KEY: file contains an old-style OpenSSL PEM
+ * or DER private key
+ * @NM_SETTING_802_1X_CK_FORMAT_PKCS12: file contains a PKCS#<!-- -->12 certificate
+ * and private key
+ *
+ * #NMSetting8021xCKFormat values indicate the general type of a certificate
+ * or private key
+ */
+typedef enum { /*< underscore_name=nm_setting_802_1x_ck_format >*/
+ NM_SETTING_802_1X_CK_FORMAT_UNKNOWN = 0,
+ NM_SETTING_802_1X_CK_FORMAT_X509,
+ NM_SETTING_802_1X_CK_FORMAT_RAW_KEY,
+ NM_SETTING_802_1X_CK_FORMAT_PKCS12
+} NMSetting8021xCKFormat;
+
+/**
+ * NMSetting8021xCKScheme:
+ * @NM_SETTING_802_1X_CK_SCHEME_UNKNOWN: unknown certificate or private key
+ * scheme
+ * @NM_SETTING_802_1X_CK_SCHEME_BLOB: certificate or key is stored as the raw
+ * item data
+ * @NM_SETTING_802_1X_CK_SCHEME_PATH: certificate or key is stored as a path
+ * to a file containing the certificate or key data
+ *
+ * #NMSetting8021xCKScheme values indicate how a certificate or private key is
+ * stored in the setting properties, either as a blob of the item's data, or as
+ * a path to a certificate or private key file on the filesystem
+ */
+typedef enum { /*< underscore_name=nm_setting_802_1x_ck_scheme >*/
+ NM_SETTING_802_1X_CK_SCHEME_UNKNOWN = 0,
+ NM_SETTING_802_1X_CK_SCHEME_BLOB,
+ NM_SETTING_802_1X_CK_SCHEME_PATH
+} NMSetting8021xCKScheme;
+
+
+#define NM_TYPE_SETTING_802_1X (nm_setting_802_1x_get_type ())
+#define NM_SETTING_802_1X(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_802_1X, NMSetting8021x))
+#define NM_SETTING_802_1X_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_802_1X, NMSetting8021xClass))
+#define NM_IS_SETTING_802_1X(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_802_1X))
+#define NM_IS_SETTING_802_1X_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_802_1X))
+#define NM_SETTING_802_1X_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_802_1X, NMSetting8021xClass))
+
+#define NM_SETTING_802_1X_SETTING_NAME "802-1x"
+
+#define NM_SETTING_802_1X_EAP "eap"
+#define NM_SETTING_802_1X_IDENTITY "identity"
+#define NM_SETTING_802_1X_ANONYMOUS_IDENTITY "anonymous-identity"
+#define NM_SETTING_802_1X_PAC_FILE "pac-file"
+#define NM_SETTING_802_1X_CA_CERT "ca-cert"
+#define NM_SETTING_802_1X_CA_PATH "ca-path"
+#define NM_SETTING_802_1X_SUBJECT_MATCH "subject-match"
+#define NM_SETTING_802_1X_ALTSUBJECT_MATCHES "altsubject-matches"
+#define NM_SETTING_802_1X_CLIENT_CERT "client-cert"
+#define NM_SETTING_802_1X_PHASE1_PEAPVER "phase1-peapver"
+#define NM_SETTING_802_1X_PHASE1_PEAPLABEL "phase1-peaplabel"
+#define NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING "phase1-fast-provisioning"
+#define NM_SETTING_802_1X_PHASE2_AUTH "phase2-auth"
+#define NM_SETTING_802_1X_PHASE2_AUTHEAP "phase2-autheap"
+#define NM_SETTING_802_1X_PHASE2_CA_CERT "phase2-ca-cert"
+#define NM_SETTING_802_1X_PHASE2_CA_PATH "phase2-ca-path"
+#define NM_SETTING_802_1X_PHASE2_SUBJECT_MATCH "phase2-subject-match"
+#define NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES "phase2-altsubject-matches"
+#define NM_SETTING_802_1X_PHASE2_CLIENT_CERT "phase2-client-cert"
+#define NM_SETTING_802_1X_PASSWORD "password"
+#define NM_SETTING_802_1X_PASSWORD_FLAGS "password-flags"
+#define NM_SETTING_802_1X_PASSWORD_RAW "password-raw"
+#define NM_SETTING_802_1X_PASSWORD_RAW_FLAGS "password-raw-flags"
+#define NM_SETTING_802_1X_PRIVATE_KEY "private-key"
+#define NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD "private-key-password"
+#define NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS "private-key-password-flags"
+#define NM_SETTING_802_1X_PHASE2_PRIVATE_KEY "phase2-private-key"
+#define NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD "phase2-private-key-password"
+#define NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS "phase2-private-key-password-flags"
+#define NM_SETTING_802_1X_PIN "pin"
+#define NM_SETTING_802_1X_PIN_FLAGS "pin-flags"
+#define NM_SETTING_802_1X_SYSTEM_CA_CERTS "system-ca-certs"
+
+/* PRIVATE KEY NOTE: when setting PKCS#12 private keys directly via properties
+ * using the "blob" scheme, the data must be passed in PKCS#12 binary format.
+ * In this case, the appropriate "client-cert" (or "phase2-client-cert")
+ * property of the NMSetting8021x object must also contain the exact same
+ * PKCS#12 binary data that the private key does. This is because the
+ * PKCS#12 file contains both the private key and client certificate, so both
+ * properties need to be set to the same thing. When using the "path" scheme,
+ * just set both the private-key and client-cert properties to the same path.
+ *
+ * When setting OpenSSL-derived "traditional" format (ie S/MIME style, not
+ * PKCS#8) RSA and DSA keys directly via properties with the "blob" scheme, they
+ * should be passed to NetworkManager in PEM format with the "DEK-Info" and
+ * "Proc-Type" tags intact. Decrypted private keys should not be used as this
+ * is insecure and could allow unprivileged users to access the decrypted
+ * private key data.
+ *
+ * When using the "path" scheme, just set the private-key and client-cert
+ * properties to the paths to their respective objects.
+ */
+
+struct _NMSetting8021x {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSetting8021xClass;
+
+GType nm_setting_802_1x_get_type (void);
+
+NMSetting *nm_setting_802_1x_new (void);
+
+guint32 nm_setting_802_1x_get_num_eap_methods (NMSetting8021x *setting);
+const char * nm_setting_802_1x_get_eap_method (NMSetting8021x *setting, guint32 i);
+gboolean nm_setting_802_1x_add_eap_method (NMSetting8021x *setting, const char *eap);
+void nm_setting_802_1x_remove_eap_method (NMSetting8021x *setting, guint32 i);
+gboolean nm_setting_802_1x_remove_eap_method_by_value (NMSetting8021x *setting, const char *eap);
+void nm_setting_802_1x_clear_eap_methods (NMSetting8021x *setting);
+
+const char * nm_setting_802_1x_get_identity (NMSetting8021x *setting);
+
+const char * nm_setting_802_1x_get_anonymous_identity (NMSetting8021x *setting);
+
+const char * nm_setting_802_1x_get_pac_file (NMSetting8021x *setting);
+
+gboolean nm_setting_802_1x_get_system_ca_certs (NMSetting8021x *setting);
+const char * nm_setting_802_1x_get_ca_path (NMSetting8021x *setting);
+const char * nm_setting_802_1x_get_phase2_ca_path (NMSetting8021x *setting);
+
+NMSetting8021xCKScheme nm_setting_802_1x_get_ca_cert_scheme (NMSetting8021x *setting);
+GBytes * nm_setting_802_1x_get_ca_cert_blob (NMSetting8021x *setting);
+const char * nm_setting_802_1x_get_ca_cert_path (NMSetting8021x *setting);
+gboolean nm_setting_802_1x_set_ca_cert (NMSetting8021x *setting,
+ const char *cert_path,
+ NMSetting8021xCKScheme scheme,
+ NMSetting8021xCKFormat *out_format,
+ GError **error);
+
+const char * nm_setting_802_1x_get_subject_match (NMSetting8021x *setting);
+
+guint32 nm_setting_802_1x_get_num_altsubject_matches (NMSetting8021x *setting);
+const char * nm_setting_802_1x_get_altsubject_match (NMSetting8021x *setting,
+ guint32 i);
+gboolean nm_setting_802_1x_add_altsubject_match (NMSetting8021x *setting,
+ const char *altsubject_match);
+void nm_setting_802_1x_remove_altsubject_match (NMSetting8021x *setting,
+ guint32 i);
+gboolean nm_setting_802_1x_remove_altsubject_match_by_value (NMSetting8021x *setting,
+ const char *altsubject_match);
+void nm_setting_802_1x_clear_altsubject_matches (NMSetting8021x *setting);
+
+NMSetting8021xCKScheme nm_setting_802_1x_get_client_cert_scheme (NMSetting8021x *setting);
+GBytes * nm_setting_802_1x_get_client_cert_blob (NMSetting8021x *setting);
+const char * nm_setting_802_1x_get_client_cert_path (NMSetting8021x *setting);
+gboolean nm_setting_802_1x_set_client_cert (NMSetting8021x *setting,
+ const char *cert_path,
+ NMSetting8021xCKScheme scheme,
+ NMSetting8021xCKFormat *out_format,
+ GError **error);
+
+const char * nm_setting_802_1x_get_phase1_peapver (NMSetting8021x *setting);
+
+const char * nm_setting_802_1x_get_phase1_peaplabel (NMSetting8021x *setting);
+
+const char * nm_setting_802_1x_get_phase1_fast_provisioning (NMSetting8021x *setting);
+
+const char * nm_setting_802_1x_get_phase2_auth (NMSetting8021x *setting);
+
+const char * nm_setting_802_1x_get_phase2_autheap (NMSetting8021x *setting);
+
+NMSetting8021xCKScheme nm_setting_802_1x_get_phase2_ca_cert_scheme (NMSetting8021x *setting);
+GBytes * nm_setting_802_1x_get_phase2_ca_cert_blob (NMSetting8021x *setting);
+const char * nm_setting_802_1x_get_phase2_ca_cert_path (NMSetting8021x *setting);
+gboolean nm_setting_802_1x_set_phase2_ca_cert (NMSetting8021x *setting,
+ const char *cert_path,
+ NMSetting8021xCKScheme scheme,
+ NMSetting8021xCKFormat *out_format,
+ GError **error);
+
+const char * nm_setting_802_1x_get_phase2_subject_match (NMSetting8021x *setting);
+
+guint32 nm_setting_802_1x_get_num_phase2_altsubject_matches (NMSetting8021x *setting);
+const char * nm_setting_802_1x_get_phase2_altsubject_match (NMSetting8021x *setting,
+ guint32 i);
+gboolean nm_setting_802_1x_add_phase2_altsubject_match (NMSetting8021x *setting,
+ const char *phase2_altsubject_match);
+void nm_setting_802_1x_remove_phase2_altsubject_match (NMSetting8021x *setting,
+ guint32 i);
+gboolean nm_setting_802_1x_remove_phase2_altsubject_match_by_value (NMSetting8021x *setting,
+ const char *phase2_altsubject_match);
+void nm_setting_802_1x_clear_phase2_altsubject_matches (NMSetting8021x *setting);
+
+NMSetting8021xCKScheme nm_setting_802_1x_get_phase2_client_cert_scheme (NMSetting8021x *setting);
+GBytes * nm_setting_802_1x_get_phase2_client_cert_blob (NMSetting8021x *setting);
+const char * nm_setting_802_1x_get_phase2_client_cert_path (NMSetting8021x *setting);
+gboolean nm_setting_802_1x_set_phase2_client_cert (NMSetting8021x *setting,
+ const char *cert_path,
+ NMSetting8021xCKScheme scheme,
+ NMSetting8021xCKFormat *out_format,
+ GError **error);
+
+const char * nm_setting_802_1x_get_password (NMSetting8021x *setting);
+NMSettingSecretFlags nm_setting_802_1x_get_password_flags (NMSetting8021x *setting);
+GBytes * nm_setting_802_1x_get_password_raw (NMSetting8021x *setting);
+NMSettingSecretFlags nm_setting_802_1x_get_password_raw_flags (NMSetting8021x *setting);
+
+const char * nm_setting_802_1x_get_pin (NMSetting8021x *setting);
+NMSettingSecretFlags nm_setting_802_1x_get_pin_flags (NMSetting8021x *setting);
+
+NMSetting8021xCKScheme nm_setting_802_1x_get_private_key_scheme (NMSetting8021x *setting);
+GBytes * nm_setting_802_1x_get_private_key_blob (NMSetting8021x *setting);
+const char * nm_setting_802_1x_get_private_key_path (NMSetting8021x *setting);
+gboolean nm_setting_802_1x_set_private_key (NMSetting8021x *setting,
+ const char *key_path,
+ const char *password,
+ NMSetting8021xCKScheme scheme,
+ NMSetting8021xCKFormat *out_format,
+ GError **error);
+const char * nm_setting_802_1x_get_private_key_password (NMSetting8021x *setting);
+NMSettingSecretFlags nm_setting_802_1x_get_private_key_password_flags (NMSetting8021x *setting);
+
+NMSetting8021xCKFormat nm_setting_802_1x_get_private_key_format (NMSetting8021x *setting);
+
+NMSetting8021xCKScheme nm_setting_802_1x_get_phase2_private_key_scheme (NMSetting8021x *setting);
+GBytes * nm_setting_802_1x_get_phase2_private_key_blob (NMSetting8021x *setting);
+const char * nm_setting_802_1x_get_phase2_private_key_path (NMSetting8021x *setting);
+gboolean nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *setting,
+ const char *key_path,
+ const char *password,
+ NMSetting8021xCKScheme scheme,
+ NMSetting8021xCKFormat *out_format,
+ GError **error);
+const char * nm_setting_802_1x_get_phase2_private_key_password (NMSetting8021x *setting);
+NMSettingSecretFlags nm_setting_802_1x_get_phase2_private_key_password_flags (NMSetting8021x *setting);
+
+NMSetting8021xCKFormat nm_setting_802_1x_get_phase2_private_key_format (NMSetting8021x *setting);
+
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_8021X_H__ */
diff --git a/libnm-core/nm-setting-adsl.c b/libnm-core/nm-setting-adsl.c
new file mode 100644
index 000000000..00bcef543
--- /dev/null
+++ b/libnm-core/nm-setting-adsl.c
@@ -0,0 +1,448 @@
+/* -*- 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 2011 - 2013 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-adsl.h"
+#include "nm-setting-ppp.h"
+#include "nm-setting-private.h"
+#include "nm-utils.h"
+#include "nm-core-enum-types.h"
+
+/**
+ * SECTION:nm-setting-adsl
+ * @short_description: Describes ADSL-based properties
+ *
+ * The #NMSettingAdsl object is a #NMSetting subclass that describes
+ * properties of ADSL connections.
+ */
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingAdsl, nm_setting_adsl, NM_TYPE_SETTING,
+ _nm_register_setting (ADSL, 1))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_ADSL)
+
+#define NM_SETTING_ADSL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_ADSL, NMSettingAdslPrivate))
+
+typedef struct {
+ char * username;
+ char * password;
+ NMSettingSecretFlags password_flags;
+ char * protocol;
+ char * encapsulation;
+ guint32 vpi;
+ guint32 vci;
+} NMSettingAdslPrivate;
+
+enum {
+ PROP_0,
+ PROP_USERNAME,
+ PROP_PASSWORD,
+ PROP_PASSWORD_FLAGS,
+ PROP_PROTOCOL,
+ PROP_ENCAPSULATION,
+ PROP_VPI,
+ PROP_VCI,
+
+ LAST_PROP
+};
+
+/**
+ * nm_setting_adsl_new:
+ *
+ * Creates a new #NMSettingAdsl object with default values.
+ *
+ * Returns: the new empty #NMSettingAdsl object
+ **/
+NMSetting *
+nm_setting_adsl_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_ADSL, NULL);
+}
+
+/**
+ * nm_setting_adsl_get_username:
+ * @setting: the #NMSettingAdsl
+ *
+ * Returns: the #NMSettingAdsl:username property of the setting
+ **/
+const char *
+nm_setting_adsl_get_username (NMSettingAdsl *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_ADSL (setting), NULL);
+
+ return NM_SETTING_ADSL_GET_PRIVATE (setting)->username;
+}
+
+/**
+ * nm_setting_adsl_get_password:
+ * @setting: the #NMSettingAdsl
+ *
+ * Returns: the #NMSettingAdsl:password property of the setting
+ **/
+const char *
+nm_setting_adsl_get_password (NMSettingAdsl *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_ADSL (setting), NULL);
+
+ return NM_SETTING_ADSL_GET_PRIVATE (setting)->password;
+}
+
+/**
+ * nm_setting_adsl_get_password_flags:
+ * @setting: the #NMSettingAdsl
+ *
+ * Returns: the #NMSettingSecretFlags pertaining to the #NMSettingAdsl:password
+ **/
+NMSettingSecretFlags
+nm_setting_adsl_get_password_flags (NMSettingAdsl *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_ADSL (setting), NM_SETTING_SECRET_FLAG_NONE);
+
+ return NM_SETTING_ADSL_GET_PRIVATE (setting)->password_flags;
+}
+
+/**
+ * nm_setting_adsl_get_protocol:
+ * @setting: the #NMSettingAdsl
+ *
+ * Returns: the #NMSettingAdsl:protocol property of the setting
+ **/
+const char *
+nm_setting_adsl_get_protocol (NMSettingAdsl *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_ADSL (setting), NULL);
+
+ return NM_SETTING_ADSL_GET_PRIVATE (setting)->protocol;
+}
+
+/**
+ * nm_setting_adsl_get_encapsulation:
+ * @setting: the #NMSettingAdsl
+ *
+ * Returns: the #NMSettingAdsl:encapsulation property of the setting
+ **/
+const char *
+nm_setting_adsl_get_encapsulation (NMSettingAdsl *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_ADSL (setting), NULL);
+
+ return NM_SETTING_ADSL_GET_PRIVATE (setting)->encapsulation;
+}
+
+/**
+ * nm_setting_adsl_get_vpi:
+ * @setting: the #NMSettingAdsl
+ *
+ * Returns: the #NMSettingAdsl:vpi property of the setting
+ **/
+guint32
+nm_setting_adsl_get_vpi (NMSettingAdsl *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_ADSL (setting), 0);
+
+ return NM_SETTING_ADSL_GET_PRIVATE (setting)->vpi;
+}
+
+/**
+ * nm_setting_adsl_get_vci:
+ * @setting: the #NMSettingAdsl
+ *
+ * Returns: the #NMSettingAdsl:vci property of the setting
+ **/
+guint32
+nm_setting_adsl_get_vci (NMSettingAdsl *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_ADSL (setting), 0);
+
+ return NM_SETTING_ADSL_GET_PRIVATE (setting)->vci;
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ NMSettingAdslPrivate *priv = NM_SETTING_ADSL_GET_PRIVATE (setting);
+
+ if (!priv->username) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_ADSL_SETTING_NAME, NM_SETTING_ADSL_USERNAME);
+ return FALSE;
+ } else if (!strlen (priv->username)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_ADSL_SETTING_NAME, NM_SETTING_ADSL_USERNAME);
+ return FALSE;
+ }
+
+ if (priv->password && !strlen (priv->password)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_ADSL_SETTING_NAME, NM_SETTING_ADSL_PASSWORD);
+ return FALSE;
+ }
+
+ if ( !priv->protocol
+ || ( strcmp (priv->protocol, NM_SETTING_ADSL_PROTOCOL_PPPOA)
+ && strcmp (priv->protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE)
+ && strcmp (priv->protocol, NM_SETTING_ADSL_PROTOCOL_IPOATM))){
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid value for the property"),
+ priv->protocol ? priv->protocol : "(null)");
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_ADSL_SETTING_NAME, NM_SETTING_ADSL_PROTOCOL);
+ return FALSE;
+ }
+
+ if ( priv->encapsulation
+ && ( strcmp (priv->encapsulation, NM_SETTING_ADSL_ENCAPSULATION_VCMUX)
+ && strcmp (priv->encapsulation, NM_SETTING_ADSL_ENCAPSULATION_LLC) )) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid value for the property"),
+ priv->encapsulation);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_ADSL_SETTING_NAME, NM_SETTING_ADSL_ENCAPSULATION);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static GPtrArray *
+need_secrets (NMSetting *setting)
+{
+ NMSettingAdslPrivate *priv = NM_SETTING_ADSL_GET_PRIVATE (setting);
+ GPtrArray *secrets = NULL;
+
+ if (priv->password)
+ return NULL;
+
+ if (!(priv->password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) {
+ secrets = g_ptr_array_sized_new (1);
+ g_ptr_array_add (secrets, NM_SETTING_ADSL_PASSWORD);
+ }
+
+ return secrets;
+}
+
+static void
+nm_setting_adsl_init (NMSettingAdsl *setting)
+{
+}
+
+static void
+finalize (GObject *object)
+{
+ NMSettingAdslPrivate *priv = NM_SETTING_ADSL_GET_PRIVATE (object);
+
+ g_free (priv->username);
+ g_free (priv->password);
+ g_free (priv->protocol);
+ g_free (priv->encapsulation);
+
+ G_OBJECT_CLASS (nm_setting_adsl_parent_class)->finalize (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingAdslPrivate *priv = NM_SETTING_ADSL_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_USERNAME:
+ g_free (priv->username);
+ priv->username = g_value_dup_string (value);
+ break;
+ case PROP_PASSWORD:
+ g_free (priv->password);
+ priv->password = g_value_dup_string (value);
+ break;
+ case PROP_PASSWORD_FLAGS:
+ priv->password_flags = g_value_get_flags (value);
+ break;
+ case PROP_PROTOCOL:
+ g_free (priv->protocol);
+ priv->protocol = g_ascii_strdown (g_value_get_string (value), -1);
+ break;
+ case PROP_ENCAPSULATION:
+ g_free (priv->encapsulation);
+ priv->encapsulation = g_ascii_strdown (g_value_get_string (value), -1);
+ break;
+ case PROP_VPI:
+ priv->vpi = g_value_get_uint (value);
+ break;
+ case PROP_VCI:
+ priv->vci = g_value_get_uint (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)
+{
+ NMSettingAdsl *setting = NM_SETTING_ADSL (object);
+
+ switch (prop_id) {
+ case PROP_USERNAME:
+ g_value_set_string (value, nm_setting_adsl_get_username (setting));
+ break;
+ case PROP_PASSWORD:
+ g_value_set_string (value, nm_setting_adsl_get_password (setting));
+ break;
+ case PROP_PASSWORD_FLAGS:
+ g_value_set_flags (value, nm_setting_adsl_get_password_flags (setting));
+ break;
+ case PROP_PROTOCOL:
+ g_value_set_string (value, nm_setting_adsl_get_protocol (setting));
+ break;
+ case PROP_ENCAPSULATION:
+ g_value_set_string (value, nm_setting_adsl_get_encapsulation (setting));
+ break;
+ case PROP_VPI:
+ g_value_set_uint (value, nm_setting_adsl_get_vpi (setting));
+ break;
+ case PROP_VCI:
+ g_value_set_uint (value, nm_setting_adsl_get_vci (setting));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_setting_adsl_class_init (NMSettingAdslClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+ NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+ g_type_class_add_private (setting_class, 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->need_secrets = need_secrets;
+
+ /* Properties */
+
+ /**
+ * NMSettingAdsl:username:
+ *
+ * Username used to authenticate with the ADSL service.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_USERNAME,
+ g_param_spec_string (NM_SETTING_ADSL_USERNAME, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingAdsl:password:
+ *
+ * Password used to authenticate with the ADSL service.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_PASSWORD,
+ g_param_spec_string (NM_SETTING_ADSL_PASSWORD, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_SECRET |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingAdsl:password-flags:
+ *
+ * Flags indicating how to handle the #NMSettingAdsl:password property.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_PASSWORD_FLAGS,
+ g_param_spec_flags (NM_SETTING_ADSL_PASSWORD_FLAGS, "", "",
+ NM_TYPE_SETTING_SECRET_FLAGS,
+ NM_SETTING_SECRET_FLAG_NONE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingAdsl:protocol:
+ *
+ * ADSL connection protocol. Can be "pppoa", "pppoe" or "ipoatm".
+ **/
+ g_object_class_install_property
+ (object_class, PROP_PROTOCOL,
+ g_param_spec_string (NM_SETTING_ADSL_PROTOCOL, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingAdsl:encapsulation:
+ *
+ * Encapsulation of ADSL connection. Can be "vcmux" or "llc".
+ **/
+ g_object_class_install_property
+ (object_class, PROP_ENCAPSULATION,
+ g_param_spec_string (NM_SETTING_ADSL_ENCAPSULATION, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingAdsl:vpi:
+ *
+ * VPI of ADSL connection
+ **/
+ g_object_class_install_property
+ (object_class, PROP_VPI,
+ g_param_spec_uint (NM_SETTING_ADSL_VPI, "", "",
+ 0, 65536, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingAdsl:vci:
+ *
+ * VCI of ADSL connection
+ **/
+ g_object_class_install_property
+ (object_class, PROP_VCI,
+ g_param_spec_uint (NM_SETTING_ADSL_VCI, "", "",
+ 0, 65536, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+}
diff --git a/libnm-core/nm-setting-adsl.h b/libnm-core/nm-setting-adsl.h
new file mode 100644
index 000000000..2b44d6868
--- /dev/null
+++ b/libnm-core/nm-setting-adsl.h
@@ -0,0 +1,81 @@
+/* -*- 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 2007 - 2008 Red Hat, Inc.
+ */
+
+#ifndef __NM_SETTING_ADSL_H__
+#define __NM_SETTING_ADSL_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_ADSL (nm_setting_adsl_get_type ())
+#define NM_SETTING_ADSL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_ADSL, NMSettingAdsl))
+#define NM_SETTING_ADSL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_ADSL, NMSettingAdslClass))
+#define NM_IS_SETTING_ADSL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_ADSL))
+#define NM_IS_SETTING_ADSL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_ADSL))
+#define NM_SETTING_ADSL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_ADSL, NMSettingAdslClass))
+
+#define NM_SETTING_ADSL_SETTING_NAME "adsl"
+
+#define NM_SETTING_ADSL_USERNAME "username"
+#define NM_SETTING_ADSL_PASSWORD "password"
+#define NM_SETTING_ADSL_PASSWORD_FLAGS "password-flags"
+#define NM_SETTING_ADSL_PROTOCOL "protocol"
+#define NM_SETTING_ADSL_ENCAPSULATION "encapsulation"
+#define NM_SETTING_ADSL_VPI "vpi"
+#define NM_SETTING_ADSL_VCI "vci"
+
+#define NM_SETTING_ADSL_PROTOCOL_PPPOA "pppoa"
+#define NM_SETTING_ADSL_PROTOCOL_PPPOE "pppoe"
+#define NM_SETTING_ADSL_PROTOCOL_IPOATM "ipoatm"
+
+#define NM_SETTING_ADSL_ENCAPSULATION_VCMUX "vcmux"
+#define NM_SETTING_ADSL_ENCAPSULATION_LLC "llc"
+
+struct _NMSettingAdsl {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingAdslClass;
+
+GType nm_setting_adsl_get_type (void);
+
+NMSetting *nm_setting_adsl_new (void);
+const char *nm_setting_adsl_get_username (NMSettingAdsl *setting);
+const char *nm_setting_adsl_get_password (NMSettingAdsl *setting);
+const char *nm_setting_adsl_get_protocol (NMSettingAdsl *setting);
+const char *nm_setting_adsl_get_encapsulation (NMSettingAdsl *setting);
+guint32 nm_setting_adsl_get_vpi (NMSettingAdsl *setting);
+guint32 nm_setting_adsl_get_vci (NMSettingAdsl *setting);
+NMSettingSecretFlags nm_setting_adsl_get_password_flags (NMSettingAdsl *setting);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_ADSL_H__ */
diff --git a/libnm-core/nm-setting-bluetooth.c b/libnm-core/nm-setting-bluetooth.c
new file mode 100644
index 000000000..41a0b4c2f
--- /dev/null
+++ b/libnm-core/nm-setting-bluetooth.c
@@ -0,0 +1,285 @@
+/* -*- 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 2007 - 2013 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <net/ethernet.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-bluetooth.h"
+#include "nm-setting-cdma.h"
+#include "nm-setting-gsm.h"
+#include "nm-setting-private.h"
+#include "nm-utils.h"
+#include "nm-utils-private.h"
+
+/**
+ * SECTION:nm-setting-bluetooth
+ * @short_description: Describes Bluetooth connection properties
+ *
+ * The #NMSettingBluetooth object is a #NMSetting subclass that describes
+ * properties necessary for connection to devices that provide network
+ * connections via the Bluetooth Dial-Up Networking (DUN) and Network Access
+ * Point (NAP) profiles.
+ **/
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingBluetooth, nm_setting_bluetooth, NM_TYPE_SETTING,
+ _nm_register_setting (BLUETOOTH, 1))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_BLUETOOTH)
+
+#define NM_SETTING_BLUETOOTH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BLUETOOTH, NMSettingBluetoothPrivate))
+
+typedef struct {
+ char *bdaddr;
+ char *type;
+} NMSettingBluetoothPrivate;
+
+enum {
+ PROP_0,
+ PROP_BDADDR,
+ PROP_TYPE,
+
+ LAST_PROP
+};
+
+/**
+ * nm_setting_bluetooth_new:
+ *
+ * Creates a new #NMSettingBluetooth object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingBluetooth object
+ **/
+NMSetting *nm_setting_bluetooth_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_BLUETOOTH, NULL);
+}
+
+/**
+ * nm_setting_bluetooth_get_connection_type:
+ * @setting: the #NMSettingBluetooth
+ *
+ * Returns the connection method for communicating with the remote device (i.e.
+ * either DUN to a DUN-capable device or PANU to a NAP-capable device).
+ *
+ * Returns: the type, either %NM_SETTING_BLUETOOTH_TYPE_PANU or
+ * %NM_SETTING_BLUETOOTH_TYPE_DUN
+ **/
+const char *
+nm_setting_bluetooth_get_connection_type (NMSettingBluetooth *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BLUETOOTH (setting), NULL);
+
+ return NM_SETTING_BLUETOOTH_GET_PRIVATE (setting)->type;
+}
+
+/**
+ * nm_setting_bluetooth_get_bdaddr:
+ * @setting: the #NMSettingBluetooth
+ *
+ * Gets the Bluetooth address of the remote device which this setting
+ * describes a connection to.
+ *
+ * Returns: the Bluetooth address
+ **/
+const char *
+nm_setting_bluetooth_get_bdaddr (NMSettingBluetooth *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BLUETOOTH (setting), NULL);
+
+ return NM_SETTING_BLUETOOTH_GET_PRIVATE (setting)->bdaddr;
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ NMSettingBluetoothPrivate *priv = NM_SETTING_BLUETOOTH_GET_PRIVATE (setting);
+
+ if (!priv->bdaddr) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME, NM_SETTING_BLUETOOTH_BDADDR);
+ return FALSE;
+ }
+
+ if (!nm_utils_hwaddr_valid (priv->bdaddr, ETH_ALEN)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME, NM_SETTING_BLUETOOTH_BDADDR);
+ return FALSE;
+ }
+
+ if (!priv->type) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME, NM_SETTING_BLUETOOTH_TYPE);
+ return FALSE;
+ } else if (!g_str_equal (priv->type, NM_SETTING_BLUETOOTH_TYPE_DUN) &&
+ !g_str_equal (priv->type, NM_SETTING_BLUETOOTH_TYPE_PANU)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid value for the property"),
+ priv->type);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME, NM_SETTING_BLUETOOTH_TYPE);
+ return FALSE;
+ }
+
+ /* Make sure the corresponding 'type' setting is present */
+ if ( connection
+ && !strcmp (priv->type, NM_SETTING_BLUETOOTH_TYPE_DUN)) {
+ gboolean gsm = FALSE, cdma = FALSE;
+
+ gsm = !!nm_connection_get_setting_gsm (connection);
+ cdma = !!nm_connection_get_setting_cdma (connection);
+
+ if (!gsm && !cdma) {
+ /* We can't return MISSING_SETTING here, because we don't know
+ * whether to prefix the message with NM_SETTING_GSM_SETTING_NAME or
+ * NM_SETTING_CDMA_SETTING_NAME.
+ */
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_SETTING,
+ _("'%s' connection requires '%s' or '%s' setting"),
+ NM_SETTING_BLUETOOTH_TYPE_DUN,
+ NM_SETTING_GSM_SETTING_NAME, NM_SETTING_CDMA_SETTING_NAME);
+ g_prefix_error (error, "%s: ", NM_SETTING_BLUETOOTH_SETTING_NAME);
+ return FALSE;
+ }
+ }
+ /* PANU doesn't need a 'type' setting since no further configuration
+ * is required at the interface level.
+ */
+
+ return TRUE;
+}
+
+static void
+nm_setting_bluetooth_init (NMSettingBluetooth *setting)
+{
+}
+
+static void
+finalize (GObject *object)
+{
+ NMSettingBluetoothPrivate *priv = NM_SETTING_BLUETOOTH_GET_PRIVATE (object);
+
+ g_free (priv->bdaddr);
+ g_free (priv->type);
+
+ G_OBJECT_CLASS (nm_setting_bluetooth_parent_class)->finalize (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingBluetoothPrivate *priv = NM_SETTING_BLUETOOTH_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_BDADDR:
+ g_free (priv->bdaddr);
+ priv->bdaddr = g_value_dup_string (value);
+ break;
+ case PROP_TYPE:
+ g_free (priv->type);
+ priv->type = 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)
+{
+ NMSettingBluetooth *setting = NM_SETTING_BLUETOOTH (object);
+
+ switch (prop_id) {
+ case PROP_BDADDR:
+ g_value_set_string (value, nm_setting_bluetooth_get_bdaddr (setting));
+ break;
+ case PROP_TYPE:
+ g_value_set_string (value, nm_setting_bluetooth_get_connection_type (setting));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_setting_bluetooth_class_init (NMSettingBluetoothClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+ NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+ g_type_class_add_private (setting_class, 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 */
+
+ /**
+ * NMSettingBluetooth:bdaddr:
+ *
+ * The Bluetooth address of the device.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_BDADDR,
+ g_param_spec_string (NM_SETTING_BLUETOOTH_BDADDR, "", "",
+ NULL,
+ 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);
+
+ /**
+ * NMSettingBluetooth:type:
+ *
+ * Either "dun" for Dial-Up Networking connections or "panu" for Personal
+ * Area Networking connections to devices supporting the NAP profile.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_TYPE,
+ g_param_spec_string (NM_SETTING_BLUETOOTH_TYPE, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+}
diff --git a/libnm-core/nm-setting-bluetooth.h b/libnm-core/nm-setting-bluetooth.h
new file mode 100644
index 000000000..6bb5ce80a
--- /dev/null
+++ b/libnm-core/nm-setting-bluetooth.h
@@ -0,0 +1,81 @@
+/* -*- 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 2007 - 2009 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#ifndef __NM_SETTING_BLUETOOTH_H__
+#define __NM_SETTING_BLUETOOTH_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_BLUETOOTH (nm_setting_bluetooth_get_type ())
+#define NM_SETTING_BLUETOOTH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_BLUETOOTH, NMSettingBluetooth))
+#define NM_SETTING_BLUETOOTH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_BLUETOOTH, NMSettingBluetoothClass))
+#define NM_IS_SETTING_BLUETOOTH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_BLUETOOTH))
+#define NM_IS_SETTING_BLUETOOTH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_BLUETOOTH))
+#define NM_SETTING_BLUETOOTH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_BLUETOOTH, NMSettingBluetoothClass))
+
+#define NM_SETTING_BLUETOOTH_SETTING_NAME "bluetooth"
+
+#define NM_SETTING_BLUETOOTH_BDADDR "bdaddr"
+#define NM_SETTING_BLUETOOTH_TYPE "type"
+
+/**
+ * NM_SETTING_BLUETOOTH_TYPE_DUN:
+ *
+ * Connection type describing a connection to devices that support the Bluetooth
+ * DUN profile.
+ */
+#define NM_SETTING_BLUETOOTH_TYPE_DUN "dun"
+
+/**
+ * NM_SETTING_BLUETOOTH_TYPE_PANU:
+ *
+ * Connection type describing a connection to devices that support the Bluetooth
+ * NAP (Network Access Point) protocol, which accepts connections via PANU.
+ */
+#define NM_SETTING_BLUETOOTH_TYPE_PANU "panu"
+
+struct _NMSettingBluetooth {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingBluetoothClass;
+
+GType nm_setting_bluetooth_get_type (void);
+
+NMSetting * nm_setting_bluetooth_new (void);
+const char * nm_setting_bluetooth_get_bdaddr (NMSettingBluetooth *setting);
+const char * nm_setting_bluetooth_get_connection_type (NMSettingBluetooth *setting);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_BLUETOOTH_H__ */
diff --git a/libnm-core/nm-setting-bond.c b/libnm-core/nm-setting-bond.c
new file mode 100644
index 000000000..bb0531253
--- /dev/null
+++ b/libnm-core/nm-setting-bond.c
@@ -0,0 +1,760 @@
+/* -*- 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 2011 - 2013 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-bond.h"
+#include "nm-utils.h"
+#include "nm-utils-private.h"
+#include "nm-connection-private.h"
+#include "nm-setting-infiniband.h"
+
+/**
+ * SECTION:nm-setting-bond
+ * @short_description: Describes connection properties for bonds
+ *
+ * The #NMSettingBond object is a #NMSetting subclass that describes properties
+ * necessary for bond connections.
+ **/
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingBond, nm_setting_bond, NM_TYPE_SETTING,
+ _nm_register_setting (BOND, 1))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_BOND)
+
+#define NM_SETTING_BOND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BOND, NMSettingBondPrivate))
+
+typedef struct {
+ GHashTable *options;
+} NMSettingBondPrivate;
+
+enum {
+ PROP_0,
+ PROP_OPTIONS,
+ LAST_PROP
+};
+
+enum {
+ TYPE_INT,
+ TYPE_STR,
+ TYPE_BOTH,
+ TYPE_IP,
+ TYPE_IFNAME,
+};
+
+typedef struct {
+ const char *opt;
+ const char *val;
+ guint opt_type;
+ guint min;
+ guint max;
+ char *list[10];
+} BondDefault;
+
+static const BondDefault defaults[] = {
+ { NM_SETTING_BOND_OPTION_MODE, "balance-rr", TYPE_BOTH, 0, 6,
+ { "balance-rr", "active-backup", "balance-xor", "broadcast", "802.3ad", "balance-tlb", "balance-alb", NULL } },
+ { NM_SETTING_BOND_OPTION_MIIMON, "100", TYPE_INT, 0, G_MAXINT },
+ { NM_SETTING_BOND_OPTION_DOWNDELAY, "0", TYPE_INT, 0, G_MAXINT },
+ { NM_SETTING_BOND_OPTION_UPDELAY, "0", TYPE_INT, 0, G_MAXINT },
+ { NM_SETTING_BOND_OPTION_ARP_INTERVAL, "0", TYPE_INT, 0, G_MAXINT },
+ { NM_SETTING_BOND_OPTION_ARP_IP_TARGET, "", TYPE_IP },
+ { NM_SETTING_BOND_OPTION_ARP_VALIDATE, "0", TYPE_BOTH, 0, 3,
+ { "none", "active", "backup", "all", NULL } },
+ { NM_SETTING_BOND_OPTION_PRIMARY, "", TYPE_IFNAME },
+ { NM_SETTING_BOND_OPTION_PRIMARY_RESELECT, "0", TYPE_BOTH, 0, 2,
+ { "always", "better", "failure", NULL } },
+ { NM_SETTING_BOND_OPTION_FAIL_OVER_MAC, "0", TYPE_BOTH, 0, 2,
+ { "none", "active", "follow", NULL } },
+ { NM_SETTING_BOND_OPTION_USE_CARRIER, "1", TYPE_INT, 0, 1 },
+ { NM_SETTING_BOND_OPTION_AD_SELECT, "0", TYPE_BOTH, 0, 2,
+ { "stable", "bandwidth", "count", NULL } },
+ { NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY, "0", TYPE_BOTH, 0, 2,
+ { "layer2", "layer3+4", "layer2+3", NULL } },
+ { NM_SETTING_BOND_OPTION_RESEND_IGMP, "1", TYPE_INT, 0, 255 },
+ { NM_SETTING_BOND_OPTION_LACP_RATE, "0", TYPE_BOTH, 0, 1,
+ { "slow", "fast", NULL } },
+};
+
+/**
+ * nm_setting_bond_new:
+ *
+ * Creates a new #NMSettingBond object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingBond object
+ **/
+NMSetting *
+nm_setting_bond_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_BOND, NULL);
+}
+
+/**
+ * nm_setting_bond_get_num_options:
+ * @setting: the #NMSettingBond
+ *
+ * Returns the number of options that should be set for this bond when it
+ * is activated. This can be used to retrieve each option individually
+ * using nm_setting_bond_get_option().
+ *
+ * Returns: the number of bonding options
+ **/
+guint32
+nm_setting_bond_get_num_options (NMSettingBond *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BOND (setting), 0);
+
+ return g_hash_table_size (NM_SETTING_BOND_GET_PRIVATE (setting)->options);
+}
+
+/**
+ * nm_setting_bond_get_option:
+ * @setting: the #NMSettingBond
+ * @idx: index of the desired option, from 0 to
+ * nm_setting_bond_get_num_options() - 1
+ * @out_name: (out) (transfer none): on return, the name of the bonding option;
+ * this value is owned by the setting and should not be modified
+ * @out_value: (out) (transfer none): on return, the value of the name of the
+ * bonding option; this value is owned by the setting and should not be
+ * modified
+ *
+ * Given an index, return the value of the bonding option at that index. Indexes
+ * are *not* guaranteed to be static across modifications to options done by
+ * nm_setting_bond_add_option() and nm_setting_bond_remove_option(),
+ * and should not be used to refer to options except for short periods of time
+ * such as during option iteration.
+ *
+ * Returns: %TRUE on success if the index was valid and an option was found,
+ * %FALSE if the index was invalid (ie, greater than the number of options
+ * currently held by the setting)
+ **/
+gboolean
+nm_setting_bond_get_option (NMSettingBond *setting,
+ guint32 idx,
+ const char **out_name,
+ const char **out_value)
+{
+ NMSettingBondPrivate *priv;
+ GList *keys;
+ const char *_key = NULL, *_value = NULL;
+
+ g_return_val_if_fail (NM_IS_SETTING_BOND (setting), FALSE);
+
+ priv = NM_SETTING_BOND_GET_PRIVATE (setting);
+
+ if (idx >= nm_setting_bond_get_num_options (setting))
+ return FALSE;
+
+ keys = g_hash_table_get_keys (priv->options);
+ _key = g_list_nth_data (keys, idx);
+ _value = g_hash_table_lookup (priv->options, _key);
+
+ if (out_name)
+ *out_name = _key;
+ if (out_value)
+ *out_value = _value;
+
+ g_list_free (keys);
+ return TRUE;
+}
+
+static gboolean
+validate_int (const char *name, const char *value, const BondDefault *def)
+{
+ glong num;
+ guint i;
+
+ for (i = 0; i < strlen (value); i++) {
+ if (!g_ascii_isdigit (value[i]) && value[i] != '-')
+ return FALSE;
+ }
+
+ errno = 0;
+ num = strtol (value, NULL, 10);
+ if (errno)
+ return FALSE;
+ if (num < def->min || num > def->max)
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+validate_list (const char *name, const char *value, const BondDefault *def)
+{
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (def->list) && def->list[i]; i++) {
+ if (g_strcmp0 (def->list[i], value) == 0)
+ return TRUE;
+ }
+
+ /* empty validation list means all values pass */
+ return def->list[0] == NULL ? TRUE : FALSE;
+}
+
+static gboolean
+validate_ip (const char *name, const char *value)
+{
+ char **ips, **iter;
+ gboolean success = TRUE;
+ struct in_addr addr;
+
+ if (!value || !value[0])
+ return FALSE;
+
+ ips = g_strsplit_set (value, ",", 0);
+ for (iter = ips; iter && *iter && success; iter++)
+ success = !!inet_aton (*iter, &addr);
+ g_strfreev (ips);
+
+ return success;
+}
+
+static gboolean
+validate_ifname (const char *name, const char *value)
+{
+ if (!value || !value[0])
+ return FALSE;
+
+ return nm_utils_iface_valid_name (value);
+}
+
+/**
+ * nm_setting_bond_validate_option:
+ * @name: the name of the option to validate
+ * @value: the value of the option to validate
+ *
+ * Checks whether @name is a valid bond option and @value is a valid value for
+ * the @name. If @value is %NULL, the function only validates the option name.
+ *
+ * Returns: %TRUE, if the @value is valid for the given name.
+ * If the @name is not a valid option, %FALSE will be returned.
+ **/
+gboolean
+nm_setting_bond_validate_option (const char *name,
+ const char *value)
+{
+ guint i;
+
+ if (!name || !name[0])
+ return FALSE;
+
+ for (i = 0; i < G_N_ELEMENTS (defaults); i++) {
+ if (g_strcmp0 (defaults[i].opt, name) == 0) {
+ if (value == NULL)
+ return TRUE;
+ switch (defaults[i].opt_type) {
+ case TYPE_INT:
+ return validate_int (name, value, &defaults[i]);
+ case TYPE_STR:
+ return validate_list (name, value, &defaults[i]);
+ case TYPE_BOTH:
+ return ( validate_int (name, value, &defaults[i])
+ || validate_list (name, value, &defaults[i]));
+ case TYPE_IP:
+ return validate_ip (name, value);
+ case TYPE_IFNAME:
+ return validate_ifname (name, value);
+ }
+ return FALSE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * nm_setting_bond_get_option_by_name:
+ * @setting: the #NMSettingBond
+ * @name: the option name for which to retrieve the value
+ *
+ * Returns the value associated with the bonding option specified by
+ * @name, if it exists.
+ *
+ * Returns: the value, or %NULL if the key/value pair was never added to the
+ * setting; the value is owned by the setting and must not be modified
+ **/
+const char *
+nm_setting_bond_get_option_by_name (NMSettingBond *setting,
+ const char *name)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL);
+
+ if (!nm_setting_bond_validate_option (name, NULL))
+ return NULL;
+
+ return g_hash_table_lookup (NM_SETTING_BOND_GET_PRIVATE (setting)->options, name);
+}
+
+/**
+ * nm_setting_bond_add_option:
+ * @setting: the #NMSettingBond
+ * @name: name for the option
+ * @value: value for the option
+ *
+ * Add an option to the table. The option is compared to an internal list
+ * of allowed options. Option names may contain only alphanumeric characters
+ * (ie [a-zA-Z0-9]). Adding a new name replaces any existing name/value pair
+ * that may already exist.
+ *
+ * The order of how to set several options is relevant because there are options
+ * that conflict with each other.
+ *
+ * Returns: %TRUE if the option was valid and was added to the internal option
+ * list, %FALSE if it was not.
+ **/
+gboolean
+nm_setting_bond_add_option (NMSettingBond *setting,
+ const char *name,
+ const char *value)
+{
+ NMSettingBondPrivate *priv;
+
+ g_return_val_if_fail (NM_IS_SETTING_BOND (setting), FALSE);
+
+ if (!value || !nm_setting_bond_validate_option (name, value))
+ return FALSE;
+
+ priv = NM_SETTING_BOND_GET_PRIVATE (setting);
+
+ g_hash_table_insert (priv->options, g_strdup (name), g_strdup (value));
+
+ if ( !strcmp (name, NM_SETTING_BOND_OPTION_MIIMON)
+ && strcmp (value, "0") != 0) {
+ g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
+ g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
+ } else if ( !strcmp (name, NM_SETTING_BOND_OPTION_ARP_INTERVAL)
+ && strcmp (value, "0") != 0) {
+ g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_MIIMON);
+ g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_DOWNDELAY);
+ g_hash_table_remove (priv->options, NM_SETTING_BOND_OPTION_UPDELAY);
+ }
+
+ g_object_notify (G_OBJECT (setting), NM_SETTING_BOND_OPTIONS);
+
+ return TRUE;
+}
+
+/**
+ * nm_setting_bond_remove_option:
+ * @setting: the #NMSettingBond
+ * @name: name of the option to remove
+ *
+ * Remove the bonding option referenced by @name from the internal option
+ * list.
+ *
+ * Returns: %TRUE if the option was found and removed from the internal option
+ * list, %FALSE if it was not.
+ **/
+gboolean
+nm_setting_bond_remove_option (NMSettingBond *setting,
+ const char *name)
+{
+ gboolean found;
+
+ g_return_val_if_fail (NM_IS_SETTING_BOND (setting), FALSE);
+
+ if (!nm_setting_bond_validate_option (name, NULL))
+ return FALSE;
+
+ found = g_hash_table_remove (NM_SETTING_BOND_GET_PRIVATE (setting)->options, name);
+ if (found)
+ g_object_notify (G_OBJECT (setting), NM_SETTING_BOND_OPTIONS);
+ return found;
+}
+
+/**
+ * nm_setting_bond_get_valid_options:
+ * @setting: the #NMSettingBond
+ *
+ * Returns a list of valid bond options.
+ *
+ * Returns: (transfer none): a %NULL-terminated array of strings of valid bond options.
+ **/
+const char **
+nm_setting_bond_get_valid_options (NMSettingBond *setting)
+{
+ static const char *array[G_N_ELEMENTS (defaults) + 1] = { NULL };
+ int i;
+
+ /* initialize the array once */
+ if (G_UNLIKELY (array[0] == NULL)) {
+ for (i = 0; i < G_N_ELEMENTS (defaults); i++)
+ array[i] = defaults[i].opt;
+ array[i] = NULL;
+ }
+ return array;
+}
+
+/**
+ * nm_setting_bond_get_option_default:
+ * @setting: the #NMSettingBond
+ * @name: the name of the option
+ *
+ * Returns: the value of the bond option if not overridden by an entry in
+ * the #NMSettingBond:options property.
+ **/
+const char *
+nm_setting_bond_get_option_default (NMSettingBond *setting, const char *name)
+{
+ guint i;
+
+ g_return_val_if_fail (NM_IS_SETTING_BOND (setting), NULL);
+ g_return_val_if_fail (nm_setting_bond_validate_option (name, NULL), NULL);
+
+ for (i = 0; i < G_N_ELEMENTS (defaults); i++) {
+ if (g_strcmp0 (defaults[i].opt, name) == 0)
+ return defaults[i].val;
+ }
+ /* Any option that passes nm_setting_bond_validate_option() should also be found in defaults */
+ g_assert_not_reached ();
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (setting);
+ GHashTableIter iter;
+ const char *key, *value;
+ const char *valid_modes[] = { "balance-rr",
+ "active-backup",
+ "balance-xor",
+ "broadcast",
+ "802.3ad",
+ "balance-tlb",
+ "balance-alb",
+ NULL };
+ int miimon = 0, arp_interval = 0;
+ const char *arp_ip_target = NULL;
+ const char *lacp_rate;
+ const char *primary;
+
+ g_hash_table_iter_init (&iter, priv->options);
+ while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value)) {
+ if (!value[0] || !nm_setting_bond_validate_option (key, value)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("invalid option '%s' or its value '%s'"),
+ key, value);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+ return FALSE;
+ }
+ }
+
+ value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_MIIMON);
+ if (value)
+ miimon = atoi (value);
+ value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
+ if (value)
+ arp_interval = atoi (value);
+
+ /* Can only set one of miimon and arp_interval */
+ if (miimon > 0 && arp_interval > 0) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("only one of '%s' and '%s' can be set"),
+ NM_SETTING_BOND_OPTION_MIIMON,
+ NM_SETTING_BOND_OPTION_ARP_INTERVAL);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+ }
+
+ value = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_MODE);
+ if (!value) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("mandatory option '%s' is missing"),
+ NM_SETTING_BOND_OPTION_MODE);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+ return FALSE;
+ }
+ if (!_nm_utils_string_in_list (value, valid_modes)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid value for '%s'"),
+ value, NM_SETTING_BOND_OPTION_MODE);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+ return FALSE;
+ }
+
+ /* Make sure mode is compatible with other settings */
+ if ( strcmp (value, "balance-alb") == 0
+ || strcmp (value, "balance-tlb") == 0) {
+ if (arp_interval > 0) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s=%s' is incompatible with '%s > 0'"),
+ NM_SETTING_BOND_OPTION_MODE, value, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+ return FALSE;
+ }
+ }
+
+ primary = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_PRIMARY);
+ if (strcmp (value, "active-backup") == 0) {
+ if (primary && !nm_utils_iface_valid_name (primary)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid interface name for '%s' option"),
+ primary, NM_SETTING_BOND_OPTION_PRIMARY);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+ return FALSE;
+ }
+ } else {
+ if (primary) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' option is only valid for '%s=%s'"),
+ NM_SETTING_BOND_OPTION_PRIMARY,
+ NM_SETTING_BOND_OPTION_MODE, "active-backup");
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+ return FALSE;
+ }
+ }
+
+ if (nm_connection_get_setting_infiniband (connection)) {
+ if (strcmp (value, "active-backup") != 0) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s=%s' is not a valid configuration for '%s'"),
+ NM_SETTING_BOND_OPTION_MODE, value, NM_SETTING_INFINIBAND_SETTING_NAME);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+ return FALSE;
+ }
+ }
+
+ if (miimon == 0) {
+ /* updelay and downdelay can only be used with miimon */
+ if (g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_UPDELAY)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' option requires '%s' option to be set"),
+ NM_SETTING_BOND_OPTION_UPDELAY, NM_SETTING_BOND_OPTION_MIIMON);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+ return FALSE;
+ }
+ if (g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_DOWNDELAY)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' option requires '%s' option to be set"),
+ NM_SETTING_BOND_OPTION_DOWNDELAY, NM_SETTING_BOND_OPTION_MIIMON);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+ return FALSE;
+ }
+ }
+
+ /* arp_ip_target can only be used with arp_interval, and must
+ * contain a comma-separated list of IPv4 addresses.
+ */
+ arp_ip_target = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
+ if (arp_interval > 0) {
+ char **addrs;
+ guint32 addr;
+ int i;
+
+ if (!arp_ip_target) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' option requires '%s' option to be set"),
+ NM_SETTING_BOND_OPTION_ARP_INTERVAL, NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+ return FALSE;
+ }
+
+ addrs = g_strsplit (arp_ip_target, ",", -1);
+ if (!addrs[0]) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' option is empty"),
+ NM_SETTING_BOND_OPTION_ARP_IP_TARGET);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+ g_strfreev (addrs);
+ return FALSE;
+ }
+
+ for (i = 0; addrs[i]; i++) {
+ if (!inet_pton (AF_INET, addrs[i], &addr)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid IPv4 address for '%s' option"),
+ NM_SETTING_BOND_OPTION_ARP_IP_TARGET, addrs[i]);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+ g_strfreev (addrs);
+ return FALSE;
+ }
+ }
+ g_strfreev (addrs);
+ } else {
+ if (arp_ip_target) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' option requires '%s' option to be set"),
+ NM_SETTING_BOND_OPTION_ARP_IP_TARGET, NM_SETTING_BOND_OPTION_ARP_INTERVAL);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+ return FALSE;
+ }
+ }
+
+ lacp_rate = g_hash_table_lookup (priv->options, NM_SETTING_BOND_OPTION_LACP_RATE);
+ if ( lacp_rate
+ && (g_strcmp0 (value, "802.3ad") != 0 && g_strcmp0 (value, "4") != 0)
+ && (strcmp (lacp_rate, "slow") != 0 && strcmp (lacp_rate, "0") != 0)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' option is only valid with mode '%s'"),
+ NM_SETTING_BOND_OPTION_LACP_RATE, "802.3ad");
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BOND_SETTING_NAME, NM_SETTING_BOND_OPTIONS);
+ return FALSE;
+ }
+
+ return _nm_connection_verify_required_interface_name (connection, error);
+}
+
+static void
+nm_setting_bond_init (NMSettingBond *setting)
+{
+ NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (setting);
+
+ priv->options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ /* Default values: */
+ nm_setting_bond_add_option (setting, NM_SETTING_BOND_OPTION_MODE, "balance-rr");
+}
+
+static void
+finalize (GObject *object)
+{
+ NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (object);
+
+ g_hash_table_destroy (priv->options);
+
+ G_OBJECT_CLASS (nm_setting_bond_parent_class)->finalize (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_OPTIONS:
+ g_hash_table_unref (priv->options);
+ priv->options = _nm_utils_copy_strdict (g_value_get_boxed (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)
+{
+ NMSettingBondPrivate *priv = NM_SETTING_BOND_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_OPTIONS:
+ g_value_take_boxed (value, _nm_utils_copy_strdict (priv->options));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_setting_bond_class_init (NMSettingBondClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+ NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+ g_type_class_add_private (setting_class, sizeof (NMSettingBondPrivate));
+
+ /* virtual methods */
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+ object_class->finalize = finalize;
+ parent_class->verify = verify;
+
+ /* Properties */
+ /**
+ * NMSettingBond:options:
+ *
+ * Dictionary of key/value pairs of bonding options. Both keys and values
+ * must be strings. Option names must contain only alphanumeric characters
+ * (ie, [a-zA-Z0-9]).
+ *
+ * Type: GHashTable(utf8,utf8)
+ **/
+ /* ---ifcfg-rh---
+ * property: options
+ * variable: BONDING_OPTS
+ * description: Bonding options.
+ * example: BONDING_OPTS="miimon=100 mode=broadcast"
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_OPTIONS,
+ g_param_spec_boxed (NM_SETTING_BOND_OPTIONS, "", "",
+ G_TYPE_HASH_TABLE,
+ 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);
+
+ /* ---dbus---
+ * property: interface-name
+ * format: string
+ * description: Deprecated in favor of connection.interface-name, but can
+ * be used for backward-compatibility with older daemons, to set the
+ * 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);
+}
diff --git a/libnm-core/nm-setting-bond.h b/libnm-core/nm-setting-bond.h
new file mode 100644
index 000000000..055801a59
--- /dev/null
+++ b/libnm-core/nm-setting-bond.h
@@ -0,0 +1,98 @@
+/* -*- 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 2011 - 2013 Red Hat, Inc.
+ */
+
+#ifndef __NM_SETTING_BOND_H__
+#define __NM_SETTING_BOND_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_BOND (nm_setting_bond_get_type ())
+#define NM_SETTING_BOND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_BOND, NMSettingBond))
+#define NM_SETTING_BOND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_BOND, NMSettingBondClass))
+#define NM_IS_SETTING_BOND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_BOND))
+#define NM_IS_SETTING_BOND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_BOND))
+#define NM_SETTING_BOND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_BOND, NMSettingBondClass))
+
+#define NM_SETTING_BOND_SETTING_NAME "bond"
+
+#define NM_SETTING_BOND_OPTIONS "options"
+
+/* Valid options for the 'options' property */
+#define NM_SETTING_BOND_OPTION_MODE "mode"
+#define NM_SETTING_BOND_OPTION_MIIMON "miimon"
+#define NM_SETTING_BOND_OPTION_DOWNDELAY "downdelay"
+#define NM_SETTING_BOND_OPTION_UPDELAY "updelay"
+#define NM_SETTING_BOND_OPTION_ARP_INTERVAL "arp_interval"
+#define NM_SETTING_BOND_OPTION_ARP_IP_TARGET "arp_ip_target"
+#define NM_SETTING_BOND_OPTION_ARP_VALIDATE "arp_validate"
+#define NM_SETTING_BOND_OPTION_PRIMARY "primary"
+#define NM_SETTING_BOND_OPTION_PRIMARY_RESELECT "primary_reselect"
+#define NM_SETTING_BOND_OPTION_FAIL_OVER_MAC "fail_over_mac"
+#define NM_SETTING_BOND_OPTION_USE_CARRIER "use_carrier"
+#define NM_SETTING_BOND_OPTION_AD_SELECT "ad_select"
+#define NM_SETTING_BOND_OPTION_XMIT_HASH_POLICY "xmit_hash_policy"
+#define NM_SETTING_BOND_OPTION_RESEND_IGMP "resend_igmp"
+#define NM_SETTING_BOND_OPTION_LACP_RATE "lacp_rate"
+
+struct _NMSettingBond {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingBondClass;
+
+GType nm_setting_bond_get_type (void);
+
+NMSetting * nm_setting_bond_new (void);
+guint32 nm_setting_bond_get_num_options (NMSettingBond *setting);
+gboolean nm_setting_bond_get_option (NMSettingBond *setting,
+ guint32 idx,
+ const char **out_name,
+ const char **out_value);
+const char * nm_setting_bond_get_option_by_name (NMSettingBond *setting,
+ const char *name);
+gboolean nm_setting_bond_add_option (NMSettingBond *setting,
+ const char *name,
+ const char *value);
+gboolean nm_setting_bond_remove_option (NMSettingBond *setting,
+ const char *name);
+
+gboolean nm_setting_bond_validate_option (const char *name,
+ const char *value);
+
+const char **nm_setting_bond_get_valid_options (NMSettingBond *setting);
+
+const char * nm_setting_bond_get_option_default (NMSettingBond *setting,
+ const char *name);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_BOND_H__ */
diff --git a/libnm-core/nm-setting-bridge-port.c b/libnm-core/nm-setting-bridge-port.c
new file mode 100644
index 000000000..763af37bc
--- /dev/null
+++ b/libnm-core/nm-setting-bridge-port.c
@@ -0,0 +1,321 @@
+/* -*- 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 2012 - 2013 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-bridge-port.h"
+#include "nm-utils.h"
+#include "nm-utils-private.h"
+#include "nm-connection-private.h"
+#include "nm-setting-connection.h"
+#include "nm-setting-bridge.h"
+
+/**
+ * SECTION:nm-setting-bridge-port
+ * @short_description: Describes connection properties for bridge ports
+ *
+ * The #NMSettingBridgePort object is a #NMSetting subclass that describes
+ * 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, 3))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_BRIDGE_PORT)
+
+#define NM_SETTING_BRIDGE_PORT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BRIDGE_PORT, NMSettingBridgePortPrivate))
+
+typedef struct {
+ guint16 priority;
+ guint16 path_cost;
+ gboolean hairpin_mode;
+} NMSettingBridgePortPrivate;
+
+enum {
+ PROP_0,
+ PROP_PRIORITY,
+ PROP_PATH_COST,
+ PROP_HAIRPIN_MODE,
+ LAST_PROP
+};
+
+/**************************************************************************/
+
+/**
+ * nm_setting_bridge_port_get_priority:
+ * @setting: the #NMSettingBridgePort
+ *
+ * Returns: the #NMSettingBridgePort:priority property of the setting
+ **/
+guint16
+nm_setting_bridge_port_get_priority (NMSettingBridgePort *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BRIDGE_PORT (setting), 0);
+
+ return NM_SETTING_BRIDGE_PORT_GET_PRIVATE (setting)->priority;
+}
+
+/**
+ * nm_setting_bridge_port_get_path_cost:
+ * @setting: the #NMSettingBridgePort
+ *
+ * Returns: the #NMSettingBridgePort:path-cost property of the setting
+ **/
+guint16
+nm_setting_bridge_port_get_path_cost (NMSettingBridgePort *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BRIDGE_PORT (setting), 0);
+
+ return NM_SETTING_BRIDGE_PORT_GET_PRIVATE (setting)->path_cost;
+}
+
+/**
+ * nm_setting_bridge_port_get_hairpin_mode:
+ * @setting: the #NMSettingBridgePort
+ *
+ * Returns: the #NMSettingBridgePort:hairpin-mode property of the setting
+ **/
+gboolean
+nm_setting_bridge_port_get_hairpin_mode (NMSettingBridgePort *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BRIDGE_PORT (setting), FALSE);
+
+ return NM_SETTING_BRIDGE_PORT_GET_PRIVATE (setting)->hairpin_mode;
+}
+
+/**************************************************************************/
+
+#define BR_MAX_PORT_PRIORITY 63
+#define BR_DEF_PRIORITY 32
+
+#define BR_MIN_PATH_COST 1
+#define BR_MAX_PATH_COST 65535
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ NMSettingBridgePortPrivate *priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE (setting);
+
+ if (priv->priority > BR_MAX_PORT_PRIORITY) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%d' is not a valid value for the property (should be <= %d)"),
+ priv->priority, BR_MAX_PORT_PRIORITY);
+ g_prefix_error (error, "%s.%s: ",
+ NM_SETTING_BRIDGE_PORT_SETTING_NAME,
+ NM_SETTING_BRIDGE_PORT_PRIORITY);
+ return FALSE;
+ }
+
+ if (priv->path_cost > BR_MAX_PATH_COST) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%d' is not a valid value for the property (should be <= %d)"),
+ priv->path_cost, BR_MAX_PATH_COST);
+ g_prefix_error (error, "%s.%s: ",
+ NM_SETTING_BRIDGE_PORT_SETTING_NAME,
+ NM_SETTING_BRIDGE_PORT_PATH_COST);
+ return FALSE;
+ }
+
+
+ if (connection) {
+ NMSettingConnection *s_con;
+ const char *slave_type;
+
+ s_con = nm_connection_get_setting_connection (connection);
+ if (!s_con) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_SETTING,
+ _("missing setting"));
+ g_prefix_error (error, "%s: ", NM_SETTING_CONNECTION_SETTING_NAME);
+ return FALSE;
+ }
+
+ slave_type = nm_setting_connection_get_slave_type (s_con);
+ if ( slave_type
+ && strcmp (slave_type, NM_SETTING_BRIDGE_SETTING_NAME)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("A connection with a '%s' setting must have the slave-type set to '%s'. Instead it is '%s'"),
+ NM_SETTING_BRIDGE_PORT_SETTING_NAME,
+ NM_SETTING_BRIDGE_SETTING_NAME,
+ slave_type);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_SLAVE_TYPE);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/**************************************************************************/
+
+/**
+ * nm_setting_bridge_port_new:
+ *
+ * Creates a new #NMSettingBridgePort object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingBridgePort object
+ **/
+NMSetting *
+nm_setting_bridge_port_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_BRIDGE_PORT, NULL);
+}
+
+static void
+nm_setting_bridge_port_init (NMSettingBridgePort *setting)
+{
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingBridgePortPrivate *priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_PRIORITY:
+ priv->priority = (guint16) (g_value_get_uint (value) & 0xFFFF);
+ break;
+ case PROP_PATH_COST:
+ priv->path_cost = (guint16) (g_value_get_uint (value) & 0xFFFF);
+ break;
+ case PROP_HAIRPIN_MODE:
+ priv->hairpin_mode = g_value_get_boolean (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)
+{
+ NMSettingBridgePortPrivate *priv = NM_SETTING_BRIDGE_PORT_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_PRIORITY:
+ g_value_set_uint (value, priv->priority);
+ break;
+ case PROP_PATH_COST:
+ g_value_set_uint (value, priv->path_cost);
+ break;
+ case PROP_HAIRPIN_MODE:
+ g_value_set_boolean (value, priv->hairpin_mode);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_setting_bridge_port_class_init (NMSettingBridgePortClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+ NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+ g_type_class_add_private (setting_class, sizeof (NMSettingBridgePortPrivate));
+
+ /* virtual methods */
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+ parent_class->verify = verify;
+
+ /* Properties */
+ /**
+ * NMSettingBridgePort:priority:
+ *
+ * The Spanning Tree Protocol (STP) priority of this bridge port.
+ **/
+ /* ---ifcfg-rh---
+ * property: priority
+ * variable: BRIDGING_OPTS: priority=
+ * values: 0 - 63
+ * default: 32
+ * description: STP priority.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_PRIORITY,
+ g_param_spec_uint (NM_SETTING_BRIDGE_PORT_PRIORITY, "", "",
+ 0, BR_MAX_PORT_PRIORITY, BR_DEF_PRIORITY,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingBridgePort:path-cost:
+ *
+ * The Spanning Tree Protocol (STP) port cost for destinations via this
+ * port.
+ **/
+ /* ---ifcfg-rh---
+ * property: path-cost
+ * variable: BRIDGING_OPTS: path_cost=
+ * values: 1 - 65535
+ * default: 100
+ * description: STP cost.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_PATH_COST,
+ g_param_spec_uint (NM_SETTING_BRIDGE_PORT_PATH_COST, "", "",
+ 0, BR_MAX_PATH_COST, 100,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingBridgePort:hairpin-mode:
+ *
+ * Enables or disabled "hairpin mode" for the port, which allows frames to
+ * be sent back out through the port the frame was received on.
+ **/
+ /* ---ifcfg-rh---
+ * property: hairpin-mode
+ * variable: BRIDGING_OPTS: hairpin_mode=
+ * default: yes
+ * description: Hairpin mode of the bridge port.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_HAIRPIN_MODE,
+ g_param_spec_boolean (NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE, "", "",
+ FALSE,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+}
diff --git a/libnm-core/nm-setting-bridge-port.h b/libnm-core/nm-setting-bridge-port.h
new file mode 100644
index 000000000..49ca38b34
--- /dev/null
+++ b/libnm-core/nm-setting-bridge-port.h
@@ -0,0 +1,69 @@
+/* -*- 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 2012 Red Hat, Inc.
+ */
+
+#ifndef __NM_SETTING_BRIDGE_PORT_H__
+#define __NM_SETTING_BRIDGE_PORT_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_BRIDGE_PORT (nm_setting_bridge_port_get_type ())
+#define NM_SETTING_BRIDGE_PORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_BRIDGE_PORT, NMSettingBridgePort))
+#define NM_SETTING_BRIDGE_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_BRIDGE_PORT, NMSettingBridgePortClass))
+#define NM_IS_SETTING_BRIDGE_PORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_BRIDGE_PORT))
+#define NM_IS_SETTING_BRIDGE_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_BRIDGE_PORT))
+#define NM_SETTING_BRIDGE_PORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_BRIDGE_PORT, NMSettingBridgePortClass))
+
+#define NM_SETTING_BRIDGE_PORT_SETTING_NAME "bridge-port"
+
+#define NM_SETTING_BRIDGE_PORT_PRIORITY "priority"
+#define NM_SETTING_BRIDGE_PORT_PATH_COST "path-cost"
+#define NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE "hairpin-mode"
+
+struct _NMSettingBridgePort {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingBridgePortClass;
+
+GType nm_setting_bridge_port_get_type (void);
+
+NMSetting * nm_setting_bridge_port_new (void);
+
+guint16 nm_setting_bridge_port_get_priority (NMSettingBridgePort *setting);
+
+guint16 nm_setting_bridge_port_get_path_cost (NMSettingBridgePort *setting);
+
+gboolean nm_setting_bridge_port_get_hairpin_mode (NMSettingBridgePort *setting);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_BRIDGE_PORT_H__ */
diff --git a/libnm-core/nm-setting-bridge.c b/libnm-core/nm-setting-bridge.c
new file mode 100644
index 000000000..51c6ac5a0
--- /dev/null
+++ b/libnm-core/nm-setting-bridge.c
@@ -0,0 +1,540 @@
+/* -*- 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 2011 - 2013 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-bridge.h"
+#include "nm-connection-private.h"
+#include "nm-utils.h"
+#include "nm-utils-private.h"
+
+/**
+ * SECTION:nm-setting-bridge
+ * @short_description: Describes connection properties for bridges
+ *
+ * The #NMSettingBridge object is a #NMSetting subclass that describes properties
+ * necessary for bridging connections.
+ **/
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingBridge, nm_setting_bridge, NM_TYPE_SETTING,
+ _nm_register_setting (BRIDGE, 1))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_BRIDGE)
+
+#define NM_SETTING_BRIDGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_BRIDGE, NMSettingBridgePrivate))
+
+typedef struct {
+ char * mac_address;
+ gboolean stp;
+ guint16 priority;
+ guint16 forward_delay;
+ guint16 hello_time;
+ guint16 max_age;
+ guint32 ageing_time;
+} NMSettingBridgePrivate;
+
+enum {
+ PROP_0,
+ PROP_MAC_ADDRESS,
+ PROP_STP,
+ PROP_PRIORITY,
+ PROP_FORWARD_DELAY,
+ PROP_HELLO_TIME,
+ PROP_MAX_AGE,
+ PROP_AGEING_TIME,
+ LAST_PROP
+};
+
+/**
+ * nm_setting_bridge_new:
+ *
+ * Creates a new #NMSettingBridge object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingBridge object
+ **/
+NMSetting *
+nm_setting_bridge_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_BRIDGE, NULL);
+}
+
+/**
+ * nm_setting_bridge_get_mac_address:
+ * @setting: the #NMSettingBridge
+ *
+ * Returns: the #NMSettingBridge:mac-address property of the setting
+ **/
+const char *
+nm_setting_bridge_get_mac_address (NMSettingBridge *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), NULL);
+
+ return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->mac_address;
+}
+
+/**
+ * nm_setting_bridge_get_stp:
+ * @setting: the #NMSettingBridge
+ *
+ * Returns: the #NMSettingBridge:stp property of the setting
+ **/
+gboolean
+nm_setting_bridge_get_stp (NMSettingBridge *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), FALSE);
+
+ return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->stp;
+}
+
+/**
+ * nm_setting_bridge_get_priority:
+ * @setting: the #NMSettingBridge
+ *
+ * Returns: the #NMSettingBridge:priority property of the setting
+ **/
+guint16
+nm_setting_bridge_get_priority (NMSettingBridge *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), 0);
+
+ return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->priority;
+}
+
+/**
+ * nm_setting_bridge_get_forward_delay:
+ * @setting: the #NMSettingBridge
+ *
+ * Returns: the #NMSettingBridge:forward-delay property of the setting
+ **/
+guint16
+nm_setting_bridge_get_forward_delay (NMSettingBridge *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), 0);
+
+ return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->forward_delay;
+}
+
+/**
+ * nm_setting_bridge_get_hello_time:
+ * @setting: the #NMSettingBridge
+ *
+ * Returns: the #NMSettingBridge:hello-time property of the setting
+ **/
+guint16
+nm_setting_bridge_get_hello_time (NMSettingBridge *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), 0);
+
+ return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->hello_time;
+}
+
+/**
+ * nm_setting_bridge_get_max_age:
+ * @setting: the #NMSettingBridge
+ *
+ * Returns: the #NMSettingBridge:max-age property of the setting
+ **/
+guint16
+nm_setting_bridge_get_max_age (NMSettingBridge *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), 0);
+
+ return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->max_age;
+}
+
+/**
+ * nm_setting_bridge_get_ageing_time:
+ * @setting: the #NMSettingBridge
+ *
+ * Returns: the #NMSettingBridge:ageing-time property of the setting
+ **/
+guint
+nm_setting_bridge_get_ageing_time (NMSettingBridge *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_BRIDGE (setting), 0);
+
+ return NM_SETTING_BRIDGE_GET_PRIVATE (setting)->ageing_time;
+}
+
+/* IEEE 802.1D-1998 timer values */
+#define BR_MIN_HELLO_TIME 1
+#define BR_MAX_HELLO_TIME 10
+
+#define BR_MIN_FORWARD_DELAY 2
+#define BR_MAX_FORWARD_DELAY 30
+
+#define BR_MIN_MAX_AGE 6
+#define BR_MAX_MAX_AGE 40
+
+/* IEEE 802.1D-1998 Table 7.4 */
+#define BR_MIN_AGEING_TIME 0
+#define BR_MAX_AGEING_TIME 1000000
+
+static inline gboolean
+check_range (guint32 val,
+ guint32 min,
+ guint32 max,
+ const char *prop,
+ GError **error)
+{
+ if ((val != 0) && (val < min || val > max)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("value '%d' is out of range <%d-%d>"),
+ val, min, max);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, prop);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE (setting);
+
+ if (priv->mac_address && !nm_utils_hwaddr_valid (priv->mac_address, ETH_ALEN)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("is not a valid MAC address"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_BRIDGE_SETTING_NAME, NM_SETTING_BRIDGE_MAC_ADDRESS);
+ return FALSE;
+ }
+
+ if (!check_range (priv->forward_delay,
+ BR_MIN_FORWARD_DELAY,
+ BR_MAX_FORWARD_DELAY,
+ NM_SETTING_BRIDGE_FORWARD_DELAY,
+ error))
+ return FALSE;
+
+ if (!check_range (priv->hello_time,
+ BR_MIN_HELLO_TIME,
+ BR_MAX_HELLO_TIME,
+ NM_SETTING_BRIDGE_HELLO_TIME,
+ error))
+ return FALSE;
+
+ if (!check_range (priv->max_age,
+ BR_MIN_MAX_AGE,
+ BR_MAX_MAX_AGE,
+ NM_SETTING_BRIDGE_MAX_AGE,
+ error))
+ return FALSE;
+
+ if (!check_range (priv->ageing_time,
+ BR_MIN_AGEING_TIME,
+ BR_MAX_AGEING_TIME,
+ NM_SETTING_BRIDGE_AGEING_TIME,
+ error))
+ return FALSE;
+
+ return _nm_connection_verify_required_interface_name (connection, error);
+}
+
+static void
+nm_setting_bridge_init (NMSettingBridge *setting)
+{
+}
+
+static void
+finalize (GObject *object)
+{
+ NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE (object);
+
+ g_free (priv->mac_address);
+
+ G_OBJECT_CLASS (nm_setting_bridge_parent_class)->finalize (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_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),
+ ETH_ALEN);
+ break;
+ case PROP_STP:
+ priv->stp = g_value_get_boolean (value);
+ break;
+ case PROP_PRIORITY:
+ priv->priority = (guint16) g_value_get_uint (value);
+ break;
+ case PROP_FORWARD_DELAY:
+ priv->forward_delay = (guint16) g_value_get_uint (value);
+ break;
+ case PROP_HELLO_TIME:
+ priv->hello_time = (guint16) g_value_get_uint (value);
+ break;
+ case PROP_MAX_AGE:
+ priv->max_age = (guint16) g_value_get_uint (value);
+ break;
+ case PROP_AGEING_TIME:
+ priv->ageing_time = g_value_get_uint (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)
+{
+ NMSettingBridgePrivate *priv = NM_SETTING_BRIDGE_GET_PRIVATE (object);
+ NMSettingBridge *setting = NM_SETTING_BRIDGE (object);
+
+ switch (prop_id) {
+ case PROP_MAC_ADDRESS:
+ g_value_set_string (value, nm_setting_bridge_get_mac_address (setting));
+ break;
+ case PROP_STP:
+ g_value_set_boolean (value, priv->stp);
+ break;
+ case PROP_PRIORITY:
+ g_value_set_uint (value, priv->priority);
+ break;
+ case PROP_FORWARD_DELAY:
+ g_value_set_uint (value, priv->forward_delay);
+ break;
+ case PROP_HELLO_TIME:
+ g_value_set_uint (value, priv->hello_time);
+ break;
+ case PROP_MAX_AGE:
+ g_value_set_uint (value, priv->max_age);
+ break;
+ case PROP_AGEING_TIME:
+ g_value_set_uint (value, priv->ageing_time);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_setting_bridge_class_init (NMSettingBridgeClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+ NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+ g_type_class_add_private (setting_class, 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 */
+ /**
+ * NMSettingBridge:mac-address:
+ *
+ * If specified, the MAC address of bridge. When creating a new bridge, this
+ * MAC address will be set. When matching an existing (outside
+ * NetworkManager created) bridge, this MAC address must match.
+ **/
+ /* ---keyfile---
+ * property: mac-address
+ * format: ususal hex-digits-and-colons notation
+ * description: MAC address in traditional hex-digits-and-colons notation,
+ * or semicolon separated list of 6 decimal bytes (obsolete)
+ * example: mac-address=00:22:68:12:79:A2
+ * mac-address=0;34;104;18;121;162;
+ * ---end---
+ * ---ifcfg-rh---
+ * property: mac-address
+ * variable: MACADDR(+)
+ * description: MAC address of the bridge. Note that this requires a recent
+ * kernel support, originally introduced in 3.15 upstream kernel)
+ * MACADDR for bridges is an NM extension.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_MAC_ADDRESS,
+ g_param_spec_string (NM_SETTING_BRIDGE_MAC_ADDRESS, "", "",
+ NULL,
+ 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);
+
+ /**
+ * NMSettingBridge:stp:
+ *
+ * Controls whether Spanning Tree Protocol (STP) is enabled for this bridge.
+ **/
+ /* ---ifcfg-rh---
+ * property: stp
+ * variable: STP
+ * default: no
+ * description: Span tree protocol participation.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_STP,
+ g_param_spec_boolean (NM_SETTING_BRIDGE_STP, "", "",
+ TRUE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingBridge:priority:
+ *
+ * Sets the Spanning Tree Protocol (STP) priority for this bridge. Lower
+ * values are "better"; the lowest priority bridge will be elected the root
+ * bridge.
+ **/
+ /* ---ifcfg-rh---
+ * property: priority
+ * variable: BRIDGING_OPTS: priority=
+ * values: 0 - 32768
+ * default: 32768
+ * description: STP priority.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_PRIORITY,
+ g_param_spec_uint (NM_SETTING_BRIDGE_PRIORITY, "", "",
+ 0, G_MAXUINT16, 0x8000,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingBridge:forward-delay:
+ *
+ * The Spanning Tree Protocol (STP) forwarding delay, in seconds.
+ **/
+ /* ---ifcfg-rh---
+ * property: forward-delay
+ * variable: DELAY
+ * values: 2 - 30
+ * default: 15
+ * description: STP forwarding delay.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_FORWARD_DELAY,
+ g_param_spec_uint (NM_SETTING_BRIDGE_FORWARD_DELAY, "", "",
+ 0, BR_MAX_FORWARD_DELAY, 15,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingBridge:hello-time:
+ *
+ * The Spanning Tree Protocol (STP) hello time, in seconds.
+ **/
+ /* ---ifcfg-rh---
+ * property: hello-time
+ * variable: BRIDGING_OPTS: hello_time=
+ * values: 1 - 10
+ * default: 2
+ * description: STP hello time.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_HELLO_TIME,
+ g_param_spec_uint (NM_SETTING_BRIDGE_HELLO_TIME, "", "",
+ 0, BR_MAX_HELLO_TIME, 2,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingBridge:max-age:
+ *
+ * The Spanning Tree Protocol (STP) maximum message age, in seconds.
+ **/
+ /* ---ifcfg-rh---
+ * property: max-age
+ * variable: BRIDGING_OPTS: max_age=
+ * values: 6 - 40
+ * default: 20
+ * description: STP maximum message age.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_MAX_AGE,
+ g_param_spec_uint (NM_SETTING_BRIDGE_MAX_AGE, "", "",
+ 0, BR_MAX_MAX_AGE, 20,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingBridge:ageing-time:
+ *
+ * The Ethernet MAC address aging time, in seconds.
+ **/
+ /* ---ifcfg-rh---
+ * property: ageing-time
+ * variable: BRIDGING_OPTS: ageing_time=
+ * values: 0 - 1000000
+ * default: 300
+ * description: Ethernet MAC ageing time.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_AGEING_TIME,
+ g_param_spec_uint (NM_SETTING_BRIDGE_AGEING_TIME, "", "",
+ 0, BR_MAX_AGEING_TIME, 300,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /* ---dbus---
+ * property: interface-name
+ * format: string
+ * description: Deprecated in favor of connection.interface-name, but can
+ * be used for backward-compatibility with older daemons, to set the
+ * 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);
+}
diff --git a/libnm-core/nm-setting-bridge.h b/libnm-core/nm-setting-bridge.h
new file mode 100644
index 000000000..b4fe74772
--- /dev/null
+++ b/libnm-core/nm-setting-bridge.h
@@ -0,0 +1,81 @@
+/* -*- 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 2011 - 2012 Red Hat, Inc.
+ */
+
+#ifndef __NM_SETTING_BRIDGE_H__
+#define __NM_SETTING_BRIDGE_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_BRIDGE (nm_setting_bridge_get_type ())
+#define NM_SETTING_BRIDGE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_BRIDGE, NMSettingBridge))
+#define NM_SETTING_BRIDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_BRIDGE, NMSettingBridgeClass))
+#define NM_IS_SETTING_BRIDGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_BRIDGE))
+#define NM_IS_SETTING_BRIDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_BRIDGE))
+#define NM_SETTING_BRIDGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_BRIDGE, NMSettingBridgeClass))
+
+#define NM_SETTING_BRIDGE_SETTING_NAME "bridge"
+
+#define NM_SETTING_BRIDGE_MAC_ADDRESS "mac-address"
+#define NM_SETTING_BRIDGE_STP "stp"
+#define NM_SETTING_BRIDGE_PRIORITY "priority"
+#define NM_SETTING_BRIDGE_FORWARD_DELAY "forward-delay"
+#define NM_SETTING_BRIDGE_HELLO_TIME "hello-time"
+#define NM_SETTING_BRIDGE_MAX_AGE "max-age"
+#define NM_SETTING_BRIDGE_AGEING_TIME "ageing-time"
+
+struct _NMSettingBridge {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingBridgeClass;
+
+GType nm_setting_bridge_get_type (void);
+
+NMSetting * nm_setting_bridge_new (void);
+
+const char * nm_setting_bridge_get_mac_address (NMSettingBridge *setting);
+
+gboolean nm_setting_bridge_get_stp (NMSettingBridge *setting);
+
+guint16 nm_setting_bridge_get_priority (NMSettingBridge *setting);
+
+guint16 nm_setting_bridge_get_forward_delay (NMSettingBridge *setting);
+
+guint16 nm_setting_bridge_get_hello_time (NMSettingBridge *setting);
+
+guint16 nm_setting_bridge_get_max_age (NMSettingBridge *setting);
+
+guint32 nm_setting_bridge_get_ageing_time (NMSettingBridge *setting);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_BRIDGE_H__ */
diff --git a/libnm-core/nm-setting-cdma.c b/libnm-core/nm-setting-cdma.c
new file mode 100644
index 000000000..ebbbda740
--- /dev/null
+++ b/libnm-core/nm-setting-cdma.c
@@ -0,0 +1,336 @@
+/* -*- 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 2007 - 2013 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-cdma.h"
+#include "nm-utils.h"
+#include "nm-setting-private.h"
+#include "nm-core-enum-types.h"
+
+/**
+ * SECTION:nm-setting-cdma
+ * @short_description: Describes CDMA-based mobile broadband properties
+ *
+ * The #NMSettingCdma object is a #NMSetting subclass that describes
+ * properties that allow connections to IS-95-based mobile broadband
+ * networks, including those using CDMA2000/EVDO technology.
+ */
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingCdma, nm_setting_cdma, NM_TYPE_SETTING,
+ _nm_register_setting (CDMA, 1))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_CDMA)
+
+#define NM_SETTING_CDMA_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_CDMA, NMSettingCdmaPrivate))
+
+typedef struct {
+ char *number; /* For dialing, duh */
+ char *username;
+ char *password;
+ NMSettingSecretFlags password_flags;
+} NMSettingCdmaPrivate;
+
+enum {
+ PROP_0,
+ PROP_NUMBER,
+ PROP_USERNAME,
+ PROP_PASSWORD,
+ PROP_PASSWORD_FLAGS,
+
+ LAST_PROP
+};
+
+/**
+ * nm_setting_cdma_new:
+ *
+ * Creates a new #NMSettingCdma object with default values.
+ *
+ * Returns: the new empty #NMSettingCdma object
+ **/
+NMSetting *
+nm_setting_cdma_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_CDMA, NULL);
+}
+
+/**
+ * nm_setting_cdma_get_number:
+ * @setting: the #NMSettingCdma
+ *
+ * Returns: the #NMSettingCdma:number property of the setting
+ **/
+const char *
+nm_setting_cdma_get_number (NMSettingCdma *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_CDMA (setting), NULL);
+
+ return NM_SETTING_CDMA_GET_PRIVATE (setting)->number;
+}
+
+/**
+ * nm_setting_cdma_get_username:
+ * @setting: the #NMSettingCdma
+ *
+ * Returns: the #NMSettingCdma:username property of the setting
+ **/
+const char *
+nm_setting_cdma_get_username (NMSettingCdma *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_CDMA (setting), NULL);
+
+ return NM_SETTING_CDMA_GET_PRIVATE (setting)->username;
+}
+
+/**
+ * nm_setting_cdma_get_password:
+ * @setting: the #NMSettingCdma
+ *
+ * Returns: the #NMSettingCdma:password property of the setting
+ **/
+const char *
+nm_setting_cdma_get_password (NMSettingCdma *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_CDMA (setting), NULL);
+
+ return NM_SETTING_CDMA_GET_PRIVATE (setting)->password;
+}
+
+/**
+ * nm_setting_cdma_get_password_flags:
+ * @setting: the #NMSettingCdma
+ *
+ * Returns: the #NMSettingSecretFlags pertaining to the #NMSettingCdma:password
+ **/
+NMSettingSecretFlags
+nm_setting_cdma_get_password_flags (NMSettingCdma *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_CDMA (setting), NM_SETTING_SECRET_FLAG_NONE);
+
+ return NM_SETTING_CDMA_GET_PRIVATE (setting)->password_flags;
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ NMSettingCdmaPrivate *priv = NM_SETTING_CDMA_GET_PRIVATE (setting);
+
+ if (!priv->number) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CDMA_SETTING_NAME, NM_SETTING_CDMA_NUMBER);
+ return FALSE;
+ } else if (!strlen (priv->number)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty'"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CDMA_SETTING_NAME, NM_SETTING_CDMA_NUMBER);
+ return FALSE;
+ }
+
+ if (priv->username && !strlen (priv->username)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CDMA_SETTING_NAME, NM_SETTING_CDMA_USERNAME);
+ return FALSE;
+ }
+
+ if (priv->password && !strlen (priv->password)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CDMA_SETTING_NAME, NM_SETTING_CDMA_PASSWORD);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static GPtrArray *
+need_secrets (NMSetting *setting)
+{
+ NMSettingCdmaPrivate *priv = NM_SETTING_CDMA_GET_PRIVATE (setting);
+ GPtrArray *secrets = NULL;
+
+ if (priv->password)
+ return NULL;
+
+ if (priv->username) {
+ if (!(priv->password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) {
+ secrets = g_ptr_array_sized_new (1);
+ g_ptr_array_add (secrets, NM_SETTING_CDMA_PASSWORD);
+ }
+ }
+
+ return secrets;
+}
+
+static void
+nm_setting_cdma_init (NMSettingCdma *setting)
+{
+}
+
+static void
+finalize (GObject *object)
+{
+ NMSettingCdmaPrivate *priv = NM_SETTING_CDMA_GET_PRIVATE (object);
+
+ g_free (priv->number);
+ g_free (priv->username);
+ g_free (priv->password);
+
+ G_OBJECT_CLASS (nm_setting_cdma_parent_class)->finalize (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingCdmaPrivate *priv = NM_SETTING_CDMA_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_NUMBER:
+ g_free (priv->number);
+ priv->number = g_value_dup_string (value);
+ break;
+ case PROP_USERNAME:
+ g_free (priv->username);
+ priv->username = g_value_dup_string (value);
+ break;
+ case PROP_PASSWORD:
+ g_free (priv->password);
+ priv->password = g_value_dup_string (value);
+ break;
+ case PROP_PASSWORD_FLAGS:
+ priv->password_flags = g_value_get_flags (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)
+{
+ NMSettingCdma *setting = NM_SETTING_CDMA (object);
+
+ switch (prop_id) {
+ case PROP_NUMBER:
+ g_value_set_string (value, nm_setting_cdma_get_number (setting));
+ break;
+ case PROP_USERNAME:
+ g_value_set_string (value, nm_setting_cdma_get_username (setting));
+ break;
+ case PROP_PASSWORD:
+ g_value_set_string (value, nm_setting_cdma_get_password (setting));
+ break;
+ case PROP_PASSWORD_FLAGS:
+ g_value_set_flags (value, nm_setting_cdma_get_password_flags (setting));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_setting_cdma_class_init (NMSettingCdmaClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+ NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+ g_type_class_add_private (setting_class, 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->need_secrets = need_secrets;
+
+ /* Properties */
+
+ /**
+ * NMSettingCdma:number:
+ *
+ * The number to dial to establish the connection to the CDMA-based mobile
+ * broadband network, if any. If not specified, the default number (#777)
+ * is used when required.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_NUMBER,
+ g_param_spec_string (NM_SETTING_CDMA_NUMBER, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingCdma:username:
+ *
+ * The username used to authenticate with the network, if required. Many
+ * providers do not require a username, or accept any username. But if a
+ * username is required, it is specified here.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_USERNAME,
+ g_param_spec_string (NM_SETTING_CDMA_USERNAME, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingCdma:password:
+ *
+ * The password used to authenticate with the network, if required. Many
+ * providers do not require a password, or accept any password. But if a
+ * password is required, it is specified here.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_PASSWORD,
+ g_param_spec_string (NM_SETTING_CDMA_PASSWORD, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_SECRET |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingCdma:password-flags:
+ *
+ * Flags indicating how to handle the #NMSettingCdma:password property.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_PASSWORD_FLAGS,
+ g_param_spec_flags (NM_SETTING_CDMA_PASSWORD_FLAGS, "", "",
+ NM_TYPE_SETTING_SECRET_FLAGS,
+ NM_SETTING_SECRET_FLAG_NONE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+}
diff --git a/libnm-core/nm-setting-cdma.h b/libnm-core/nm-setting-cdma.h
new file mode 100644
index 000000000..6e333dccc
--- /dev/null
+++ b/libnm-core/nm-setting-cdma.h
@@ -0,0 +1,69 @@
+/* -*- 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 2007 - 2011 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#ifndef __NM_SETTING_CDMA_H__
+#define __NM_SETTING_CDMA_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_CDMA (nm_setting_cdma_get_type ())
+#define NM_SETTING_CDMA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_CDMA, NMSettingCdma))
+#define NM_SETTING_CDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_CDMA, NMSettingCdmaClass))
+#define NM_IS_SETTING_CDMA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_CDMA))
+#define NM_IS_SETTING_CDMA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_CDMA))
+#define NM_SETTING_CDMA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_CDMA, NMSettingCdmaClass))
+
+#define NM_SETTING_CDMA_SETTING_NAME "cdma"
+
+#define NM_SETTING_CDMA_NUMBER "number"
+#define NM_SETTING_CDMA_USERNAME "username"
+#define NM_SETTING_CDMA_PASSWORD "password"
+#define NM_SETTING_CDMA_PASSWORD_FLAGS "password-flags"
+
+struct _NMSettingCdma {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingCdmaClass;
+
+GType nm_setting_cdma_get_type (void);
+
+NMSetting *nm_setting_cdma_new (void);
+const char *nm_setting_cdma_get_number (NMSettingCdma *setting);
+const char *nm_setting_cdma_get_username (NMSettingCdma *setting);
+const char *nm_setting_cdma_get_password (NMSettingCdma *setting);
+NMSettingSecretFlags nm_setting_cdma_get_password_flags (NMSettingCdma *setting);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_CDMA_H__ */
diff --git a/libnm-core/nm-setting-connection.c b/libnm-core/nm-setting-connection.c
new file mode 100644
index 000000000..01f5d423c
--- /dev/null
+++ b/libnm-core/nm-setting-connection.c
@@ -0,0 +1,1569 @@
+/* -*- 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 2007 - 2013 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-utils.h"
+#include "nm-utils-private.h"
+#include "nm-setting-connection.h"
+#include "nm-connection-private.h"
+#include "nm-setting-bond.h"
+#include "nm-setting-bridge.h"
+#include "nm-setting-team.h"
+#include "nm-setting-vlan.h"
+
+/**
+ * SECTION:nm-setting-connection
+ * @short_description: Describes general connection properties
+ *
+ * The #NMSettingConnection object is a #NMSetting subclass that describes
+ * properties that apply to all #NMConnection objects, regardless of what type
+ * of network connection they describe. Each #NMConnection object must contain
+ * a #NMSettingConnection setting.
+ **/
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingConnection, nm_setting_connection, NM_TYPE_SETTING,
+ _nm_register_setting (CONNECTION, 0))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_CONNECTION)
+
+#define NM_SETTING_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_CONNECTION, NMSettingConnectionPrivate))
+
+typedef enum {
+ PERM_TYPE_USER = 0,
+} PermType;
+
+typedef struct {
+ guint8 ptype;
+ char *item;
+} Permission;
+
+typedef struct {
+ char *id;
+ char *uuid;
+ char *interface_name;
+ char *type;
+ char *master;
+ char *slave_type;
+ GSList *permissions; /* list of Permission structs */
+ gboolean autoconnect;
+ gint autoconnect_priority;
+ guint64 timestamp;
+ gboolean read_only;
+ char *zone;
+ GSList *secondaries; /* secondary connections to activate with the base connection */
+ guint gateway_ping_timeout;
+} NMSettingConnectionPrivate;
+
+enum {
+ PROP_0,
+ PROP_ID,
+ PROP_UUID,
+ PROP_INTERFACE_NAME,
+ PROP_TYPE,
+ PROP_PERMISSIONS,
+ PROP_AUTOCONNECT,
+ PROP_AUTOCONNECT_PRIORITY,
+ PROP_TIMESTAMP,
+ PROP_READ_ONLY,
+ PROP_ZONE,
+ PROP_MASTER,
+ PROP_SLAVE_TYPE,
+ PROP_SECONDARIES,
+ PROP_GATEWAY_PING_TIMEOUT,
+
+ LAST_PROP
+};
+
+/***********************************************************************/
+
+#define PERM_USER_PREFIX "user:"
+
+static Permission *
+permission_new_from_str (const char *str)
+{
+ Permission *p;
+ const char *last_colon;
+ size_t ulen = 0, i;
+
+ g_return_val_if_fail (strncmp (str, PERM_USER_PREFIX, strlen (PERM_USER_PREFIX)) == 0, NULL);
+ str += strlen (PERM_USER_PREFIX);
+
+ last_colon = strrchr (str, ':');
+ if (last_colon) {
+ /* Ensure that somebody didn't pass "user::" */
+ g_return_val_if_fail (last_colon > str, NULL);
+
+ /* Reject :[detail] for now */
+ g_return_val_if_fail (*(last_colon + 1) == '\0', NULL);
+
+ /* Make sure we don't include detail in the username */
+ ulen = last_colon - str;
+ } else
+ ulen = strlen (str);
+
+ /* Sanity check the length of the username */
+ g_return_val_if_fail (ulen < 100, NULL);
+
+ /* Make sure there's no ':' in the username */
+ for (i = 0; i < ulen; i++)
+ g_return_val_if_fail (str[i] != ':', NULL);
+
+ /* And the username must be valid UTF-8 */
+ g_return_val_if_fail (g_utf8_validate (str, -1, NULL) == TRUE, NULL);
+
+ /* Yay, valid... create the new permission */
+ p = g_slice_new0 (Permission);
+ p->ptype = PERM_TYPE_USER;
+ if (last_colon) {
+ p->item = g_malloc (ulen + 1);
+ memcpy (p->item, str, ulen);
+ p->item[ulen] = '\0';
+ } else
+ p->item = g_strdup (str);
+
+ return p;
+}
+
+static Permission *
+permission_new (const char *uname)
+{
+ Permission *p;
+
+ g_return_val_if_fail (uname, NULL);
+ g_return_val_if_fail (uname[0] != '\0', NULL);
+ g_return_val_if_fail (strchr (uname, ':') == NULL, NULL);
+ g_return_val_if_fail (g_utf8_validate (uname, -1, NULL) == TRUE, NULL);
+
+ /* Yay, valid... create the new permission */
+ p = g_slice_new0 (Permission);
+ p->ptype = PERM_TYPE_USER;
+ p->item = g_strdup (uname);
+ return p;
+}
+
+static char *
+permission_to_string (Permission *p)
+{
+ return g_strdup_printf (PERM_USER_PREFIX "%s:", p->item);
+}
+
+static void
+permission_free (Permission *p)
+{
+ g_free (p->item);
+ memset (p, 0, sizeof (*p));
+ g_slice_free (Permission, p);
+}
+
+/***********************************************************************/
+
+/**
+ * nm_setting_connection_new:
+ *
+ * Creates a new #NMSettingConnection object with default values.
+ *
+ * Returns: the new empty #NMSettingConnection object
+ **/
+NMSetting *nm_setting_connection_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_CONNECTION, NULL);
+}
+
+/**
+ * nm_setting_connection_get_id:
+ * @setting: the #NMSettingConnection
+ *
+ * Returns the #NMSettingConnection:id property of the connection.
+ *
+ * Returns: the connection ID
+ **/
+const char *
+nm_setting_connection_get_id (NMSettingConnection *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), NULL);
+
+ return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->id;
+}
+
+/**
+ * nm_setting_connection_get_uuid:
+ * @setting: the #NMSettingConnection
+ *
+ * Returns the #NMSettingConnection:uuid property of the connection.
+ *
+ * Returns: the connection UUID
+ **/
+const char *
+nm_setting_connection_get_uuid (NMSettingConnection *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), NULL);
+
+ return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->uuid;
+}
+
+/**
+ * nm_setting_connection_get_interface_name:
+ * @setting: the #NMSettingConnection
+ *
+ * Returns the #NMSettingConnection:interface-name property of the connection.
+ *
+ * Returns: the connection's interface name
+ **/
+const char *
+nm_setting_connection_get_interface_name (NMSettingConnection *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), NULL);
+
+ return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->interface_name;
+}
+
+/**
+ * nm_setting_connection_get_connection_type:
+ * @setting: the #NMSettingConnection
+ *
+ * Returns the #NMSettingConnection:type property of the connection.
+ *
+ * Returns: the connection type
+ **/
+const char *
+nm_setting_connection_get_connection_type (NMSettingConnection *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), NULL);
+
+ return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->type;
+}
+
+
+/**
+ * nm_setting_connection_get_num_permissions:
+ * @setting: the #NMSettingConnection
+ *
+ * Returns the number of entires in the #NMSettingConnection:permissions
+ * property of this setting.
+ *
+ * Returns: the number of permissions entires
+ */
+guint32
+nm_setting_connection_get_num_permissions (NMSettingConnection *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), 0);
+
+ return g_slist_length (NM_SETTING_CONNECTION_GET_PRIVATE (setting)->permissions);
+}
+
+/**
+ * nm_setting_connection_get_permission:
+ * @setting: the #NMSettingConnection
+ * @idx: the zero-based index of the permissions entry
+ * @out_ptype: on return, the permission type (at this time, always "user")
+ * @out_pitem: on return, the permission item (formatted accoring to @ptype, see
+ * #NMSettingConnection:permissions for more detail
+ * @out_detail: on return, the permission detail (at this time, always %NULL)
+ *
+ * Retrieve one of the entries of the #NMSettingConnection:permissions property
+ * of this setting.
+ *
+ * Returns: %TRUE if a permission was returned, %FALSE if @idx was invalid
+ */
+gboolean
+nm_setting_connection_get_permission (NMSettingConnection *setting,
+ guint32 idx,
+ const char **out_ptype,
+ const char **out_pitem,
+ const char **out_detail)
+{
+ NMSettingConnectionPrivate *priv;
+ Permission *p;
+
+ g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), FALSE);
+
+ priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
+
+ g_return_val_if_fail (idx < g_slist_length (priv->permissions), FALSE);
+
+ p = g_slist_nth_data (priv->permissions, idx);
+ if (out_ptype)
+ *out_ptype = "user";
+ if (out_pitem)
+ *out_pitem = p->item;
+ if (out_detail)
+ *out_detail = NULL;
+
+ return TRUE;
+}
+
+/**
+ * nm_setting_connection_permissions_user_allowed:
+ * @setting: the #NMSettingConnection
+ * @uname: the user name to check permissions for
+ *
+ * Checks whether the given username is allowed to view/access this connection.
+ *
+ * Returns: %TRUE if the requested user is allowed to view this connection,
+ * %FALSE if the given user is not allowed to view this connection
+ */
+gboolean
+nm_setting_connection_permissions_user_allowed (NMSettingConnection *setting,
+ const char *uname)
+{
+ NMSettingConnectionPrivate *priv;
+ GSList *iter;
+
+ g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), FALSE);
+ g_return_val_if_fail (uname != NULL, FALSE);
+ g_return_val_if_fail (*uname != '\0', FALSE);
+
+ priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
+
+ /* If no permissions, visible to all */
+ if (priv->permissions == NULL)
+ return TRUE;
+
+ /* Find the username in the permissions list */
+ for (iter = priv->permissions; iter; iter = g_slist_next (iter)) {
+ Permission *p = iter->data;
+
+ if (strcmp (uname, p->item) == 0)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * nm_setting_connection_add_permission:
+ * @setting: the #NMSettingConnection
+ * @ptype: the permission type; at this time only "user" is supported
+ * @pitem: the permission item formatted as required for @ptype
+ * @detail: (allow-none): unused at this time; must be %NULL
+ *
+ * Adds a permission to the connection's permission list. At this time, only
+ * the "user" permission type is supported, and @pitem must be a username. See
+ * #NMSettingConnection:permissions: for more details.
+ *
+ * Returns: %TRUE if the permission was unique and was successfully added to the
+ * list, %FALSE if @ptype or @pitem was invalid or it the permission was already
+ * present in the list
+ */
+gboolean
+nm_setting_connection_add_permission (NMSettingConnection *setting,
+ const char *ptype,
+ const char *pitem,
+ const char *detail)
+{
+ NMSettingConnectionPrivate *priv;
+ Permission *p;
+ GSList *iter;
+
+ g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), FALSE);
+ g_return_val_if_fail (ptype, FALSE);
+ g_return_val_if_fail (strlen (ptype) > 0, FALSE);
+ g_return_val_if_fail (detail == NULL, FALSE);
+
+ /* Only "user" for now... */
+ g_return_val_if_fail (strcmp (ptype, "user") == 0, FALSE);
+
+ priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
+
+ /* No dupes */
+ for (iter = priv->permissions; iter; iter = g_slist_next (iter)) {
+ p = iter->data;
+ if (strcmp (pitem, p->item) == 0)
+ return FALSE;
+ }
+
+ p = permission_new (pitem);
+ g_return_val_if_fail (p != NULL, FALSE);
+ priv->permissions = g_slist_append (priv->permissions, p);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_CONNECTION_PERMISSIONS);
+
+ return TRUE;
+}
+
+/**
+ * nm_setting_connection_remove_permission:
+ * @setting: the #NMSettingConnection
+ * @idx: the zero-based index of the permission to remove
+ *
+ * Removes the permission at index @idx from the connection.
+ */
+void
+nm_setting_connection_remove_permission (NMSettingConnection *setting,
+ guint32 idx)
+{
+ NMSettingConnectionPrivate *priv;
+ GSList *iter;
+
+ g_return_if_fail (NM_IS_SETTING_CONNECTION (setting));
+
+ priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
+ iter = g_slist_nth (priv->permissions, idx);
+ g_return_if_fail (iter != NULL);
+
+ permission_free ((Permission *) iter->data);
+ priv->permissions = g_slist_delete_link (priv->permissions, iter);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_CONNECTION_PERMISSIONS);
+}
+
+/**
+ * nm_setting_connection_remove_permission_by_value:
+ * @setting: the #NMSettingConnection
+ * @ptype: the permission type; at this time only "user" is supported
+ * @pitem: the permission item formatted as required for @ptype
+ * @detail: (allow-none): unused at this time; must be %NULL
+ *
+ * Removes the permission from the connection.
+ * At this time, only the "user" permission type is supported, and @pitem must
+ * be a username. See #NMSettingConnection:permissions: for more details.
+ *
+ * Returns: %TRUE if the permission was found and removed; %FALSE if it was not.
+ */
+gboolean
+nm_setting_connection_remove_permission_by_value (NMSettingConnection *setting,
+ const char *ptype,
+ const char *pitem,
+ const char *detail)
+{
+ NMSettingConnectionPrivate *priv;
+ Permission *p;
+ GSList *iter;
+
+ g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), FALSE);
+ g_return_val_if_fail (ptype, FALSE);
+ g_return_val_if_fail (strlen (ptype) > 0, FALSE);
+ g_return_val_if_fail (detail == NULL, FALSE);
+
+ /* Only "user" for now... */
+ g_return_val_if_fail (strcmp (ptype, "user") == 0, FALSE);
+
+ priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
+ for (iter = priv->permissions; iter; iter = g_slist_next (iter)) {
+ p = iter->data;
+ if (strcmp (pitem, p->item) == 0) {
+ permission_free ((Permission *) iter->data);
+ priv->permissions = g_slist_delete_link (priv->permissions, iter);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_CONNECTION_PERMISSIONS);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * nm_setting_connection_get_autoconnect:
+ * @setting: the #NMSettingConnection
+ *
+ * Returns the #NMSettingConnection:autoconnect property of the connection.
+ *
+ * Returns: the connection's autoconnect behavior
+ **/
+gboolean
+nm_setting_connection_get_autoconnect (NMSettingConnection *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), FALSE);
+
+ return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->autoconnect;
+}
+
+/**
+ * nm_setting_connection_get_autoconnect_priority:
+ * @setting: the #NMSettingConnection
+ *
+ * Returns the #NMSettingConnection:autoconnect-priority property of the connection.
+ * The higher number, the higher priority.
+ *
+ * Returns: the connection's autoconnect priority
+ **/
+gint
+nm_setting_connection_get_autoconnect_priority (NMSettingConnection *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), 0);
+
+ return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->autoconnect_priority;
+}
+
+/**
+ * nm_setting_connection_get_timestamp:
+ * @setting: the #NMSettingConnection
+ *
+ * Returns the #NMSettingConnection:timestamp property of the connection.
+ *
+ * Returns: the connection's timestamp
+ **/
+guint64
+nm_setting_connection_get_timestamp (NMSettingConnection *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), 0);
+
+ return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->timestamp;
+}
+
+/**
+ * nm_setting_connection_get_read_only:
+ * @setting: the #NMSettingConnection
+ *
+ * Returns the #NMSettingConnection:read-only property of the connection.
+ *
+ * Returns: %TRUE if the connection is read-only, %FALSE if it is not
+ **/
+gboolean
+nm_setting_connection_get_read_only (NMSettingConnection *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), TRUE);
+
+ return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->read_only;
+}
+
+/**
+ * nm_setting_connection_get_zone:
+ * @setting: the #NMSettingConnection
+ *
+ * Returns the #NMSettingConnection:zone property of the connection.
+ *
+ * Returns: the trust level of a connection
+ **/
+const char *
+nm_setting_connection_get_zone (NMSettingConnection *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), NULL);
+
+ return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->zone;
+}
+
+/**
+ * nm_setting_connection_get_master:
+ * @setting: the #NMSettingConnection
+ *
+ * Returns the #NMSettingConnection:master property of the connection.
+ *
+ * Returns: interface name of the master device or UUID of the master
+ * connection.
+ */
+const char *
+nm_setting_connection_get_master (NMSettingConnection *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), NULL);
+
+ return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->master;
+}
+
+/**
+ * nm_setting_connection_get_slave_type:
+ * @setting: the #NMSettingConnection
+ *
+ * Returns the #NMSettingConnection:slave-type property of the connection.
+ *
+ * Returns: the type of slave this connection is, if any
+ */
+const char *
+nm_setting_connection_get_slave_type (NMSettingConnection *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), NULL);
+
+ return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->slave_type;
+}
+
+/**
+ * nm_setting_connection_is_slave_type:
+ * @setting: the #NMSettingConnection
+ * @type: the setting name (ie #NM_SETTING_BOND_SETTING_NAME) to be matched
+ * against @setting's slave type
+ *
+ * Returns: %TRUE if connection is of the given slave @type
+ */
+gboolean
+nm_setting_connection_is_slave_type (NMSettingConnection *setting,
+ const char *type)
+{
+ g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), FALSE);
+
+ return !g_strcmp0 (NM_SETTING_CONNECTION_GET_PRIVATE (setting)->slave_type, type);
+}
+
+/**
+ * nm_setting_connection_get_num_secondaries:
+ * @setting: the #NMSettingConnection
+ *
+ * Returns: the number of configured secondary connection UUIDs
+ **/
+guint32
+nm_setting_connection_get_num_secondaries (NMSettingConnection *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), 0);
+
+ return g_slist_length (NM_SETTING_CONNECTION_GET_PRIVATE (setting)->secondaries);
+}
+
+/**
+ * nm_setting_connection_get_secondary:
+ * @setting: the #NMSettingConnection
+ * @idx: the zero-based index of the secondary connection UUID entry
+ *
+ * Returns: the secondary connection UUID at index @idx
+ **/
+const char *
+nm_setting_connection_get_secondary (NMSettingConnection *setting, guint32 idx)
+{
+ NMSettingConnectionPrivate *priv;
+
+ g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), NULL);
+
+ priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
+ g_return_val_if_fail (idx <= g_slist_length (priv->secondaries), NULL);
+
+ return (const char *) g_slist_nth_data (priv->secondaries, idx);
+}
+
+/**
+ * nm_setting_connection_add_secondary:
+ * @setting: the #NMSettingConnection
+ * @sec_uuid: the secondary connection UUID to add
+ *
+ * Adds a new secondary connetion UUID to the setting.
+ *
+ * Returns: %TRUE if the secondary connection UUID was added; %FALSE if the UUID
+ * was already present
+ **/
+gboolean
+nm_setting_connection_add_secondary (NMSettingConnection *setting,
+ const char *sec_uuid)
+{
+ NMSettingConnectionPrivate *priv;
+ GSList *iter;
+
+ g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), FALSE);
+ g_return_val_if_fail (sec_uuid != NULL, FALSE);
+ g_return_val_if_fail (sec_uuid[0] != '\0', FALSE);
+
+ priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
+ for (iter = priv->secondaries; iter; iter = g_slist_next (iter)) {
+ if (!strcmp (sec_uuid, (char *) iter->data))
+ return FALSE;
+ }
+
+ priv->secondaries = g_slist_append (priv->secondaries, g_strdup (sec_uuid));
+ g_object_notify (G_OBJECT (setting), NM_SETTING_CONNECTION_SECONDARIES);
+ return TRUE;
+}
+
+/**
+ * nm_setting_connection_remove_secondary:
+ * @setting: the #NMSettingConnection
+ * @idx: index number of the secondary connection UUID
+ *
+ * Removes the secondary coonnection UUID at index @idx.
+ **/
+void
+nm_setting_connection_remove_secondary (NMSettingConnection *setting, guint32 idx)
+{
+ NMSettingConnectionPrivate *priv;
+ GSList *elt;
+
+ g_return_if_fail (NM_IS_SETTING_CONNECTION (setting));
+
+ priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
+ elt = g_slist_nth (priv->secondaries, idx);
+ g_return_if_fail (elt != NULL);
+
+ g_free (elt->data);
+ priv->secondaries = g_slist_delete_link (priv->secondaries, elt);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_CONNECTION_SECONDARIES);
+}
+
+/**
+ * nm_setting_connection_remove_secondary_by_value:
+ * @setting: the #NMSettingConnection
+ * @sec_uuid: the secondary connection UUID to remove
+ *
+ * Removes the secondary coonnection UUID @sec_uuid.
+ *
+ * Returns: %TRUE if the secondary connection UUID was found and removed; %FALSE if it was not.
+ **/
+gboolean
+nm_setting_connection_remove_secondary_by_value (NMSettingConnection *setting,
+ const char *sec_uuid)
+{
+ NMSettingConnectionPrivate *priv;
+ GSList *iter;
+
+ g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), FALSE);
+ g_return_val_if_fail (sec_uuid != NULL, FALSE);
+ g_return_val_if_fail (sec_uuid[0] != '\0', FALSE);
+
+ priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
+ for (iter = priv->secondaries; iter; iter = g_slist_next (iter)) {
+ if (!strcmp (sec_uuid, (char *) iter->data)) {
+ priv->secondaries = g_slist_delete_link (priv->secondaries, iter);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_CONNECTION_SECONDARIES);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * nm_setting_connection_get_gateway_ping_timeout:
+ * @setting: the #NMSettingConnection
+ *
+ * Returns: the value contained in the #NMSettingConnection:gateway-ping-timeout
+ * property.
+ **/
+guint32
+nm_setting_connection_get_gateway_ping_timeout (NMSettingConnection *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_CONNECTION (setting), 0);
+
+ return NM_SETTING_CONNECTION_GET_PRIVATE (setting)->gateway_ping_timeout;
+}
+
+static void
+_set_error_missing_base_setting (GError **error, const char *type)
+{
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_SETTING,
+ _("setting required for connection of type '%s'"),
+ type);
+ g_prefix_error (error, "%s: ", type);
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
+ gboolean is_slave;
+ const char *slave_setting_type = NULL;
+ NMSetting *normerr_base_type = NULL;
+ const char *normerr_slave_setting_type = NULL;
+ const char *normerr_missing_slave_type = NULL;
+ const char *normerr_missing_slave_type_port = NULL;
+ gboolean normerr_base_setting = FALSE;
+
+ if (!priv->id) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_ID);
+ return FALSE;
+ } else if (!priv->id[0]) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_ID);
+ return FALSE;
+ }
+
+ if (priv->uuid && !nm_utils_is_uuid (priv->uuid)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid UUID"),
+ priv->uuid);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_UUID);
+ return FALSE;
+ }
+
+ if (priv->interface_name) {
+ if (!nm_utils_iface_valid_name (priv->interface_name)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid interface name"),
+ priv->interface_name);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME);
+ return FALSE;
+ }
+ }
+
+ if (!priv->type) {
+ if (!connection || !(normerr_base_type = _nm_connection_find_base_type_setting (connection))) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_TYPE);
+ return FALSE;
+ }
+ } else {
+ GType base_type;
+
+ if (!priv->type[0]) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_TYPE);
+ return FALSE;
+ }
+
+ base_type = nm_setting_lookup_type (priv->type);
+ if (base_type == G_TYPE_INVALID || !_nm_setting_type_is_base_type (base_type)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("connection type '%s' is not valid"),
+ priv->type);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_TYPE);
+ return FALSE;
+ }
+
+ /* Make sure the corresponding 'type' item is present */
+ if ( connection
+ && !nm_connection_get_setting_by_name (connection, priv->type)) {
+ NMSetting *s_base;
+ NMConnection *connection2;
+
+ s_base = g_object_new (base_type, NULL);
+ connection2 = nm_simple_connection_new_clone (connection);
+ nm_connection_add_setting (connection2, s_base);
+
+ normerr_base_setting = nm_setting_verify (s_base, connection2, NULL);
+
+ g_object_unref (connection2);
+
+ if (!normerr_base_setting) {
+ _set_error_missing_base_setting (error, priv->type);
+ return FALSE;
+ }
+ }
+ }
+
+ is_slave = FALSE;
+ if (priv->slave_type)
+ is_slave = _nm_setting_slave_type_is_valid (priv->slave_type, &slave_setting_type);
+
+ if (priv->slave_type && !is_slave) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("Unknown slave type '%s'"), priv->slave_type);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_SLAVE_TYPE);
+ return FALSE;
+ }
+
+ if (is_slave) {
+ if (!priv->master) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("Slave connections need a valid '%s' property"), NM_SETTING_CONNECTION_MASTER);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_MASTER);
+ return FALSE;
+ }
+ if ( slave_setting_type
+ && connection
+ && !nm_connection_get_setting_by_name (connection, slave_setting_type))
+ normerr_slave_setting_type = slave_setting_type;
+ } else {
+ if (priv->master) {
+ const char *slave_type;
+ NMSetting *s_port;
+
+ if ( connection
+ && (slave_type = _nm_connection_detect_slave_type (connection, &s_port))) {
+ normerr_missing_slave_type = slave_type;
+ normerr_missing_slave_type_port = nm_setting_get_name (s_port);
+ } else {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("Cannot set '%s' without '%s'"),
+ NM_SETTING_CONNECTION_MASTER, NM_SETTING_CONNECTION_SLAVE_TYPE);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_SLAVE_TYPE);
+ return FALSE;
+ }
+ }
+ }
+
+ /* *** errors above here should be always fatal, below NORMALIZABLE_ERROR *** */
+
+ if (!priv->uuid) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_UUID);
+ return NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
+ }
+
+ if (normerr_base_type) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property type should be set to '%s'"),
+ nm_setting_get_name (normerr_base_type));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_TYPE);
+ return NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
+ }
+
+ if (normerr_base_setting) {
+ _set_error_missing_base_setting (error, priv->type);
+ return NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
+ }
+
+ if (normerr_slave_setting_type) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_SETTING,
+ _("slave-type '%s' requires a '%s' setting in the connection"),
+ priv->slave_type, normerr_slave_setting_type);
+ g_prefix_error (error, "%s: ", normerr_slave_setting_type);
+ return NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
+ }
+
+ if (normerr_missing_slave_type) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("Detect a slave connection with '%s' set and a port type '%s'. '%s' should be set to '%s'"),
+ NM_SETTING_CONNECTION_MASTER, normerr_missing_slave_type_port,
+ NM_SETTING_CONNECTION_SLAVE_TYPE, normerr_missing_slave_type);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_SLAVE_TYPE);
+ return NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
+ }
+
+ return TRUE;
+}
+
+static const char *
+find_virtual_interface_name (GVariant *connection_dict)
+{
+ GVariant *setting_dict;
+ const char *interface_name;
+
+ setting_dict = g_variant_lookup_value (connection_dict, NM_SETTING_BOND_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
+ if (!setting_dict)
+ setting_dict = g_variant_lookup_value (connection_dict, NM_SETTING_BRIDGE_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
+ if (!setting_dict)
+ setting_dict = g_variant_lookup_value (connection_dict, NM_SETTING_TEAM_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
+ if (!setting_dict)
+ setting_dict = g_variant_lookup_value (connection_dict, NM_SETTING_VLAN_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
+
+ if (!setting_dict)
+ return NULL;
+
+ /* All of the deprecated virtual interface name properties were named "interface-name". */
+ if (!g_variant_lookup (setting_dict, "interface-name", "&s", &interface_name))
+ return NULL;
+
+ return interface_name;
+}
+
+static void
+nm_setting_connection_set_interface_name (NMSetting *setting,
+ GVariant *connection_dict,
+ const char *property,
+ GVariant *value)
+{
+ const char *interface_name;
+
+ /* For compatibility reasons, if there is an invalid virtual interface name,
+ * we need to make verification fail, even if that virtual name would be
+ * overridden by a valid connection.interface-name.
+ */
+ interface_name = find_virtual_interface_name (connection_dict);
+ if (!interface_name || nm_utils_iface_valid_name (interface_name))
+ interface_name = g_variant_get_string (value, NULL);
+
+ g_object_set (G_OBJECT (setting),
+ NM_SETTING_CONNECTION_INTERFACE_NAME, interface_name,
+ NULL);
+}
+
+static void
+nm_setting_connection_no_interface_name (NMSetting *setting,
+ GVariant *connection_dict,
+ const char *property)
+{
+ const char *virtual_interface_name;
+
+ virtual_interface_name = find_virtual_interface_name (connection_dict);
+ g_object_set (G_OBJECT (setting),
+ NM_SETTING_CONNECTION_INTERFACE_NAME, virtual_interface_name,
+ NULL);
+}
+
+static gboolean
+compare_property (NMSetting *setting,
+ NMSetting *other,
+ const GParamSpec *prop_spec,
+ NMSettingCompareFlags flags)
+{
+ /* Handle ignore ID */
+ if ( (flags & NM_SETTING_COMPARE_FLAG_IGNORE_ID)
+ && g_strcmp0 (prop_spec->name, NM_SETTING_CONNECTION_ID) == 0)
+ return TRUE;
+
+ /* Handle ignore timestamp */
+ if ( (flags & NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP)
+ && 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);
+}
+
+static void
+nm_setting_connection_init (NMSettingConnection *setting)
+{
+}
+
+static void
+finalize (GObject *object)
+{
+ NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE (object);
+
+ g_free (priv->id);
+ g_free (priv->uuid);
+ g_free (priv->interface_name);
+ g_free (priv->type);
+ g_free (priv->zone);
+ g_free (priv->master);
+ g_free (priv->slave_type);
+ g_slist_free_full (priv->permissions, (GDestroyNotify) permission_free);
+ g_slist_free_full (priv->secondaries, g_free);
+
+ G_OBJECT_CLASS (nm_setting_connection_parent_class)->finalize (object);
+}
+
+static GSList *
+perm_strv_to_permlist (char **strv)
+{
+ GSList *list = NULL;
+ int i;
+
+ if (!strv)
+ return NULL;
+
+ for (i = 0; strv[i]; i++) {
+ Permission *p;
+
+ p = permission_new_from_str (strv[i]);
+ if (p)
+ list = g_slist_append (list, p);
+ }
+
+ return list;
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_ID:
+ g_free (priv->id);
+ priv->id = g_value_dup_string (value);
+ break;
+ case PROP_UUID:
+ g_free (priv->uuid);
+ priv->uuid = g_value_dup_string (value);
+ break;
+ case PROP_INTERFACE_NAME:
+ g_free (priv->interface_name);
+ priv->interface_name = g_value_dup_string (value);
+ break;
+ case PROP_TYPE:
+ g_free (priv->type);
+ priv->type = g_value_dup_string (value);
+ break;
+ case PROP_PERMISSIONS:
+ g_slist_free_full (priv->permissions, (GDestroyNotify) permission_free);
+ priv->permissions = perm_strv_to_permlist (g_value_get_boxed (value));
+ break;
+ case PROP_AUTOCONNECT:
+ priv->autoconnect = g_value_get_boolean (value);
+ break;
+ case PROP_AUTOCONNECT_PRIORITY:
+ priv->autoconnect_priority = g_value_get_int (value);
+ break;
+ case PROP_TIMESTAMP:
+ priv->timestamp = g_value_get_uint64 (value);
+ break;
+ case PROP_READ_ONLY:
+ priv->read_only = g_value_get_boolean (value);
+ break;
+ case PROP_ZONE:
+ g_free (priv->zone);
+ priv->zone = g_value_dup_string (value);
+ break;
+ case PROP_MASTER:
+ g_free (priv->master);
+ priv->master = g_value_dup_string (value);
+ break;
+ case PROP_SLAVE_TYPE:
+ g_free (priv->slave_type);
+ priv->slave_type = g_value_dup_string (value);
+ break;
+ case PROP_SECONDARIES:
+ g_slist_free_full (priv->secondaries, g_free);
+ priv->secondaries = _nm_utils_strv_to_slist (g_value_get_boxed (value));
+ break;
+ case PROP_GATEWAY_PING_TIMEOUT:
+ priv->gateway_ping_timeout = g_value_get_uint (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static char **
+perm_permlist_to_strv (GSList *permlist)
+{
+ GPtrArray *strings;
+ GSList *iter;
+
+ strings = g_ptr_array_new ();
+ for (iter = permlist; iter; iter = g_slist_next (iter))
+ g_ptr_array_add (strings, permission_to_string ((Permission *) iter->data));
+ g_ptr_array_add (strings, NULL);
+
+ return (char **) g_ptr_array_free (strings, FALSE);
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ NMSettingConnection *setting = NM_SETTING_CONNECTION (object);
+ NMSettingConnectionPrivate *priv = NM_SETTING_CONNECTION_GET_PRIVATE (setting);
+
+ switch (prop_id) {
+ case PROP_ID:
+ g_value_set_string (value, nm_setting_connection_get_id (setting));
+ break;
+ case PROP_UUID:
+ g_value_set_string (value, nm_setting_connection_get_uuid (setting));
+ break;
+ case PROP_INTERFACE_NAME:
+ g_value_set_string (value, nm_setting_connection_get_interface_name (setting));
+ break;
+ case PROP_TYPE:
+ g_value_set_string (value, nm_setting_connection_get_connection_type (setting));
+ break;
+ case PROP_PERMISSIONS:
+ g_value_take_boxed (value, perm_permlist_to_strv (priv->permissions));
+ break;
+ case PROP_AUTOCONNECT:
+ g_value_set_boolean (value, nm_setting_connection_get_autoconnect (setting));
+ break;
+ case PROP_AUTOCONNECT_PRIORITY:
+ g_value_set_int (value, nm_setting_connection_get_autoconnect_priority (setting));
+ break;
+ case PROP_TIMESTAMP:
+ g_value_set_uint64 (value, nm_setting_connection_get_timestamp (setting));
+ break;
+ case PROP_READ_ONLY:
+ g_value_set_boolean (value, nm_setting_connection_get_read_only (setting));
+ break;
+ case PROP_ZONE:
+ g_value_set_string (value, nm_setting_connection_get_zone (setting));
+ break;
+ case PROP_MASTER:
+ g_value_set_string (value, nm_setting_connection_get_master (setting));
+ break;
+ case PROP_SLAVE_TYPE:
+ g_value_set_string (value, nm_setting_connection_get_slave_type (setting));
+ break;
+ case PROP_SECONDARIES:
+ g_value_take_boxed (value, _nm_utils_slist_to_strv (priv->secondaries));
+ break;
+ case PROP_GATEWAY_PING_TIMEOUT:
+ g_value_set_uint (value, priv->gateway_ping_timeout);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+ NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+ g_type_class_add_private (setting_class, 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 */
+
+ /**
+ * NMSettingConnection:id:
+ *
+ * A human readable unique identifier for the connection, like "Work Wi-Fi"
+ * or "T-Mobile 3G".
+ **/
+ /* ---ifcfg-rh---
+ * property: id
+ * variable: NAME(+)
+ * description: User friendly name for the connection profile.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_ID,
+ g_param_spec_string (NM_SETTING_CONNECTION_ID, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingConnection:uuid:
+ *
+ * A universally unique identifier for the connection, for example generated
+ * with libuuid. It should be assigned when the connection is created, and
+ * never changed as long as the connection still applies to the same
+ * network. For example, it should not be changed when the
+ * #NMSettingConnection:id property or #NMSettingIP4Config changes, but
+ * might need to be re-created when the Wi-Fi SSID, mobile broadband network
+ * provider, or #NMSettingConnection:type property changes.
+ *
+ * The UUID must be in the format "2815492f-7e56-435e-b2e9-246bd7cdc664"
+ * (ie, contains only hexadecimal characters and "-"). A suitable UUID may
+ * be generated by nm_utils_uuid_generate() or
+ * nm_utils_uuid_generate_from_string().
+ **/
+ /* ---ifcfg-rh---
+ * property: uuid
+ * variable: UUID(+)
+ * description: UUID for the connection profile. When missing, NetworkManager
+ * creates the UUID itself (by hashing the file).
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_UUID,
+ g_param_spec_string (NM_SETTING_CONNECTION_UUID, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingConnection:interface-name:
+ *
+ * The name of the network interface this connection is bound to. If not
+ * set, then the connection can be attached to any interface of the
+ * appropriate type (subject to restrictions imposed by other settings).
+ *
+ * For software devices this specifies the name of the created device.
+ *
+ * For connection types where interface names cannot easily be made
+ * persistent (e.g. mobile broadband or USB Ethernet), this property should
+ * not be used. Setting this property restricts the interfaces a connection
+ * can be used with, and if interface names change or are reordered the
+ * connection may be applied to the wrong interface.
+ **/
+ /* ---ifcfg-rh---
+ * property: interface-name
+ * variable: DEVICE
+ * description: Interface name of the device this profile is bound to. The variable
+ * can be left out when the profile should apply for more devices. Note that DEVICE
+ * can be required for some connection types.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_INTERFACE_NAME,
+ g_param_spec_string (NM_SETTING_CONNECTION_INTERFACE_NAME, "", "",
+ NULL,
+ 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);
+
+ /**
+ * NMSettingConnection:type:
+ *
+ * Base type of the connection. For hardware-dependent connections, should
+ * contain the setting name of the hardware-type specific setting (ie,
+ * "802-3-ethernet" or "802-11-wireless" or "bluetooth", etc), and for
+ * non-hardware dependent connections like VPN or otherwise, should contain
+ * the setting name of that setting type (ie, "vpn" or "bridge", etc).
+ **/
+ /* ---ifcfg-rh---
+ * property: type
+ * variable: TYPE (DEVICETYPE, DEVICE)
+ * values: Ethernet, Wireless, InfiniBand, Bridge, Bond, Vlan, Team, TeamPort
+ * description: Base type of the connection. DEVICETYPE is used for teaming
+ * connections.
+ * example: TYPE=Ethernet; TYPE=Bond; TYPE=Bridge; DEVICETYPE=TeamPort
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_TYPE,
+ g_param_spec_string (NM_SETTING_CONNECTION_TYPE, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingConnection:permissions:
+ *
+ * An array of strings defining what access a given user has to this
+ * connection. If this is %NULL or empty, all users are allowed to access
+ * this connection. Otherwise a user is allowed to access this connection
+ * if and only if they are in this list. Each entry is of the form
+ * "[type]:[id]:[reserved]"; for example, "user:dcbw:blah".
+ *
+ * At this time only the "user" [type] is allowed. Any other values are
+ * ignored and reserved for future use. [id] is the username that this
+ * permission refers to, which may not contain the ":" character. Any
+ * [reserved] information present must be ignored and is reserved for future
+ * use. All of [type], [id], and [reserved] must be valid UTF-8.
+ */
+ /* ---ifcfg-rh---
+ * property: permissions
+ * variable: USERS(+)
+ * description: USERS restrict the access for this conenction to certain
+ * users only.
+ * example: USERS="joe bob"
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_PERMISSIONS,
+ g_param_spec_boxed (NM_SETTING_CONNECTION_PERMISSIONS, "", "",
+ G_TYPE_STRV,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingConnection:autoconnect:
+ *
+ * Whether or not the connection should be automatically connected by
+ * NetworkManager when the resources for the connection are available.
+ * %TRUE to automatically activate the connection, %FALSE to require manual
+ * intervention to activate the connection.
+ **/
+ /* ---ifcfg-rh---
+ * property: autoconnect
+ * variable: ONBOOT
+ * default: yes
+ * description: Whether the connection should be autoconnected (not only while booting).
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_AUTOCONNECT,
+ g_param_spec_boolean (NM_SETTING_CONNECTION_AUTOCONNECT, "", "",
+ TRUE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingConnection:autoconnect-priority:
+ *
+ * The autoconnect priority. If the connection is set to autoconnect,
+ * connections with higher priority will be preferred. Defaults to 0.
+ * The higher number means higher priority.
+ **/
+ /* ---ifcfg-rh---
+ * property: autoconnect-priority
+ * variable: AUTOCONNECT_PRIORITY(+)
+ * values: -999 to 999
+ * default: 0
+ * description: Connection priority for automatic activation. Connections with
+ * higher numbers are preferred when selecting profiles for automatic activation.
+ * example: AUTOCONNECT_PRIORITY=20
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_AUTOCONNECT_PRIORITY,
+ g_param_spec_int (NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, "", "",
+ NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MIN,
+ NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MAX,
+ NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_DEFAULT,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingConnection:timestamp:
+ *
+ * The time, in seconds since the Unix Epoch, that the connection was last
+ * _successfully_ fully activated.
+ *
+ * NetworkManager updates the connection timestamp periodically when the
+ * connection is active to ensure that an active connection has the latest
+ * timestamp. The property is only meant for reading (changes to this
+ * property will not be preserved).
+ **/
+ g_object_class_install_property
+ (object_class, PROP_TIMESTAMP,
+ g_param_spec_uint64 (NM_SETTING_CONNECTION_TIMESTAMP, "", "",
+ 0, G_MAXUINT64, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingConnection:read-only:
+ *
+ * %FALSE if the connection can be modified using the provided settings
+ * service's D-Bus interface with the right privileges, or %TRUE if the
+ * connection is read-only and cannot be modified.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_READ_ONLY,
+ g_param_spec_boolean (NM_SETTING_CONNECTION_READ_ONLY, "", "",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingConnection:zone:
+ *
+ * The trust level of a the connection. Free form case-insensitive string
+ * (for example "Home", "Work", "Public"). %NULL or unspecified zone means
+ * the connection will be placed in the default zone as defined by the
+ * firewall.
+ **/
+ /* ---ifcfg-rh---
+ * property: zone
+ * variable: ZONE(+)
+ * description: Trust level of this connection. The string is usually used
+ * for a firewall.
+ * example: ZONE=Work
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_ZONE,
+ g_param_spec_string (NM_SETTING_CONNECTION_ZONE, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingConnection:master:
+ *
+ * Interface name of the master device or UUID of the master connection.
+ **/
+ /* ---ifcfg-rh---
+ * property: master
+ * variable: MASTER, TEAM_MASTER, BRIDGE
+ * description: Reference to master connection. The variable used depends on
+ * the connection type.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_MASTER,
+ g_param_spec_string (NM_SETTING_CONNECTION_MASTER, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingConnection:slave-type:
+ *
+ * Setting name of the device type of this slave's master connection (eg,
+ * %NM_SETTING_BOND_SETTING_NAME), or %NULL if this connection is not a
+ * slave.
+ **/
+ /* ---ifcfg-rh---
+ * property: slave-type
+ * variable: MASTER, TEAM_MASTER, DEVICETYPE, BRIDGE
+ * description: Slave type doesn't map directly to a variable, but it is
+ * recognized using different variables. MASTER for bonding,
+ * TEAM_MASTER and DEVICETYPE for teaming, BRIDGE for bridging.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_SLAVE_TYPE,
+ g_param_spec_string (NM_SETTING_CONNECTION_SLAVE_TYPE, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingConnection:secondaries:
+ *
+ * List of connection UUIDs that should be activated when the base
+ * connection itself is activated. Currently only VPN connections are
+ * supported.
+ **/
+ /* ---ifcfg-rh---
+ * property: secondaries
+ * variable: SECONDARY_UUIDS(+)
+ * description: UUID of VPN connections that should be activated
+ * together with this connection.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_SECONDARIES,
+ g_param_spec_boxed (NM_SETTING_CONNECTION_SECONDARIES, "", "",
+ G_TYPE_STRV,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingConnection:gateway-ping-timeout:
+ *
+ * If greater than zero, delay success of IP addressing until either the
+ * timeout is reached, or an IP gateway replies to a ping.
+ **/
+ /* ---ifcfg-rh---
+ * property: gateway-ping-timeout
+ * variable: GATEWAY_PING_TIMEOUT(+)
+ * default: 0
+ * description: If greater than zero, the IP connectivity will be checked by
+ * pinging the gateway and waiting for the specified timeout (in seconds).
+ * example: GATEWAY_PING_TIMEOUT=5
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_GATEWAY_PING_TIMEOUT,
+ g_param_spec_uint (NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, "", "",
+ 0, 30, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+}
diff --git a/libnm-core/nm-setting-connection.h b/libnm-core/nm-setting-connection.h
new file mode 100644
index 000000000..d1ad0fe1e
--- /dev/null
+++ b/libnm-core/nm-setting-connection.h
@@ -0,0 +1,125 @@
+/* -*- 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 2007 - 2014 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#ifndef __NM_SETTING_CONNECTION_H__
+#define __NM_SETTING_CONNECTION_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_CONNECTION (nm_setting_connection_get_type ())
+#define NM_SETTING_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_CONNECTION, NMSettingConnection))
+#define NM_SETTING_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_CONNECTION, NMSettingConnectionClass))
+#define NM_IS_SETTING_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_CONNECTION))
+#define NM_IS_SETTING_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_CONNECTION))
+#define NM_SETTING_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_CONNECTION, NMSettingConnectionClass))
+
+#define NM_SETTING_CONNECTION_SETTING_NAME "connection"
+
+#define NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MIN -999
+#define NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_MAX 999
+#define NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY_DEFAULT 0
+
+#define NM_SETTING_CONNECTION_ID "id"
+#define NM_SETTING_CONNECTION_UUID "uuid"
+#define NM_SETTING_CONNECTION_INTERFACE_NAME "interface-name"
+#define NM_SETTING_CONNECTION_TYPE "type"
+#define NM_SETTING_CONNECTION_AUTOCONNECT "autoconnect"
+#define NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY "autoconnect-priority"
+#define NM_SETTING_CONNECTION_TIMESTAMP "timestamp"
+#define NM_SETTING_CONNECTION_READ_ONLY "read-only"
+#define NM_SETTING_CONNECTION_PERMISSIONS "permissions"
+#define NM_SETTING_CONNECTION_ZONE "zone"
+#define NM_SETTING_CONNECTION_MASTER "master"
+#define NM_SETTING_CONNECTION_SLAVE_TYPE "slave-type"
+#define NM_SETTING_CONNECTION_SECONDARIES "secondaries"
+#define NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT "gateway-ping-timeout"
+
+/**
+ * NMSettingConnection:
+ *
+ * The NMSettingConnection struct contains only private data.
+ * It should only be accessed through the functions described below.
+ */
+struct _NMSettingConnection {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingConnectionClass;
+
+GType nm_setting_connection_get_type (void);
+
+NMSetting * nm_setting_connection_new (void);
+const char *nm_setting_connection_get_id (NMSettingConnection *setting);
+const char *nm_setting_connection_get_uuid (NMSettingConnection *setting);
+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);
+guint64 nm_setting_connection_get_timestamp (NMSettingConnection *setting);
+gboolean nm_setting_connection_get_read_only (NMSettingConnection *setting);
+
+guint32 nm_setting_connection_get_num_permissions (NMSettingConnection *setting);
+gboolean nm_setting_connection_get_permission (NMSettingConnection *setting,
+ guint32 idx,
+ const char **out_ptype,
+ const char **out_pitem,
+ const char **out_detail);
+const char *nm_setting_connection_get_zone (NMSettingConnection *setting);
+gboolean nm_setting_connection_permissions_user_allowed (NMSettingConnection *setting, const char *uname);
+gboolean nm_setting_connection_add_permission (NMSettingConnection *setting,
+ const char *ptype,
+ const char *pitem,
+ const char *detail);
+void nm_setting_connection_remove_permission (NMSettingConnection *setting,
+ guint32 idx);
+gboolean nm_setting_connection_remove_permission_by_value (NMSettingConnection *setting,
+ const char *ptype,
+ const char *pitem,
+ const char *detail);
+
+const char *nm_setting_connection_get_master (NMSettingConnection *setting);
+gboolean nm_setting_connection_is_slave_type (NMSettingConnection *setting,
+ const char *type);
+const char *nm_setting_connection_get_slave_type (NMSettingConnection *setting);
+
+guint32 nm_setting_connection_get_num_secondaries (NMSettingConnection *setting);
+const char *nm_setting_connection_get_secondary (NMSettingConnection *setting, guint32 idx);
+gboolean nm_setting_connection_add_secondary (NMSettingConnection *setting, const char *sec_uuid);
+void nm_setting_connection_remove_secondary (NMSettingConnection *setting, guint32 idx);
+gboolean nm_setting_connection_remove_secondary_by_value (NMSettingConnection *setting, const char *sec_uuid);
+
+guint32 nm_setting_connection_get_gateway_ping_timeout (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
new file mode 100644
index 000000000..a4fa00c84
--- /dev/null
+++ b/libnm-core/nm-setting-dcb.c
@@ -0,0 +1,1280 @@
+/* -*- 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 2013 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-dcb.h"
+#include "nm-utils.h"
+#include "nm-utils-private.h"
+#include "nm-setting-private.h"
+#include "nm-core-enum-types.h"
+
+/**
+ * SECTION:nm-setting-dcb
+ * @short_description: Connection properties for Data Center Bridging
+ *
+ * The #NMSettingDcb object is a #NMSetting subclass that describes properties
+ * for enabling and using Data Center Bridging (DCB) on Ethernet networks.
+ * DCB is a set of protocols (including 802.1Qbb, 802.1Qaz, 802.1Qau, and
+ * 802.1AB) to eliminate packet loss in Ethernet networks and support the use
+ * 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, 2))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_DCB)
+
+#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;
+ const char * app_fcoe_mode;
+
+ NMSettingDcbFlags app_iscsi_flags;
+ gint app_iscsi_priority;
+
+ NMSettingDcbFlags app_fip_flags;
+ gint app_fip_priority;
+
+ /* Priority Flow Control */
+ NMSettingDcbFlags pfc_flags;
+ guint pfc[8];
+
+ /* Priority Groups */
+ NMSettingDcbFlags priority_group_flags;
+ guint priority_group_id[8];
+ guint priority_group_bandwidth[8];
+ guint priority_bandwidth[8];
+ guint priority_strict[8];
+ guint priority_traffic_class[8];
+} NMSettingDcbPrivate;
+
+enum {
+ PROP_0,
+ PROP_APP_FCOE_FLAGS,
+ PROP_APP_FCOE_PRIORITY,
+ PROP_APP_FCOE_MODE,
+
+ PROP_APP_ISCSI_FLAGS,
+ PROP_APP_ISCSI_PRIORITY,
+
+ PROP_APP_FIP_FLAGS,
+ PROP_APP_FIP_PRIORITY,
+
+ PROP_PFC_FLAGS,
+ PROP_PFC,
+
+ PROP_PRIORITY_GROUP_FLAGS,
+ PROP_PRIORITY_GROUP_ID,
+ PROP_PRIORITY_GROUP_BANDWIDTH,
+ PROP_PRIORITY_BANDWIDTH,
+ PROP_PRIORITY_STRICT,
+ PROP_PRIORITY_TRAFFIC_CLASS,
+
+ LAST_PROP
+};
+
+/**
+ * nm_setting_dcb_new:
+ *
+ * Creates a new #NMSettingDcb object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingDcb object
+ **/
+NMSetting *
+nm_setting_dcb_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_DCB, NULL);
+}
+
+/**
+ * nm_setting_dcb_get_app_fcoe_flags:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:app-fcoe-flags property of the setting
+ **/
+NMSettingDcbFlags
+nm_setting_dcb_get_app_fcoe_flags (NMSettingDcb *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+
+ return NM_SETTING_DCB_GET_PRIVATE (setting)->app_fcoe_flags;
+}
+
+/**
+ * nm_setting_dcb_get_app_fcoe_priority:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:app-fcoe-priority property of the setting
+ **/
+gint
+nm_setting_dcb_get_app_fcoe_priority (NMSettingDcb *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+
+ return NM_SETTING_DCB_GET_PRIVATE (setting)->app_fcoe_priority;
+}
+
+/**
+ * nm_setting_dcb_get_app_fcoe_mode:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:app-fcoe-mode property of the setting
+ **/
+const char *
+nm_setting_dcb_get_app_fcoe_mode (NMSettingDcb *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_DCB (setting), NULL);
+
+ return NM_SETTING_DCB_GET_PRIVATE (setting)->app_fcoe_mode;
+}
+
+/**
+ * nm_setting_dcb_get_app_iscsi_flags:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:app-iscsi-flags property of the setting
+ **/
+NMSettingDcbFlags
+nm_setting_dcb_get_app_iscsi_flags (NMSettingDcb *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+
+ return NM_SETTING_DCB_GET_PRIVATE (setting)->app_iscsi_flags;
+}
+
+/**
+ * nm_setting_dcb_get_app_iscsi_priority:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:app-iscsi-priority property of the setting
+ **/
+gint
+nm_setting_dcb_get_app_iscsi_priority (NMSettingDcb *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+
+ return NM_SETTING_DCB_GET_PRIVATE (setting)->app_iscsi_priority;
+}
+
+/**
+ * nm_setting_dcb_get_app_fip_flags:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:app-fip-flags property of the setting
+ **/
+NMSettingDcbFlags
+nm_setting_dcb_get_app_fip_flags (NMSettingDcb *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+
+ return NM_SETTING_DCB_GET_PRIVATE (setting)->app_fip_flags;
+}
+
+/**
+ * nm_setting_dcb_get_app_fip_priority:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:app-fip-priority property of the setting
+ **/
+gint
+nm_setting_dcb_get_app_fip_priority (NMSettingDcb *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+
+ return NM_SETTING_DCB_GET_PRIVATE (setting)->app_fip_priority;
+}
+
+/**
+ * nm_setting_dcb_get_priority_flow_control_flags:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:priority-flow-control-flags property of the setting
+ **/
+NMSettingDcbFlags
+nm_setting_dcb_get_priority_flow_control_flags (NMSettingDcb *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+
+ return NM_SETTING_DCB_GET_PRIVATE (setting)->pfc_flags;
+}
+
+/**
+ * nm_setting_dcb_get_priority_flow_control:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to retrieve flow control for
+ *
+ * Returns: %TRUE if flow control is enabled for the given @user_priority,
+ * %FALSE if not enabled
+ **/
+gboolean
+nm_setting_dcb_get_priority_flow_control (NMSettingDcb *setting, guint user_priority)
+{
+ g_return_val_if_fail (NM_IS_SETTING_DCB (setting), FALSE);
+ g_return_val_if_fail (user_priority <= 7, FALSE);
+
+ return !!NM_SETTING_DCB_GET_PRIVATE (setting)->pfc[user_priority];
+}
+
+/**
+ * nm_setting_dcb_set_priority_flow_control:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to set flow control for
+ * @enabled: %TRUE to enable flow control for this priority, %FALSE to disable it
+ *
+ * These values are only valid when #NMSettingDcb:priority-flow-control includes
+ * the %NM_SETTING_DCB_FLAG_ENABLE flag.
+ **/
+void
+nm_setting_dcb_set_priority_flow_control (NMSettingDcb *setting,
+ guint user_priority,
+ gboolean enabled)
+{
+ NMSettingDcbPrivate *priv;
+ guint uint_enabled = enabled ? 1 : 0;
+
+ g_return_if_fail (NM_IS_SETTING_DCB (setting));
+ g_return_if_fail (user_priority <= 7);
+
+ priv = NM_SETTING_DCB_GET_PRIVATE (setting);
+ if (priv->pfc[user_priority] != uint_enabled) {
+ priv->pfc[user_priority] = uint_enabled;
+ g_object_notify (G_OBJECT (setting), NM_SETTING_DCB_PRIORITY_FLOW_CONTROL);
+ }
+}
+
+/**
+ * nm_setting_dcb_get_priority_group_flags:
+ * @setting: the #NMSettingDcb
+ *
+ * Returns: the #NMSettingDcb:priority-group-flags property of the setting
+ **/
+NMSettingDcbFlags
+nm_setting_dcb_get_priority_group_flags (NMSettingDcb *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+
+ return NM_SETTING_DCB_GET_PRIVATE (setting)->priority_group_flags;
+}
+
+/**
+ * nm_setting_dcb_get_priority_group_id:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to retrieve the group ID for
+ *
+ * Returns: the group number @user_priority is assigned to. These values are
+ * only valid when #NMSettingDcb:priority-group-flags includes the
+ * %NM_SETTING_DCB_FLAG_ENABLE flag.
+ **/
+guint
+nm_setting_dcb_get_priority_group_id (NMSettingDcb *setting, guint user_priority)
+{
+ g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+ g_return_val_if_fail (user_priority <= 7, 0);
+
+ return NM_SETTING_DCB_GET_PRIVATE (setting)->priority_group_id[user_priority];
+}
+
+/**
+ * nm_setting_dcb_set_priority_group_id:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to set flow control for
+ * @group_id: the group (0 - 7) to assign @user_priority to, or 15 for the
+ * unrestricted group.
+ *
+ * These values are only valid when #NMSettingDcb:priority-group-flags includes
+ * the %NM_SETTING_DCB_FLAG_ENABLE flag.
+ **/
+void
+nm_setting_dcb_set_priority_group_id (NMSettingDcb *setting,
+ guint user_priority,
+ guint group_id)
+{
+ NMSettingDcbPrivate *priv;
+
+ g_return_if_fail (NM_IS_SETTING_DCB (setting));
+ g_return_if_fail (user_priority <= 7);
+ g_return_if_fail (group_id <= 7 || group_id == 15);
+
+ priv = NM_SETTING_DCB_GET_PRIVATE (setting);
+ if (priv->priority_group_id[user_priority] != group_id) {
+ priv->priority_group_id[user_priority] = group_id;
+ g_object_notify (G_OBJECT (setting), NM_SETTING_DCB_PRIORITY_GROUP_ID);
+ }
+}
+
+/**
+ * nm_setting_dcb_get_priority_group_bandwidth:
+ * @setting: the #NMSettingDcb
+ * @group_id: the priority group (0 - 7) to retrieve the bandwidth percentage for
+ *
+ * Returns: the bandwidth percentage assigned to @group_id. These values are
+ * only valid when #NMSettingDcb:priority-group-flags includes the
+ * %NM_SETTING_DCB_FLAG_ENABLE flag.
+ **/
+guint
+nm_setting_dcb_get_priority_group_bandwidth (NMSettingDcb *setting, guint group_id)
+{
+ g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+ g_return_val_if_fail (group_id <= 7, FALSE);
+
+ return NM_SETTING_DCB_GET_PRIVATE (setting)->priority_group_bandwidth[group_id];
+}
+
+/**
+ * nm_setting_dcb_set_priority_group_bandwidth:
+ * @setting: the #NMSettingDcb
+ * @group_id: the priority group (0 - 7) to set the bandwidth percentage for
+ * @bandwidth_percent: the bandwidth percentage (0 - 100) to assign to @group_id to
+ *
+ * These values are only valid when #NMSettingDcb:priority-group-flags includes
+ * the %NM_SETTING_DCB_FLAG_ENABLE flag.
+ **/
+void
+nm_setting_dcb_set_priority_group_bandwidth (NMSettingDcb *setting,
+ guint group_id,
+ guint bandwidth_percent)
+{
+ NMSettingDcbPrivate *priv;
+
+ g_return_if_fail (NM_IS_SETTING_DCB (setting));
+ g_return_if_fail (group_id <= 7);
+ g_return_if_fail (bandwidth_percent <= 100);
+
+ priv = NM_SETTING_DCB_GET_PRIVATE (setting);
+ if (priv->priority_group_bandwidth[group_id] != bandwidth_percent) {
+ priv->priority_group_bandwidth[group_id] = bandwidth_percent;
+ g_object_notify (G_OBJECT (setting), NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH);
+ }
+}
+
+/**
+ * nm_setting_dcb_get_priority_bandwidth:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to retrieve the group bandwidth percentage for
+ *
+ * Returns: the allowed bandwidth percentage of @user_priority in its priority group.
+ * These values are only valid when #NMSettingDcb:priority-group-flags includes the
+ * %NM_SETTING_DCB_FLAG_ENABLE flag.
+ **/
+guint
+nm_setting_dcb_get_priority_bandwidth (NMSettingDcb *setting, guint user_priority)
+{
+ g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+ g_return_val_if_fail (user_priority <= 7, FALSE);
+
+ return NM_SETTING_DCB_GET_PRIVATE (setting)->priority_bandwidth[user_priority];
+}
+
+/**
+ * nm_setting_dcb_set_priority_bandwidth:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to set the bandwidth percentage for
+ * @bandwidth_percent: the bandwidth percentage (0 - 100) that @user_priority is
+ * allowed to use within its priority group
+ *
+ * These values are only valid when #NMSettingDcb:priority-group-flags includes
+ * the %NM_SETTING_DCB_FLAG_ENABLE flag.
+ **/
+void
+nm_setting_dcb_set_priority_bandwidth (NMSettingDcb *setting,
+ guint user_priority,
+ guint bandwidth_percent)
+{
+ NMSettingDcbPrivate *priv;
+
+ g_return_if_fail (NM_IS_SETTING_DCB (setting));
+ g_return_if_fail (user_priority <= 7);
+ g_return_if_fail (bandwidth_percent <= 100);
+
+ priv = NM_SETTING_DCB_GET_PRIVATE (setting);
+ if (priv->priority_bandwidth[user_priority] != bandwidth_percent) {
+ priv->priority_bandwidth[user_priority] = bandwidth_percent;
+ g_object_notify (G_OBJECT (setting), NM_SETTING_DCB_PRIORITY_BANDWIDTH);
+ }
+}
+
+/**
+ * nm_setting_dcb_get_priority_strict_bandwidth:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to retrieve strict bandwidth for
+ *
+ * Returns: %TRUE if @user_priority may use all of the bandwidth allocated to its
+ * assigned group, or %FALSE if not. These values are only valid when
+ * #NMSettingDcb:priority-group-flags includes the %NM_SETTING_DCB_FLAG_ENABLE flag.
+ **/
+gboolean
+nm_setting_dcb_get_priority_strict_bandwidth (NMSettingDcb *setting, guint user_priority)
+{
+ g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+ g_return_val_if_fail (user_priority <= 7, FALSE);
+
+ return !!NM_SETTING_DCB_GET_PRIVATE (setting)->priority_strict[user_priority];
+}
+
+/**
+ * nm_setting_dcb_set_priority_strict_bandwidth:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to set strict bandwidth for
+ * @strict: %TRUE to allow @user_priority to use all the bandwidth allocated to
+ * its priority group, or %FALSE if not
+ *
+ * These values are only valid when #NMSettingDcb:priority-group-flags includes
+ * the %NM_SETTING_DCB_FLAG_ENABLE flag.
+ **/
+void
+nm_setting_dcb_set_priority_strict_bandwidth (NMSettingDcb *setting,
+ guint user_priority,
+ gboolean strict)
+{
+ NMSettingDcbPrivate *priv;
+ guint uint_strict = strict ? 1 : 0;
+
+ g_return_if_fail (NM_IS_SETTING_DCB (setting));
+ g_return_if_fail (user_priority <= 7);
+
+ priv = NM_SETTING_DCB_GET_PRIVATE (setting);
+ if (priv->priority_strict[user_priority] != uint_strict) {
+ priv->priority_strict[user_priority] = uint_strict;
+ g_object_notify (G_OBJECT (setting), NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH);
+ }
+}
+
+/**
+ * nm_setting_dcb_get_priority_traffic_class:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to retrieve the traffic class for
+ *
+ * Returns: the traffic class assigned to @user_priority. These values are only
+ * valid when #NMSettingDcb:priority-group-flags includes the
+ * %NM_SETTING_DCB_FLAG_ENABLE flag.
+ **/
+guint
+nm_setting_dcb_get_priority_traffic_class (NMSettingDcb *setting, guint user_priority)
+{
+ g_return_val_if_fail (NM_IS_SETTING_DCB (setting), 0);
+ g_return_val_if_fail (user_priority <= 7, FALSE);
+
+ return NM_SETTING_DCB_GET_PRIVATE (setting)->priority_traffic_class[user_priority];
+}
+
+/**
+ * nm_setting_dcb_set_priority_traffic_clas:
+ * @setting: the #NMSettingDcb
+ * @user_priority: the User Priority (0 - 7) to set the bandwidth percentage for
+ * @traffic_class: the traffic_class (0 - 7) that @user_priority should map to
+ *
+ * These values are only valid when #NMSettingDcb:priority-group-flags includes
+ * the %NM_SETTING_DCB_FLAG_ENABLE flag.
+ **/
+void
+nm_setting_dcb_set_priority_traffic_class (NMSettingDcb *setting,
+ guint user_priority,
+ guint traffic_class)
+{
+ NMSettingDcbPrivate *priv;
+
+ g_return_if_fail (NM_IS_SETTING_DCB (setting));
+ g_return_if_fail (user_priority <= 7);
+ g_return_if_fail (traffic_class <= 7);
+
+ priv = NM_SETTING_DCB_GET_PRIVATE (setting);
+ if (priv->priority_traffic_class[user_priority] != traffic_class) {
+ priv->priority_traffic_class[user_priority] = traffic_class;
+ g_object_notify (G_OBJECT (setting), NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS);
+ }
+}
+
+/******************************************************************/
+
+#define DCB_FLAGS_ALL (NM_SETTING_DCB_FLAG_ENABLE | \
+ NM_SETTING_DCB_FLAG_ADVERTISE | \
+ NM_SETTING_DCB_FLAG_WILLING)
+
+static gboolean
+check_dcb_flags (NMSettingDcbFlags flags, const char *prop_name, GError **error)
+{
+ if (flags & ~DCB_FLAGS_ALL) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("flags invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name);
+ return FALSE;
+ }
+
+ if (!(flags & NM_SETTING_DCB_FLAG_ENABLE) && (flags & ~NM_SETTING_DCB_FLAG_ENABLE)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("flags invalid - disabled"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+check_uint_array (const guint *array,
+ guint len,
+ NMSettingDcbFlags flags,
+ guint max,
+ guint extra,
+ gboolean sum_pct,
+ const char *prop_name,
+ GError **error)
+{
+ guint i, sum = 0;
+
+ /* Ensure each element is <= to max or equals extra */
+ for (i = 0; i < len; i++) {
+ if (!(flags & NM_SETTING_DCB_FLAG_ENABLE) && array[i]) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property invalid (not enabled)"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name);
+ return FALSE;
+ }
+
+ if ((array[i] > max) && (array[i] != extra)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("element invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name);
+ return FALSE;
+ }
+ sum += array[i];
+ }
+
+ /* Verify sum of percentages */
+ if (sum_pct) {
+ if (flags & NM_SETTING_DCB_FLAG_ENABLE) {
+ /* If the feature is enabled, sum must equal 100% */
+ if (sum != 100) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("sum not 100%"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name);
+ return FALSE;
+ }
+ } else {
+ /* If the feature is disabled, sum must equal 0%, which was checked
+ * by the for() loop above.
+ */
+ g_assert_cmpint (sum, ==, 0);
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+check_priority (gint val,
+ NMSettingDcbFlags flags,
+ const char *prop_name,
+ GError **error)
+{
+ if (!(flags & NM_SETTING_DCB_FLAG_ENABLE) && (val >= 0)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property invalid (not enabled)"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name);
+ return FALSE;
+ }
+
+ if (val < -1 || val > 7) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, prop_name);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ NMSettingDcbPrivate *priv = NM_SETTING_DCB_GET_PRIVATE (setting);
+
+ if (!check_dcb_flags (priv->app_fcoe_flags, NM_SETTING_DCB_APP_FCOE_FLAGS, error))
+ return FALSE;
+
+ if (!check_priority (priv->app_fcoe_priority, priv->app_fcoe_flags, NM_SETTING_DCB_APP_FCOE_PRIORITY, error))
+ return FALSE;
+
+ if (!priv->app_fcoe_mode) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, NM_SETTING_DCB_APP_FCOE_MODE);
+ return FALSE;
+ }
+
+ if (strcmp (priv->app_fcoe_mode, NM_SETTING_DCB_FCOE_MODE_FABRIC) &&
+ strcmp (priv->app_fcoe_mode, NM_SETTING_DCB_FCOE_MODE_VN2VN)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_DCB_SETTING_NAME, NM_SETTING_DCB_APP_FCOE_MODE);
+ return FALSE;
+ }
+
+ if (!check_dcb_flags (priv->app_iscsi_flags, NM_SETTING_DCB_APP_ISCSI_FLAGS, error))
+ return FALSE;
+
+ if (!check_priority (priv->app_iscsi_priority, priv->app_iscsi_flags, NM_SETTING_DCB_APP_ISCSI_PRIORITY, error))
+ return FALSE;
+
+ if (!check_dcb_flags (priv->app_fip_flags, NM_SETTING_DCB_APP_FIP_FLAGS, error))
+ return FALSE;
+
+ if (!check_priority (priv->app_fip_priority, priv->app_fip_flags, NM_SETTING_DCB_APP_FIP_PRIORITY, error))
+ return FALSE;
+
+ if (!check_dcb_flags (priv->pfc_flags, NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, error))
+ return FALSE;
+
+ if (!check_uint_array (priv->pfc, G_N_ELEMENTS (priv->pfc), priv->pfc_flags, 1, 0, FALSE, NM_SETTING_DCB_PRIORITY_FLOW_CONTROL, error))
+ return FALSE;
+
+ if (!check_dcb_flags (priv->priority_group_flags, NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, error))
+ return FALSE;
+
+ if (!check_uint_array (priv->priority_group_id,
+ G_N_ELEMENTS (priv->priority_group_id),
+ priv->priority_group_flags,
+ 7,
+ 15,
+ FALSE,
+ NM_SETTING_DCB_PRIORITY_GROUP_ID,
+ error))
+ return FALSE;
+
+ if (!check_uint_array (priv->priority_group_bandwidth,
+ G_N_ELEMENTS (priv->priority_group_bandwidth),
+ priv->priority_group_flags,
+ 100,
+ 0,
+ TRUE,
+ NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH,
+ error))
+ return FALSE;
+
+ /* FIXME: sum bandwidths in each group */
+ if (!check_uint_array (priv->priority_bandwidth,
+ G_N_ELEMENTS (priv->priority_bandwidth),
+ priv->priority_group_flags,
+ 100,
+ 0,
+ FALSE,
+ NM_SETTING_DCB_PRIORITY_BANDWIDTH,
+ error))
+ return FALSE;
+
+ if (!check_uint_array (priv->priority_strict,
+ G_N_ELEMENTS (priv->priority_strict),
+ priv->priority_group_flags,
+ 1,
+ 0,
+ FALSE,
+ NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH,
+ error))
+ return FALSE;
+
+ if (!check_uint_array (priv->priority_traffic_class,
+ G_N_ELEMENTS (priv->priority_traffic_class),
+ priv->priority_group_flags,
+ 7,
+ 0,
+ FALSE,
+ NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS,
+ error))
+ return FALSE;
+
+ return TRUE;
+}
+
+/******************************************************************/
+
+static void
+nm_setting_dcb_init (NMSettingDcb *setting)
+{
+}
+
+G_STATIC_ASSERT (sizeof (guint) == sizeof (gboolean));
+
+static inline void
+set_array_from_gvalue (const GValue *v, uint *a, size_t len)
+{
+ GArray *src = g_value_get_boxed (v);
+ const guint total_len = len * sizeof (a[0]);
+
+ memset (a, 0, total_len);
+ if (src) {
+ g_return_if_fail (g_array_get_element_size (src) == sizeof (a[0]));
+ g_return_if_fail (src->len == len);
+ memcpy (a, src->data, total_len);
+ }
+}
+#define SET_ARRAY_FROM_GVALUE(v, a) set_array_from_gvalue (v, a, G_N_ELEMENTS (a))
+
+static inline void
+set_gvalue_from_array (GValue *v, uint *a, size_t len)
+{
+ GArray *src = g_array_sized_new (FALSE, TRUE, sizeof (guint), len);
+
+ g_array_append_vals (src, a, len);
+ g_value_take_boxed (v, src);
+}
+
+#define SET_GVALUE_FROM_ARRAY(v, a) set_gvalue_from_array (v, a, G_N_ELEMENTS (a))
+
+static GVariant *
+_nm_setting_dcb_uint_array_to_dbus (const GValue *prop_value)
+{
+ GArray *src = g_value_get_boxed (prop_value);
+
+ return g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32, src->data, src->len, sizeof (guint32));
+}
+
+static void
+_nm_setting_dcb_uint_array_from_dbus (GVariant *dbus_value,
+ GValue *prop_value)
+{
+ gconstpointer array;
+ gsize length;
+
+ array = g_variant_get_fixed_array (dbus_value, &length, sizeof (guint32));
+ set_gvalue_from_array (prop_value, (guint *) array, length);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingDcbPrivate *priv = NM_SETTING_DCB_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_APP_FCOE_FLAGS:
+ priv->app_fcoe_flags = g_value_get_flags (value);
+ break;
+ case PROP_APP_FCOE_PRIORITY:
+ priv->app_fcoe_priority = g_value_get_int (value);
+ break;
+ case PROP_APP_FCOE_MODE:
+ priv->app_fcoe_mode = g_value_dup_string (value);
+ break;
+ case PROP_APP_ISCSI_FLAGS:
+ priv->app_iscsi_flags = g_value_get_flags (value);
+ break;
+ case PROP_APP_ISCSI_PRIORITY:
+ priv->app_iscsi_priority = g_value_get_int (value);
+ break;
+ case PROP_APP_FIP_FLAGS:
+ priv->app_fip_flags = g_value_get_flags (value);
+ break;
+ case PROP_APP_FIP_PRIORITY:
+ priv->app_fip_priority = g_value_get_int (value);
+ break;
+ case PROP_PFC_FLAGS:
+ priv->pfc_flags = g_value_get_flags (value);
+ break;
+ case PROP_PFC:
+ SET_ARRAY_FROM_GVALUE (value, priv->pfc);
+ break;
+ case PROP_PRIORITY_GROUP_FLAGS:
+ priv->priority_group_flags = g_value_get_flags (value);
+ break;
+ case PROP_PRIORITY_GROUP_ID:
+ SET_ARRAY_FROM_GVALUE (value, priv->priority_group_id);
+ break;
+ case PROP_PRIORITY_GROUP_BANDWIDTH:
+ SET_ARRAY_FROM_GVALUE (value, priv->priority_group_bandwidth);
+ break;
+ case PROP_PRIORITY_BANDWIDTH:
+ SET_ARRAY_FROM_GVALUE (value, priv->priority_bandwidth);
+ break;
+ case PROP_PRIORITY_STRICT:
+ SET_ARRAY_FROM_GVALUE (value, priv->priority_strict);
+ break;
+ case PROP_PRIORITY_TRAFFIC_CLASS:
+ SET_ARRAY_FROM_GVALUE (value, priv->priority_traffic_class);
+ 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)
+{
+ NMSettingDcb *setting = NM_SETTING_DCB (object);
+ NMSettingDcbPrivate *priv = NM_SETTING_DCB_GET_PRIVATE (setting);
+
+ switch (prop_id) {
+ case PROP_APP_FCOE_FLAGS:
+ g_value_set_flags (value, priv->app_fcoe_flags);
+ break;
+ case PROP_APP_FCOE_PRIORITY:
+ g_value_set_int (value, priv->app_fcoe_priority);
+ break;
+ case PROP_APP_FCOE_MODE:
+ g_value_set_string (value, priv->app_fcoe_mode);
+ break;
+ case PROP_APP_ISCSI_FLAGS:
+ g_value_set_flags (value, priv->app_iscsi_flags);
+ break;
+ case PROP_APP_ISCSI_PRIORITY:
+ g_value_set_int (value, priv->app_iscsi_priority);
+ break;
+ case PROP_APP_FIP_FLAGS:
+ g_value_set_flags (value, priv->app_fip_flags);
+ break;
+ case PROP_APP_FIP_PRIORITY:
+ g_value_set_int (value, priv->app_fip_priority);
+ break;
+ case PROP_PFC_FLAGS:
+ g_value_set_flags (value, priv->pfc_flags);
+ break;
+ case PROP_PFC:
+ SET_GVALUE_FROM_ARRAY (value, priv->pfc);
+ break;
+ case PROP_PRIORITY_GROUP_FLAGS:
+ g_value_set_flags (value, priv->priority_group_flags);
+ break;
+ case PROP_PRIORITY_GROUP_ID:
+ SET_GVALUE_FROM_ARRAY (value, priv->priority_group_id);
+ break;
+ case PROP_PRIORITY_GROUP_BANDWIDTH:
+ SET_GVALUE_FROM_ARRAY (value, priv->priority_group_bandwidth);
+ break;
+ case PROP_PRIORITY_BANDWIDTH:
+ SET_GVALUE_FROM_ARRAY (value, priv->priority_bandwidth);
+ break;
+ case PROP_PRIORITY_STRICT:
+ SET_GVALUE_FROM_ARRAY (value, priv->priority_strict);
+ break;
+ case PROP_PRIORITY_TRAFFIC_CLASS:
+ SET_GVALUE_FROM_ARRAY (value, priv->priority_traffic_class);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_setting_dcb_class_init (NMSettingDcbClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+ NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+ g_type_class_add_private (setting_class, sizeof (NMSettingDcbPrivate));
+
+ /* virtual methods */
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+ parent_class->verify = verify;
+
+ /* Properties */
+ /**
+ * NMSettingDcb:app-fcoe-flags:
+ *
+ * Specifies the #NMSettingDcbFlags for the DCB FCoE application. Flags may
+ * be any combination of %NM_SETTING_DCB_FLAG_ENABLE,
+ * %NM_SETTING_DCB_FLAG_ADVERTISE, and %NM_SETTING_DCB_FLAG_WILLING.
+ **/
+ /* ---ifcfg-rh---
+ * property: app-fcoe-flags
+ * variable: DCB_APP_FCOE_ENABLE, DCB_APP_FCOE_ADVERTISE, DCB_APP_FCOE_WILLING
+ * description: FCOE flags.
+ * default: no
+ * example: DCB_APP_FCOE_ENABLE=yes DCB_APP_FCOE_ADVERTISE=yes
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_APP_FCOE_FLAGS,
+ g_param_spec_flags (NM_SETTING_DCB_APP_FCOE_FLAGS, "", "",
+ NM_TYPE_SETTING_DCB_FLAGS,
+ NM_SETTING_DCB_FLAG_NONE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingDcb:app-fcoe-priority:
+ *
+ * The highest User Priority (0 - 7) which FCoE frames should use, or -1 for
+ * default priority. Only used when the #NMSettingDcb:app-fcoe-flags
+ * property includes the %NM_SETTING_DCB_FLAG_ENABLE flag.
+ **/
+ /* ---ifcfg-rh---
+ * property: app-fcoe-priority
+ * variable: DCB_APP_FCOE_PRIORITY
+ * values: 0 - 7
+ * description: Priority of FCoE frames.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_APP_FCOE_PRIORITY,
+ g_param_spec_int (NM_SETTING_DCB_APP_FCOE_PRIORITY, "", "",
+ -1, 7, -1,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingDcb:app-fcoe-mode:
+ *
+ * The FCoE controller mode; either %NM_SETTING_DCB_FCOE_MODE_FABRIC
+ * (default) or %NM_SETTING_DCB_FCOE_MODE_VN2VN.
+ **/
+ /* ---ifcfg-rh---
+ * property: app-fcoe-mode
+ * variable: DCB_APP_FCOE_MODE
+ * values: fabric, vn2vn
+ * default: fabric
+ * description: FCoE controller mode.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_APP_FCOE_MODE,
+ g_param_spec_string (NM_SETTING_DCB_APP_FCOE_MODE, "", "",
+ NM_SETTING_DCB_FCOE_MODE_FABRIC,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingDcb:app-iscsi-flags:
+ *
+ * Specifies the #NMSettingDcbFlags for the DCB iSCSI application. Flags
+ * may be any combination of %NM_SETTING_DCB_FLAG_ENABLE,
+ * %NM_SETTING_DCB_FLAG_ADVERTISE, and %NM_SETTING_DCB_FLAG_WILLING.
+ **/
+ /* ---ifcfg-rh---
+ * property: app-iscsi-flags
+ * variable: DCB_APP_ISCSI_ENABLE, DCB_APP_ISCSI_ADVERTISE, DCB_APP_ISCSI_WILLING
+ * default: no
+ * description: iSCSI flags.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_APP_ISCSI_FLAGS,
+ g_param_spec_flags (NM_SETTING_DCB_APP_ISCSI_FLAGS, "", "",
+ NM_TYPE_SETTING_DCB_FLAGS,
+ NM_SETTING_DCB_FLAG_NONE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingDcb:app-iscsi-priority:
+ *
+ * The highest User Priority (0 - 7) which iSCSI frames should use, or -1
+ * for default priority. Only used when the #NMSettingDcb:app-iscsi-flags
+ * property includes the %NM_SETTING_DCB_FLAG_ENABLE flag.
+ **/
+ /* ---ifcfg-rh---
+ * property: app-iscsi-priority
+ * variable: DCB_APP_ISCSI_PRIORITY
+ * values: 0 - 7
+ * description: Priority of iSCSI frames.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_APP_ISCSI_PRIORITY,
+ g_param_spec_int (NM_SETTING_DCB_APP_ISCSI_PRIORITY, "", "",
+ -1, 7, -1,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingDcb:app-fip-flags:
+ *
+ * Specifies the #NMSettingDcbFlags for the DCB FIP application. Flags may
+ * be any combination of %NM_SETTING_DCB_FLAG_ENABLE,
+ * %NM_SETTING_DCB_FLAG_ADVERTISE, and %NM_SETTING_DCB_FLAG_WILLING.
+ **/
+ /* ---ifcfg-rh---
+ * property: app-fip-flags
+ * variable: DCB_APP_FIP_ENABLE, DCB_APP_FIP_ADVERTISE, DCB_APP_FIP_WILLING
+ * default: no
+ * description: FIP flags.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_APP_FIP_FLAGS,
+ g_param_spec_flags (NM_SETTING_DCB_APP_FIP_FLAGS, "", "",
+ NM_TYPE_SETTING_DCB_FLAGS,
+ NM_SETTING_DCB_FLAG_NONE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingDcb:app-fip-priority:
+ *
+ * The highest User Priority (0 - 7) which FIP frames should use, or -1 for
+ * default priority. Only used when the #NMSettingDcb:app-fip-flags
+ * property includes the %NM_SETTING_DCB_FLAG_ENABLE flag.
+ **/
+ /* ---ifcfg-rh---
+ * property: app-fip-priority
+ * variable: DCB_APP_FIP_PRIORITY
+ * values: 0 - 7
+ * description: Priority of FIP frames.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_APP_FIP_PRIORITY,
+ g_param_spec_int (NM_SETTING_DCB_APP_FIP_PRIORITY, "", "",
+ -1, 7, -1,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingDcb:priority-flow-control-flags:
+ *
+ * Specifies the #NMSettingDcbFlags for DCB Priority Flow Control (PFC).
+ * Flags may be any combination of %NM_SETTING_DCB_FLAG_ENABLE,
+ * %NM_SETTING_DCB_FLAG_ADVERTISE, and %NM_SETTING_DCB_FLAG_WILLING.
+ **/
+ /* ---ifcfg-rh---
+ * property: priority-flow-control-flags
+ * variable: DCB_PFC_ENABLE, DCB_PFC_ADVERTISE, DCB_PFC_WILLING
+ * default: no
+ * description: Priority flow control flags.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_PFC_FLAGS,
+ g_param_spec_flags (NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, "", "",
+ NM_TYPE_SETTING_DCB_FLAGS,
+ NM_SETTING_DCB_FLAG_NONE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingDcb:priority-flow-control:
+ *
+ * An array of 8 boolean values, where the array index corresponds to the User
+ * Priority (0 - 7) and the value indicates whether or not the corresponding
+ * priority should transmit priority pause.
+ *
+ * Element-type: gboolean
+ **/
+ /* ---ifcfg-rh---
+ * property: priority-flow-control
+ * variable: DCB_PFC_UP
+ * description: Priority flow control values. String of 8 "0" and "1", where "0".
+ * means "do not transmit priority pause", "1" means "transmit pause".
+ * example: DCB_PFC_UP=01101110
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_PFC,
+ g_param_spec_boxed (NM_SETTING_DCB_PRIORITY_FLOW_CONTROL, "", "",
+ 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);
+
+ /**
+ * NMSettingDcb:priority-group-flags:
+ *
+ * Specifies the #NMSettingDcbFlags for DCB Priority Groups. Flags may be
+ * any combination of %NM_SETTING_DCB_FLAG_ENABLE,
+ * %NM_SETTING_DCB_FLAG_ADVERTISE, and %NM_SETTING_DCB_FLAG_WILLING.
+ **/
+ /* ---ifcfg-rh---
+ * property: priority-group-flags
+ * variable: DCB_PG_ENABLE, DCB_PG_ADVERTISE, DCB_PG_WILLING
+ * default: no
+ * description: Priority groups flags.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_PRIORITY_GROUP_FLAGS,
+ g_param_spec_flags (NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, "", "",
+ NM_TYPE_SETTING_DCB_FLAGS,
+ NM_SETTING_DCB_FLAG_NONE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingDcb:priority-group-id:
+ *
+ * An array of 8 uint values, where the array index corresponds to the User
+ * Priority (0 - 7) and the value indicates the Priority Group ID. Allowed
+ * Priority Group ID values are 0 - 7 or 15 for the unrestricted group.
+ *
+ * Element-type: guint
+ **/
+ /* ---ifcfg-rh---
+ * property: priority-group-id
+ * variable: DCB_PG_ID
+ * description: Priority groups values. String of eight priorities (0 - 7) or "f"
+ * (unrestricted).
+ * example: DCB_PG_ID=1205f173
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_PRIORITY_GROUP_ID,
+ g_param_spec_boxed (NM_SETTING_DCB_PRIORITY_GROUP_ID, "", "",
+ 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);
+
+ /**
+ * NMSettingDcb:priority-group-bandwidth:
+ *
+ * An array of 8 uint values, where the array index corresponds to the
+ * Priority Group ID (0 - 7) and the value indicates the percentage of link
+ * bandwidth allocated to that group. Allowed values are 0 - 100, and the
+ * sum of all values must total 100 percent.
+ *
+ * Element-type: guint
+ **/
+ /* ---ifcfg-rh---
+ * property: priority-group-bandwidth
+ * variable: DCB_PG_PCT
+ * description: Priority groups values. Eight bandwidths (in percent), separated with commas.
+ * example: DCB_PG_PCT=10,5,10,15,10,10,10,30
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_PRIORITY_GROUP_BANDWIDTH,
+ g_param_spec_boxed (NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH, "", "",
+ 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);
+
+ /**
+ * NMSettingDcb:priority-bandwidth:
+ *
+ * An array of 8 uint values, where the array index corresponds to the User
+ * Priority (0 - 7) and the value indicates the percentage of bandwidth of
+ * the priority's assigned group that the priority may use. The sum of all
+ * percentages for priorities which belong to the same group must total 100
+ * percent.
+ *
+ * Element-type: guint
+ **/
+ /* ---ifcfg-rh---
+ * property: priority-bandwidth
+ * variable: DCB_PG_UPPCT
+ * description: Priority values. Eight bandwidths (in percent), separated with commas.
+ * The sum of the numbers must be 100.
+ * example: DCB_PG_UPPCT=7,13,10,10,15,15,10,20
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_PRIORITY_BANDWIDTH,
+ g_param_spec_boxed (NM_SETTING_DCB_PRIORITY_BANDWIDTH, "", "",
+ 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);
+
+ /**
+ * NMSettingDcb:priority-strict-bandwidth:
+ *
+ * An array of 8 boolean values, where the array index corresponds to the User
+ * Priority (0 - 7) and the value indicates whether or not the priority may
+ * use all of the bandwidth allocated to its assigned group.
+ *
+ * Element-type: gboolean
+ **/
+ /* ---ifcfg-rh---
+ * property: priority-strict-bandwidth
+ * variable: DCB_PG_STRICT
+ * description: Priority values. String of eight "0" or "1", where "0" means
+ * "may not utilize all bandwidth", "1" means "may utilize all bandwidth".
+ * example: DCB_PG_STRICT=01101110
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_PRIORITY_STRICT,
+ g_param_spec_boxed (NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH, "", "",
+ 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);
+
+ /**
+ * NMSettingDcb:priority-traffic-class:
+ *
+ * An array of 8 uint values, where the array index corresponds to the User
+ * Priority (0 - 7) and the value indicates the traffic class (0 - 7) to
+ * which the priority is mapped.
+ *
+ * Element-type: guint
+ **/
+ /* ---ifcfg-rh---
+ * property: priority-traffic-class
+ * variable: DCB_PG_UP2TC
+ * description: Priority values. String of eight trafic class values (0 - 7).
+ * example: DCB_PG_UP2TC=01623701
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_PRIORITY_TRAFFIC_CLASS,
+ g_param_spec_boxed (NM_SETTING_DCB_PRIORITY_TRAFFIC_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);
+}
diff --git a/libnm-core/nm-setting-dcb.h b/libnm-core/nm-setting-dcb.h
new file mode 100644
index 000000000..e5bc4bcfa
--- /dev/null
+++ b/libnm-core/nm-setting-dcb.h
@@ -0,0 +1,164 @@
+/* -*- 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 2013 Red Hat, Inc.
+ */
+
+#ifndef __NM_SETTING_DCB_H__
+#define __NM_SETTING_DCB_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_DCB (nm_setting_dcb_get_type ())
+#define NM_SETTING_DCB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_DCB, NMSettingDcb))
+#define NM_SETTING_DCB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_DCB, NMSettingDcbClass))
+#define NM_IS_SETTING_DCB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_DCB))
+#define NM_IS_SETTING_DCB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_DCB))
+#define NM_SETTING_DCB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_DCB, NMSettingDcbClass))
+
+#define NM_SETTING_DCB_SETTING_NAME "dcb"
+
+/**
+ * NMSettingDcbFlags:
+ * @NM_SETTING_DCB_FLAG_NONE: no flag
+ * @NM_SETTING_DCB_FLAG_ENABLE: the feature is enabled
+ * @NM_SETTING_DCB_FLAG_ADVERTISE: the feature is advertised
+ * @NM_SETTING_DCB_FLAG_WILLING: the feature is willing to change based on
+ * peer configuration advertisements
+ *
+ * DCB feature flags.
+ **/
+typedef enum { /*< flags >*/
+ NM_SETTING_DCB_FLAG_NONE = 0x00000000,
+ NM_SETTING_DCB_FLAG_ENABLE = 0x00000001,
+ NM_SETTING_DCB_FLAG_ADVERTISE = 0x00000002,
+ NM_SETTING_DCB_FLAG_WILLING = 0x00000004
+} NMSettingDcbFlags;
+
+/**
+ * NM_SETTING_DCB_FCOE_MODE_FABRIC:
+ *
+ * Indicates that the FCoE controller should use "fabric" mode (default)
+ */
+#define NM_SETTING_DCB_FCOE_MODE_FABRIC "fabric"
+
+/**
+ * NM_SETTING_DCB_FCOE_MODE_VN2VN:
+ *
+ * Indicates that the FCoE controller should use "VN2VN" mode.
+ */
+#define NM_SETTING_DCB_FCOE_MODE_VN2VN "vn2vn"
+
+
+/* Properties */
+#define NM_SETTING_DCB_APP_FCOE_FLAGS "app-fcoe-flags"
+#define NM_SETTING_DCB_APP_FCOE_PRIORITY "app-fcoe-priority"
+#define NM_SETTING_DCB_APP_FCOE_MODE "app-fcoe-mode"
+
+#define NM_SETTING_DCB_APP_ISCSI_FLAGS "app-iscsi-flags"
+#define NM_SETTING_DCB_APP_ISCSI_PRIORITY "app-iscsi-priority"
+
+#define NM_SETTING_DCB_APP_FIP_FLAGS "app-fip-flags"
+#define NM_SETTING_DCB_APP_FIP_PRIORITY "app-fip-priority"
+
+#define NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS "priority-flow-control-flags"
+#define NM_SETTING_DCB_PRIORITY_FLOW_CONTROL "priority-flow-control"
+
+#define NM_SETTING_DCB_PRIORITY_GROUP_FLAGS "priority-group-flags"
+#define NM_SETTING_DCB_PRIORITY_GROUP_ID "priority-group-id"
+#define NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH "priority-group-bandwidth"
+#define NM_SETTING_DCB_PRIORITY_BANDWIDTH "priority-bandwidth"
+#define NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH "priority-strict-bandwidth"
+#define NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS "priority-traffic-class"
+
+
+struct _NMSettingDcb {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingDcbClass;
+
+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);
+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);
+
+NMSettingDcbFlags nm_setting_dcb_get_app_fip_flags (NMSettingDcb *setting);
+gint nm_setting_dcb_get_app_fip_priority (NMSettingDcb *setting);
+
+/* Priority Flow Control */
+NMSettingDcbFlags nm_setting_dcb_get_priority_flow_control_flags (NMSettingDcb *setting);
+gboolean nm_setting_dcb_get_priority_flow_control (NMSettingDcb *setting,
+ guint user_priority);
+void nm_setting_dcb_set_priority_flow_control (NMSettingDcb *setting,
+ guint user_priority,
+ gboolean enabled);
+
+/* Priority Groups */
+NMSettingDcbFlags nm_setting_dcb_get_priority_group_flags (NMSettingDcb *setting);
+
+guint nm_setting_dcb_get_priority_group_id (NMSettingDcb *setting,
+ guint user_priority);
+void nm_setting_dcb_set_priority_group_id (NMSettingDcb *setting,
+ guint user_priority,
+ guint group_id);
+
+guint nm_setting_dcb_get_priority_group_bandwidth (NMSettingDcb *setting,
+ guint group_id);
+void nm_setting_dcb_set_priority_group_bandwidth (NMSettingDcb *setting,
+ guint group_id,
+ guint bandwidth_percent);
+
+guint nm_setting_dcb_get_priority_bandwidth (NMSettingDcb *setting,
+ guint user_priority);
+void nm_setting_dcb_set_priority_bandwidth (NMSettingDcb *setting,
+ guint user_priority,
+ guint bandwidth_percent);
+
+gboolean nm_setting_dcb_get_priority_strict_bandwidth (NMSettingDcb *setting,
+ guint user_priority);
+void nm_setting_dcb_set_priority_strict_bandwidth (NMSettingDcb *setting,
+ guint user_priority,
+ gboolean strict);
+
+guint nm_setting_dcb_get_priority_traffic_class (NMSettingDcb *setting,
+ guint user_priority);
+void nm_setting_dcb_set_priority_traffic_class (NMSettingDcb *setting,
+ guint user_priority,
+ guint traffic_class);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_DCB_H__ */
diff --git a/libnm-core/nm-setting-generic.c b/libnm-core/nm-setting-generic.c
new file mode 100644
index 000000000..35deb2de0
--- /dev/null
+++ b/libnm-core/nm-setting-generic.c
@@ -0,0 +1,73 @@
+/* -*- 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 2013 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include "nm-setting-generic.h"
+#include "nm-setting-private.h"
+
+/**
+ * SECTION:nm-setting-generic
+ * @short_description: Describes connection properties for generic devices
+ *
+ * The #NMSettingGeneric object is a #NMSetting subclass that describes
+ * optional properties that apply to "generic" devices (ie, devices that
+ * NetworkManager does not specifically recognize).
+ *
+ * There are currently no properties on this object; it exists only to be
+ * 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, 1))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_GENERIC)
+
+#define NM_SETTING_GENERIC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_GENERIC, NMSettingGenericPrivate))
+
+typedef struct {
+ int dummy;
+} NMSettingGenericPrivate;
+
+/**************************************************************************/
+
+/**
+ * nm_setting_generic_new:
+ *
+ * Creates a new #NMSettingGeneric object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingGeneric object
+ **/
+NMSetting *
+nm_setting_generic_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_GENERIC, NULL);
+}
+
+static void
+nm_setting_generic_init (NMSettingGeneric *setting)
+{
+}
+
+static void
+nm_setting_generic_class_init (NMSettingGenericClass *setting_class)
+{
+ g_type_class_add_private (setting_class, sizeof (NMSettingGenericPrivate));
+}
diff --git a/libnm-core/nm-setting-generic.h b/libnm-core/nm-setting-generic.h
new file mode 100644
index 000000000..7a209da25
--- /dev/null
+++ b/libnm-core/nm-setting-generic.h
@@ -0,0 +1,59 @@
+/* -*- 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 2013 Red Hat, Inc.
+ */
+
+#ifndef __NM_SETTING_GENERIC_H__
+#define __NM_SETTING_GENERIC_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_GENERIC (nm_setting_generic_get_type ())
+#define NM_SETTING_GENERIC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_GENERIC, NMSettingGeneric))
+#define NM_SETTING_GENERIC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_GENERIC, NMSettingGenericClass))
+#define NM_IS_SETTING_GENERIC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_GENERIC))
+#define NM_IS_SETTING_GENERIC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_GENERIC))
+#define NM_SETTING_GENERIC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_GENERIC, NMSettingGenericClass))
+
+#define NM_SETTING_GENERIC_SETTING_NAME "generic"
+
+struct _NMSettingGeneric {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingGenericClass;
+
+GType nm_setting_generic_get_type (void);
+
+NMSetting * nm_setting_generic_new (void);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_GENERIC_H__ */
diff --git a/libnm-core/nm-setting-gsm.c b/libnm-core/nm-setting-gsm.c
new file mode 100644
index 000000000..22f8cdbad
--- /dev/null
+++ b/libnm-core/nm-setting-gsm.c
@@ -0,0 +1,616 @@
+/* -*- 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 2007 - 2013 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-gsm.h"
+#include "nm-utils.h"
+#include "nm-setting-private.h"
+#include "nm-core-enum-types.h"
+
+/**
+ * SECTION:nm-setting-gsm
+ * @short_description: Describes GSM/3GPP-based mobile broadband properties
+ *
+ * The #NMSettingGsm object is a #NMSetting subclass that describes
+ * properties that allow connections to 3GPP-based mobile broadband
+ * 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, 1))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_GSM)
+
+#define NM_SETTING_GSM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_GSM, NMSettingGsmPrivate))
+
+typedef struct {
+ char *number; /* For dialing, duh */
+ char *username;
+ char *password;
+ NMSettingSecretFlags password_flags;
+
+ char *apn; /* NULL for dynamic */
+ char *network_id; /* for manual registration or NULL for automatic */
+
+ char *pin;
+ NMSettingSecretFlags pin_flags;
+
+ gboolean home_only;
+} NMSettingGsmPrivate;
+
+enum {
+ PROP_0,
+ PROP_NUMBER,
+ PROP_USERNAME,
+ PROP_PASSWORD,
+ PROP_PASSWORD_FLAGS,
+ PROP_APN,
+ PROP_NETWORK_ID,
+ PROP_PIN,
+ PROP_PIN_FLAGS,
+ PROP_HOME_ONLY,
+
+ LAST_PROP
+};
+
+/**
+ * nm_setting_gsm_new:
+ *
+ * Creates a new #NMSettingGsm object with default values.
+ *
+ * Returns: the new empty #NMSettingGsm object
+ **/
+NMSetting *
+nm_setting_gsm_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_GSM, NULL);
+}
+
+/**
+ * nm_setting_gsm_get_number:
+ * @setting: the #NMSettingGsm
+ *
+ * Returns: the #NMSettingGsm:number property of the setting
+ **/
+const char *
+nm_setting_gsm_get_number (NMSettingGsm *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_GSM (setting), NULL);
+
+ return NM_SETTING_GSM_GET_PRIVATE (setting)->number;
+}
+
+/**
+ * nm_setting_gsm_get_username:
+ * @setting: the #NMSettingGsm
+ *
+ * Returns: the #NMSettingGsm:username property of the setting
+ **/
+const char *
+nm_setting_gsm_get_username (NMSettingGsm *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_GSM (setting), NULL);
+
+ return NM_SETTING_GSM_GET_PRIVATE (setting)->username;
+}
+
+/**
+ * nm_setting_gsm_get_password:
+ * @setting: the #NMSettingGsm
+ *
+ * Returns: the #NMSettingGsm:password property of the setting
+ **/
+const char *
+nm_setting_gsm_get_password (NMSettingGsm *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_GSM (setting), NULL);
+
+ return NM_SETTING_GSM_GET_PRIVATE (setting)->password;
+}
+
+/**
+ * nm_setting_gsm_get_password_flags:
+ * @setting: the #NMSettingGsm
+ *
+ * Returns: the #NMSettingSecretFlags pertaining to the #NMSettingGsm:password
+ **/
+NMSettingSecretFlags
+nm_setting_gsm_get_password_flags (NMSettingGsm *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_GSM (setting), NM_SETTING_SECRET_FLAG_NONE);
+
+ return NM_SETTING_GSM_GET_PRIVATE (setting)->password_flags;
+}
+
+/**
+ * nm_setting_gsm_get_apn:
+ * @setting: the #NMSettingGsm
+ *
+ * Returns: the #NMSettingGsm:apn property of the setting
+ **/
+const char *
+nm_setting_gsm_get_apn (NMSettingGsm *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_GSM (setting), NULL);
+
+ return NM_SETTING_GSM_GET_PRIVATE (setting)->apn;
+}
+
+/**
+ * nm_setting_gsm_get_network_id:
+ * @setting: the #NMSettingGsm
+ *
+ * Returns: the #NMSettingGsm:network-id property of the setting
+ **/
+const char *
+nm_setting_gsm_get_network_id (NMSettingGsm *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_GSM (setting), NULL);
+
+ return NM_SETTING_GSM_GET_PRIVATE (setting)->network_id;
+}
+
+/**
+ * nm_setting_gsm_get_pin:
+ * @setting: the #NMSettingGsm
+ *
+ * Returns: the #NMSettingGsm:pin property of the setting
+ **/
+const char *
+nm_setting_gsm_get_pin (NMSettingGsm *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_GSM (setting), NULL);
+
+ return NM_SETTING_GSM_GET_PRIVATE (setting)->pin;
+}
+
+/**
+ * nm_setting_gsm_get_pin_flags:
+ * @setting: the #NMSettingGsm
+ *
+ * Returns: the #NMSettingSecretFlags pertaining to the #NMSettingGsm:pin
+ **/
+NMSettingSecretFlags
+nm_setting_gsm_get_pin_flags (NMSettingGsm *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_GSM (setting), NM_SETTING_SECRET_FLAG_NONE);
+
+ return NM_SETTING_GSM_GET_PRIVATE (setting)->pin_flags;
+}
+
+/**
+ * nm_setting_gsm_get_home_only:
+ * @setting: the #NMSettingGsm
+ *
+ * Returns: the #NMSettingGsm:home-only property of the setting
+ **/
+gboolean
+nm_setting_gsm_get_home_only (NMSettingGsm *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_GSM (setting), FALSE);
+
+ return NM_SETTING_GSM_GET_PRIVATE (setting)->home_only;
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ NMSettingGsmPrivate *priv = NM_SETTING_GSM_GET_PRIVATE (setting);
+
+ if (priv->number && !priv->number[0]) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_NUMBER);
+ return FALSE;
+ }
+
+ if (priv->apn) {
+ guint32 apn_len = strlen (priv->apn);
+ guint32 i;
+
+ if (apn_len < 1 || apn_len > 64) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property value '%s' is empty or too long (>64)"),
+ priv->apn);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_APN);
+ return FALSE;
+ }
+
+ /* APNs roughly follow the same rules as DNS domain names. Allowed
+ * characters are a-z, 0-9, . and -. GSM 03.03 Section 9.1 states:
+ *
+ * The syntax of the APN shall follow the Name Syntax defined in
+ * RFC 2181 [14] and RFC 1035 [15]. The APN consists of one or
+ * more labels. Each label is coded as one octet length field
+ * followed by that number of octets coded as 8 bit ASCII characters.
+ * Following RFC 1035 [15] the labels should consist only of the
+ * alphabetic characters (A-Z and a-z), digits (0-9) and the
+ * dash (-). The case of alphabetic characters is not significant.
+ *
+ * A dot (.) is commonly used to separate parts of the APN, and
+ * apparently the underscore (_) is used as well. RFC 2181 indicates
+ * that no restrictions of any kind are placed on DNS labels, and thus
+ * it would appear that none are placed on APNs either, but many modems
+ * and networks will fail to accept APNs that include odd characters
+ * like space ( ) and such.
+ */
+ for (i = 0; i < apn_len; i++) {
+ if ( !g_ascii_isalnum (priv->apn[i])
+ && (priv->apn[i] != '.')
+ && (priv->apn[i] != '_')
+ && (priv->apn[i] != '-')) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' contains invalid char(s) (use [A-Za-z._-])"),
+ priv->apn);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_APN);
+ return FALSE;
+ }
+ }
+ }
+
+ if (priv->username && !strlen (priv->username)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_USERNAME);
+ return FALSE;
+ }
+
+ if (priv->password && !strlen (priv->password)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_USERNAME);
+ return FALSE;
+ }
+
+ if (priv->network_id) {
+ guint32 nid_len = strlen (priv->network_id);
+ guint32 i;
+
+ /* Accept both 5 and 6 digit MCC/MNC codes */
+ if ((nid_len < 5) || (nid_len > 6)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' length is invalid (should be 5 or 6 digits)"),
+ priv->network_id);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_NETWORK_ID);
+ return FALSE;
+ }
+
+ for (i = 0; i < nid_len; i++) {
+ if (!g_ascii_isdigit (priv->network_id[i])) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a number"),
+ priv->network_id);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_GSM_SETTING_NAME, NM_SETTING_GSM_NETWORK_ID);
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+static GPtrArray *
+need_secrets (NMSetting *setting)
+{
+ NMSettingGsmPrivate *priv = NM_SETTING_GSM_GET_PRIVATE (setting);
+ GPtrArray *secrets = NULL;
+
+ if (priv->password)
+ return NULL;
+
+ if (priv->username) {
+ if (!(priv->password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) {
+ secrets = g_ptr_array_sized_new (1);
+ g_ptr_array_add (secrets, NM_SETTING_GSM_PASSWORD);
+ }
+ }
+
+ return secrets;
+}
+
+static void
+nm_setting_gsm_init (NMSettingGsm *setting)
+{
+}
+
+static void
+finalize (GObject *object)
+{
+ NMSettingGsmPrivate *priv = NM_SETTING_GSM_GET_PRIVATE (object);
+
+ g_free (priv->number);
+ g_free (priv->username);
+ g_free (priv->password);
+ g_free (priv->apn);
+ g_free (priv->network_id);
+ g_free (priv->pin);
+
+ G_OBJECT_CLASS (nm_setting_gsm_parent_class)->finalize (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingGsmPrivate *priv = NM_SETTING_GSM_GET_PRIVATE (object);
+ char *tmp;
+
+ switch (prop_id) {
+ case PROP_NUMBER:
+ g_free (priv->number);
+ priv->number = g_value_dup_string (value);
+ break;
+ case PROP_USERNAME:
+ g_free (priv->username);
+ priv->username = g_value_dup_string (value);
+ break;
+ case PROP_PASSWORD:
+ g_free (priv->password);
+ priv->password = g_value_dup_string (value);
+ break;
+ case PROP_PASSWORD_FLAGS:
+ priv->password_flags = g_value_get_flags (value);
+ break;
+ case PROP_APN:
+ g_free (priv->apn);
+ priv->apn = NULL;
+ tmp = g_value_dup_string (value);
+ if (tmp)
+ priv->apn = g_strstrip (tmp);
+ break;
+ case PROP_NETWORK_ID:
+ g_free (priv->network_id);
+ priv->network_id = NULL;
+ tmp = g_value_dup_string (value);
+ if (tmp)
+ priv->network_id = g_strstrip (tmp);
+ break;
+ case PROP_PIN:
+ g_free (priv->pin);
+ priv->pin = g_value_dup_string (value);
+ break;
+ case PROP_PIN_FLAGS:
+ priv->pin_flags = g_value_get_flags (value);
+ break;
+ case PROP_HOME_ONLY:
+ priv->home_only = g_value_get_boolean (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)
+{
+ NMSettingGsm *setting = NM_SETTING_GSM (object);
+
+ switch (prop_id) {
+ case PROP_NUMBER:
+ g_value_set_string (value, nm_setting_gsm_get_number (setting));
+ break;
+ case PROP_USERNAME:
+ g_value_set_string (value, nm_setting_gsm_get_username (setting));
+ break;
+ case PROP_PASSWORD:
+ g_value_set_string (value, nm_setting_gsm_get_password (setting));
+ break;
+ case PROP_PASSWORD_FLAGS:
+ g_value_set_flags (value, nm_setting_gsm_get_password_flags (setting));
+ break;
+ case PROP_APN:
+ g_value_set_string (value, nm_setting_gsm_get_apn (setting));
+ break;
+ case PROP_NETWORK_ID:
+ g_value_set_string (value, nm_setting_gsm_get_network_id (setting));
+ break;
+ case PROP_PIN:
+ g_value_set_string (value, nm_setting_gsm_get_pin (setting));
+ break;
+ case PROP_PIN_FLAGS:
+ g_value_set_flags (value, nm_setting_gsm_get_pin_flags (setting));
+ break;
+ case PROP_HOME_ONLY:
+ g_value_set_boolean (value, nm_setting_gsm_get_home_only (setting));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_setting_gsm_class_init (NMSettingGsmClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+ NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+ g_type_class_add_private (setting_class, 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->need_secrets = need_secrets;
+
+ /* Properties */
+
+ /**
+ * NMSettingGsm:number:
+ *
+ * Number to dial when establishing a PPP data session with the GSM-based
+ * mobile broadband network. Many modems do not require PPP for connections
+ * to the mobile network and thus this property should be left blank, which
+ * allows NetworkManager to select the appropriate settings automatically.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_NUMBER,
+ g_param_spec_string (NM_SETTING_GSM_NUMBER, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingGsm:username:
+ *
+ * The username used to authenticate with the network, if required. Many
+ * providers do not require a username, or accept any username. But if a
+ * username is required, it is specified here.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_USERNAME,
+ g_param_spec_string (NM_SETTING_GSM_USERNAME, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingGsm:password:
+ *
+ * The password used to authenticate with the network, if required. Many
+ * providers do not require a password, or accept any password. But if a
+ * password is required, it is specified here.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_PASSWORD,
+ g_param_spec_string (NM_SETTING_GSM_PASSWORD, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_SECRET |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingGsm:password-flags:
+ *
+ * Flags indicating how to handle the #NMSettingGsm:password property.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_PASSWORD_FLAGS,
+ g_param_spec_flags (NM_SETTING_GSM_PASSWORD_FLAGS, "", "",
+ NM_TYPE_SETTING_SECRET_FLAGS,
+ NM_SETTING_SECRET_FLAG_NONE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingGsm:apn:
+ *
+ * The GPRS Access Point Name specifying the APN used when establishing a
+ * data session with the GSM-based network. The APN often determines how
+ * the user will be billed for their network usage and whether the user has
+ * access to the Internet or just a provider-specific walled-garden, so it
+ * is important to use the correct APN for the user's mobile broadband plan.
+ * The APN may only be composed of the characters a-z, 0-9, ., and - per GSM
+ * 03.60 Section 14.9.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_APN,
+ g_param_spec_string (NM_SETTING_GSM_APN, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingGsm:network-id:
+ *
+ * The Network ID (GSM LAI format, ie MCC-MNC) to force specific network
+ * registration. If the Network ID is specified, NetworkManager will
+ * attempt to force the device to register only on the specified network.
+ * This can be used to ensure that the device does not roam when direct
+ * roaming control of the device is not otherwise possible.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_NETWORK_ID,
+ g_param_spec_string (NM_SETTING_GSM_NETWORK_ID, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingGsm:pin:
+ *
+ * If the SIM is locked with a PIN it must be unlocked before any other
+ * operations are requested. Specify the PIN here to allow operation of the
+ * device.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_PIN,
+ g_param_spec_string (NM_SETTING_GSM_PIN, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_SECRET |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingGsm:pin-flags:
+ *
+ * Flags indicating how to handle the #NMSettingGsm:pin property.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_PIN_FLAGS,
+ g_param_spec_flags (NM_SETTING_GSM_PIN_FLAGS, "", "",
+ NM_TYPE_SETTING_SECRET_FLAGS,
+ NM_SETTING_SECRET_FLAG_NONE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingGsm:home-only:
+ *
+ * When %TRUE, only connections to the home network will be allowed.
+ * Connections to roaming networks will not be made.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_HOME_ONLY,
+ g_param_spec_boolean (NM_SETTING_GSM_HOME_ONLY, "", "",
+ FALSE,
+ G_PARAM_READWRITE |
+ 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);
+}
diff --git a/libnm-core/nm-setting-gsm.h b/libnm-core/nm-setting-gsm.h
new file mode 100644
index 000000000..907567381
--- /dev/null
+++ b/libnm-core/nm-setting-gsm.h
@@ -0,0 +1,80 @@
+/* -*- 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 2007 - 2011 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#ifndef __NM_SETTING_GSM_H__
+#define __NM_SETTING_GSM_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_GSM (nm_setting_gsm_get_type ())
+#define NM_SETTING_GSM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_GSM, NMSettingGsm))
+#define NM_SETTING_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_GSM, NMSettingGsmClass))
+#define NM_IS_SETTING_GSM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_GSM))
+#define NM_IS_SETTING_GSM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_GSM))
+#define NM_SETTING_GSM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_GSM, NMSettingGsmClass))
+
+#define NM_SETTING_GSM_SETTING_NAME "gsm"
+
+#define NM_SETTING_GSM_NUMBER "number"
+#define NM_SETTING_GSM_USERNAME "username"
+#define NM_SETTING_GSM_PASSWORD "password"
+#define NM_SETTING_GSM_PASSWORD_FLAGS "password-flags"
+#define NM_SETTING_GSM_APN "apn"
+#define NM_SETTING_GSM_NETWORK_ID "network-id"
+#define NM_SETTING_GSM_PIN "pin"
+#define NM_SETTING_GSM_PIN_FLAGS "pin-flags"
+#define NM_SETTING_GSM_HOME_ONLY "home-only"
+
+struct _NMSettingGsm {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingGsmClass;
+
+GType nm_setting_gsm_get_type (void);
+
+NMSetting *nm_setting_gsm_new (void);
+const char *nm_setting_gsm_get_number (NMSettingGsm *setting);
+const char *nm_setting_gsm_get_username (NMSettingGsm *setting);
+const char *nm_setting_gsm_get_password (NMSettingGsm *setting);
+const char *nm_setting_gsm_get_apn (NMSettingGsm *setting);
+const char *nm_setting_gsm_get_network_id (NMSettingGsm *setting);
+const char *nm_setting_gsm_get_pin (NMSettingGsm *setting);
+gboolean nm_setting_gsm_get_home_only (NMSettingGsm *setting);
+
+NMSettingSecretFlags nm_setting_gsm_get_pin_flags (NMSettingGsm *setting);
+NMSettingSecretFlags nm_setting_gsm_get_password_flags (NMSettingGsm *setting);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_GSM_H__ */
diff --git a/libnm-core/nm-setting-infiniband.c b/libnm-core/nm-setting-infiniband.c
new file mode 100644
index 000000000..b0afe04f1
--- /dev/null
+++ b/libnm-core/nm-setting-infiniband.c
@@ -0,0 +1,522 @@
+/* -*- 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 2011 - 2013 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-infiniband.h"
+#include "nm-utils.h"
+#include "nm-utils-private.h"
+#include "nm-setting-private.h"
+#include "nm-setting-connection.h"
+
+/**
+ * SECTION:nm-setting-infiniband
+ * @short_description: Describes connection properties for IP-over-InfiniBand networks
+ *
+ * The #NMSettingInfiniband object is a #NMSetting subclass that describes properties
+ * necessary for connection to IP-over-InfiniBand networks.
+ **/
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingInfiniband, nm_setting_infiniband, NM_TYPE_SETTING,
+ _nm_register_setting (INFINIBAND, 1))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_INFINIBAND)
+
+#define NM_SETTING_INFINIBAND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_INFINIBAND, NMSettingInfinibandPrivate))
+
+typedef struct {
+ char *mac_address;
+ char *transport_mode;
+ guint32 mtu;
+ int p_key;
+ char *parent, *virtual_iface_name;
+} NMSettingInfinibandPrivate;
+
+enum {
+ PROP_0,
+ PROP_MAC_ADDRESS,
+ PROP_MTU,
+ PROP_TRANSPORT_MODE,
+ PROP_P_KEY,
+ PROP_PARENT,
+
+ LAST_PROP
+};
+
+/**
+ * nm_setting_infiniband_new:
+ *
+ * Creates a new #NMSettingInfiniband object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingInfiniband object
+ **/
+NMSetting *
+nm_setting_infiniband_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_INFINIBAND, NULL);
+}
+
+/**
+ * nm_setting_infiniband_get_mac_address:
+ * @setting: the #NMSettingInfiniband
+ *
+ * Returns: the #NMSettingInfiniband:mac-address property of the setting
+ **/
+const char *
+nm_setting_infiniband_get_mac_address (NMSettingInfiniband *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_INFINIBAND (setting), NULL);
+
+ return NM_SETTING_INFINIBAND_GET_PRIVATE (setting)->mac_address;
+}
+
+/**
+ * nm_setting_infiniband_get_mtu:
+ * @setting: the #NMSettingInfiniband
+ *
+ * Returns: the #NMSettingInfiniband:mtu property of the setting
+ **/
+guint32
+nm_setting_infiniband_get_mtu (NMSettingInfiniband *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_INFINIBAND (setting), 0);
+
+ return NM_SETTING_INFINIBAND_GET_PRIVATE (setting)->mtu;
+}
+
+/**
+ * nm_setting_infiniband_get_transport_mode:
+ * @setting: the #NMSettingInfiniband
+ *
+ * Returns the transport mode for this device. Either 'datagram' or
+ * 'connected'.
+ *
+ * Returns: the IPoIB transport mode
+ **/
+const char *
+nm_setting_infiniband_get_transport_mode (NMSettingInfiniband *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_INFINIBAND (setting), NULL);
+
+ return NM_SETTING_INFINIBAND_GET_PRIVATE (setting)->transport_mode;
+}
+
+/**
+ * nm_setting_infiniband_get_p_key:
+ * @setting: the #NMSettingInfiniband
+ *
+ * Returns the P_Key to use for this device. A value of -1 means to
+ * use the default P_Key (aka "the P_Key at index 0"). Otherwise it is
+ * a 16-bit unsigned integer.
+ *
+ * Returns: the IPoIB P_Key
+ **/
+int
+nm_setting_infiniband_get_p_key (NMSettingInfiniband *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_INFINIBAND (setting), -1);
+
+ return NM_SETTING_INFINIBAND_GET_PRIVATE (setting)->p_key;
+}
+
+/**
+ * nm_setting_infiniband_get_parent:
+ * @setting: the #NMSettingInfiniband
+ *
+ * Returns the parent interface name for this device, if set.
+ *
+ * Returns: the parent interface name
+ **/
+const char *
+nm_setting_infiniband_get_parent (NMSettingInfiniband *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_INFINIBAND (setting), NULL);
+
+ return NM_SETTING_INFINIBAND_GET_PRIVATE (setting)->parent;
+}
+
+/**
+ * nm_setting_infiniband_get_virtual_interface_name:
+ * @setting: the #NMSettingInfiniband
+ *
+ * Returns the interface name created by combining #NMSettingInfiniband:parent
+ * and #NMSettingInfiniband:p-key. (If either property is unset, this will
+ * return %NULL.)
+ *
+ * Returns: the interface name, or %NULL
+ **/
+const char *
+nm_setting_infiniband_get_virtual_interface_name (NMSettingInfiniband *setting)
+{
+ NMSettingInfinibandPrivate *priv = NM_SETTING_INFINIBAND_GET_PRIVATE (setting);
+
+ if (priv->p_key == -1 || !priv->parent)
+ return NULL;
+
+ if (!priv->virtual_iface_name)
+ priv->virtual_iface_name = g_strdup_printf ("%s.%04x", priv->parent, priv->p_key);
+
+ return NM_SETTING_INFINIBAND_GET_PRIVATE (setting)->virtual_iface_name;
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ NMSettingConnection *s_con;
+ NMSettingInfinibandPrivate *priv = NM_SETTING_INFINIBAND_GET_PRIVATE (setting);
+ guint32 normerr_max_mtu = 0;
+
+ if (priv->mac_address && !nm_utils_hwaddr_valid (priv->mac_address, INFINIBAND_ALEN)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_INFINIBAND_SETTING_NAME, NM_SETTING_INFINIBAND_MAC_ADDRESS);
+ return FALSE;
+ }
+
+ if (!g_strcmp0 (priv->transport_mode, "datagram")) {
+ if (priv->mtu > 2044)
+ normerr_max_mtu = 2044;
+ } else if (!g_strcmp0 (priv->transport_mode, "connected")) {
+ if (priv->mtu > 65520)
+ normerr_max_mtu = 65520;
+ } else {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_INFINIBAND_SETTING_NAME, NM_SETTING_INFINIBAND_TRANSPORT_MODE);
+ return FALSE;
+ }
+
+ if (priv->parent) {
+ if (!nm_utils_iface_valid_name (priv->parent)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("not a valid interface name"));
+ g_prefix_error (error, "%s: ", NM_SETTING_INFINIBAND_PARENT);
+ return FALSE;
+ }
+ if (priv->p_key == -1) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("Must specify a P_Key if specifying parent"));
+ g_prefix_error (error, "%s: ", NM_SETTING_INFINIBAND_PARENT);
+ }
+ }
+
+ if (priv->p_key != -1) {
+ if (!priv->mac_address && !priv->parent) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("InfiniBand P_Key connection did not specify parent interface name"));
+ g_prefix_error (error, "%s: ", NM_SETTING_INFINIBAND_PARENT);
+ return FALSE;
+ }
+ }
+
+ s_con = nm_connection_get_setting_connection (connection);
+ if (s_con) {
+ const char *interface_name = nm_setting_connection_get_interface_name (s_con);
+
+ if (!interface_name)
+ ;
+ else if (!nm_utils_iface_valid_name (interface_name)) {
+ /* report the error for NMSettingConnection:interface-name, because
+ * it's that property that is invalid -- although we currently verify()
+ * NMSettingInfiniband.
+ **/
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid interface name"),
+ interface_name);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME);
+ return FALSE;
+ } else {
+ if (priv->p_key != -1) {
+ if (!priv->virtual_iface_name)
+ priv->virtual_iface_name = g_strdup_printf ("%s.%04x", priv->parent, priv->p_key);
+
+ if (strcmp (interface_name, priv->virtual_iface_name) != 0) {
+ /* We don't support renaming software infiniband devices. Later we might, but
+ * for now just reject such connections.
+ **/
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("interface name of software infiniband device must be '%s' or unset (instead it is '%s')"),
+ priv->virtual_iface_name, interface_name);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME);
+ return FALSE;
+ }
+ }
+ }
+ }
+
+ /* *** errors above here should be always fatal, below NORMALIZABLE_ERROR *** */
+
+ if (normerr_max_mtu > 0) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("mtu for transport mode '%s' can be at most %d but it is %d"),
+ priv->transport_mode, normerr_max_mtu, priv->mtu);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_INFINIBAND_SETTING_NAME, NM_SETTING_INFINIBAND_MTU);
+ return NM_SETTING_VERIFY_NORMALIZABLE_ERROR;
+ }
+
+ return TRUE;
+}
+
+static void
+nm_setting_infiniband_init (NMSettingInfiniband *setting)
+{
+}
+
+static void
+finalize (GObject *object)
+{
+ NMSettingInfinibandPrivate *priv = NM_SETTING_INFINIBAND_GET_PRIVATE (object);
+
+ g_free (priv->transport_mode);
+ g_free (priv->mac_address);
+ g_free (priv->parent);
+ g_free (priv->virtual_iface_name);
+
+ G_OBJECT_CLASS (nm_setting_infiniband_parent_class)->finalize (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingInfinibandPrivate *priv = NM_SETTING_INFINIBAND_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),
+ INFINIBAND_ALEN);
+ break;
+ case PROP_MTU:
+ priv->mtu = g_value_get_uint (value);
+ break;
+ case PROP_TRANSPORT_MODE:
+ g_free (priv->transport_mode);
+ priv->transport_mode = g_value_dup_string (value);
+ break;
+ case PROP_P_KEY:
+ priv->p_key = g_value_get_int (value);
+ g_clear_pointer (&priv->virtual_iface_name, g_free);
+ break;
+ case PROP_PARENT:
+ g_free (priv->parent);
+ priv->parent = g_value_dup_string (value);
+ g_clear_pointer (&priv->virtual_iface_name, g_free);
+ 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)
+{
+ NMSettingInfiniband *setting = NM_SETTING_INFINIBAND (object);
+
+ switch (prop_id) {
+ case PROP_MAC_ADDRESS:
+ g_value_set_string (value, nm_setting_infiniband_get_mac_address (setting));
+ break;
+ case PROP_MTU:
+ g_value_set_uint (value, nm_setting_infiniband_get_mtu (setting));
+ break;
+ case PROP_TRANSPORT_MODE:
+ g_value_set_string (value, nm_setting_infiniband_get_transport_mode (setting));
+ break;
+ case PROP_P_KEY:
+ g_value_set_int (value, nm_setting_infiniband_get_p_key (setting));
+ break;
+ case PROP_PARENT:
+ g_value_set_string (value, nm_setting_infiniband_get_parent (setting));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_setting_infiniband_class_init (NMSettingInfinibandClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+ NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+ g_type_class_add_private (setting_class, sizeof (NMSettingInfinibandPrivate));
+
+ /* virtual methods */
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+ object_class->finalize = finalize;
+
+ parent_class->verify = verify;
+
+ /* Properties */
+ /**
+ * NMSettingInfiniband:mac-address:
+ *
+ * If specified, this connection will only apply to the IPoIB device whose
+ * permanent MAC address matches. This property does not change the MAC
+ * address of the device (i.e. MAC spoofing).
+ **/
+ /* ---keyfile---
+ * property: mac-address
+ * format: ususal hex-digits-and-colons notation
+ * description: MAC address in traditional hex-digits-and-colons notation, or
+ * or semicolon separated list of 20 decimal bytes (obsolete)
+ * example: mac-address= 80:00:00:6d:fe:80:00:00:00:00:00:00:00:02:55:00:70:33:cf:01
+ * ---end---
+ * ---ifcfg-rh---
+ * property: mac-address
+ * variable: HWADDR
+ * description: IBoIP 20-byte hardware address of the device (in traditional
+ * hex-digits-and-colons notation).
+ * example: HWADDR=01:02:03:04:05:06:07:08:09:0A:01:02:03:04:05:06:07:08:09:11
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_MAC_ADDRESS,
+ g_param_spec_string (NM_SETTING_INFINIBAND_MAC_ADDRESS, "", "",
+ NULL,
+ 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);
+
+ /**
+ * NMSettingInfiniband:mtu:
+ *
+ * If non-zero, only transmit packets of the specified size or smaller,
+ * breaking larger packets up into multiple frames.
+ **/
+ /* ---ifcfg-rh---
+ * property: mtu
+ * variable: MTU
+ * description: MTU of the interface.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_MTU,
+ g_param_spec_uint (NM_SETTING_INFINIBAND_MTU, "", "",
+ 0, G_MAXUINT32, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingInfiniband:transport-mode:
+ *
+ * The IP-over-InfiniBand transport mode. Either "datagram" or
+ * "connected".
+ **/
+ /* ---ifcfg-rh---
+ * property: transport-mode
+ * variable: CONNECTED_MODE
+ * default: CONNECTED_MODE=no
+ * description: CONNECTED_MODE=yes for "connected" mode, CONNECTED_MODE=no for
+ * "datagram" mode
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_TRANSPORT_MODE,
+ g_param_spec_string (NM_SETTING_INFINIBAND_TRANSPORT_MODE, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingInfiniband:p-key:
+ *
+ * The InfiniBand P_Key to use for this device. A value of -1 means to use
+ * the default P_Key (aka "the P_Key at index 0"). Otherwise it is a 16-bit
+ * unsigned integer, whose high bit is set if it is a "full membership"
+ * P_Key.
+ **/
+ /* ---ifcfg-rh---
+ * property: p-key
+ * variable: PKEY_ID (and PKEY=yes)
+ * default: PKEY=no
+ * description: InfiniBand P_Key. The value can be a hex number prefixed with "0x"
+ * or a decimal number.
+ * When PKEY_ID is specified, PHYSDEV and DEVICE also must be specified.
+ * example: PKEY=yes PKEY_ID=2 PHYSDEV=mlx4_ib0 DEVICE=mlx4_ib0.8002
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_P_KEY,
+ g_param_spec_int (NM_SETTING_INFINIBAND_P_KEY, "", "",
+ -1, 0xFFFF, -1,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingInfiniband:parent:
+ *
+ * The interface name of the parent device of this device. Normally %NULL,
+ * but if the #NMSettingInfiniband:p_key property is set, then you must
+ * specify the base device by setting either this property or
+ * #NMSettingInfiniband:mac-address.
+ **/
+ /* ---ifcfg-rh---
+ * property: parent
+ * variable: PHYSDEV (PKEY=yes)
+ * default: PKEY=no
+ * description: InfiniBand parent device.
+ * example: PHYSDEV=ib0
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_PARENT,
+ g_param_spec_string (NM_SETTING_INFINIBAND_PARENT, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+}
diff --git a/libnm-core/nm-setting-infiniband.h b/libnm-core/nm-setting-infiniband.h
new file mode 100644
index 000000000..c5ad418b2
--- /dev/null
+++ b/libnm-core/nm-setting-infiniband.h
@@ -0,0 +1,72 @@
+/* -*- 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 2011 Red Hat, Inc.
+ */
+
+#ifndef __NM_SETTING_INFINIBAND_H__
+#define __NM_SETTING_INFINIBAND_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_INFINIBAND (nm_setting_infiniband_get_type ())
+#define NM_SETTING_INFINIBAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_INFINIBAND, NMSettingInfiniband))
+#define NM_SETTING_INFINIBAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_INFINIBAND, NMSettingInfinibandClass))
+#define NM_IS_SETTING_INFINIBAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_INFINIBAND))
+#define NM_IS_SETTING_INFINIBAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_INFINIBAND))
+#define NM_SETTING_INFINIBAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_INFINIBAND, NMSettingInfinibandClass))
+
+#define NM_SETTING_INFINIBAND_SETTING_NAME "infiniband"
+
+#define NM_SETTING_INFINIBAND_MAC_ADDRESS "mac-address"
+#define NM_SETTING_INFINIBAND_MTU "mtu"
+#define NM_SETTING_INFINIBAND_TRANSPORT_MODE "transport-mode"
+#define NM_SETTING_INFINIBAND_P_KEY "p-key"
+#define NM_SETTING_INFINIBAND_PARENT "parent"
+
+struct _NMSettingInfiniband {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingInfinibandClass;
+
+GType nm_setting_infiniband_get_type (void);
+
+NMSetting * nm_setting_infiniband_new (void);
+const char * nm_setting_infiniband_get_mac_address (NMSettingInfiniband *setting);
+guint32 nm_setting_infiniband_get_mtu (NMSettingInfiniband *setting);
+const char * nm_setting_infiniband_get_transport_mode (NMSettingInfiniband *setting);
+int nm_setting_infiniband_get_p_key (NMSettingInfiniband *setting);
+const char * nm_setting_infiniband_get_parent (NMSettingInfiniband *setting);
+
+const char * nm_setting_infiniband_get_virtual_interface_name (NMSettingInfiniband *setting);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_INFINIBAND_H__ */
diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c
new file mode 100644
index 000000000..e6f0401a0
--- /dev/null
+++ b/libnm-core/nm-setting-ip-config.c
@@ -0,0 +1,2363 @@
+/* -*- 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 2007 - 2014 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <arpa/inet.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-ip-config.h"
+#include "nm-setting-ip4-config.h"
+#include "nm-setting-ip6-config.h"
+#include "nm-utils.h"
+#include "nm-glib-compat.h"
+#include "nm-setting-private.h"
+#include "nm-utils-private.h"
+
+/**
+ * SECTION:nm-setting-ip-config
+ * @short_description: Abstract base class for IPv4 and IPv6
+ * addressing, routing, and name service properties
+ * @include: nm-setting-ip-config.h
+ * @see_also: #NMSettingIP4Config, #NMSettingIP6Config
+ *
+ * #NMSettingIPConfig is the abstract base class of
+ * #NMSettingIP4Config and #NMSettingIP6Config, providing properties
+ * related to IP addressing, routing, and Domain Name Service.
+ **/
+
+static char *
+canonicalize_ip (int family, const char *ip, gboolean null_any)
+{
+ guint8 addr_bytes[sizeof (struct in6_addr)];
+ char addr_str[NM_UTILS_INET_ADDRSTRLEN];
+ int ret;
+
+ if (!ip) {
+ g_return_val_if_fail (null_any == TRUE, NULL);
+ return NULL;
+ }
+
+ ret = inet_pton (family, ip, addr_bytes);
+ g_return_val_if_fail (ret == 1, NULL);
+
+ if (null_any) {
+ int addrlen = (family == AF_INET ? sizeof (struct in_addr) : sizeof (struct in6_addr));
+
+ if (!memcmp (addr_bytes, &in6addr_any, addrlen))
+ return NULL;
+ }
+
+ return g_strdup (inet_ntop (family, addr_bytes, addr_str, sizeof (addr_str)));
+}
+
+static gboolean
+valid_ip (int family, const char *ip, GError **error)
+{
+ if (!nm_utils_ipaddr_valid (family, ip)) {
+ g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED,
+ family == AF_INET ? _("Invalid IPv4 address '%s'") : _("Invalid IPv6 address '%s"),
+ ip);
+ return FALSE;
+ } else
+ return TRUE;
+}
+
+static gboolean
+valid_prefix (int family, guint prefix, GError **error, gboolean allow_zero_prefix)
+{
+ if ( (family == AF_INET && prefix > 32)
+ || (family == AF_INET6 && prefix > 128)
+ || (!allow_zero_prefix && prefix == 0)) {
+ g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED,
+ family == AF_INET ? _("Invalid IPv4 address prefix '%u'") : _("Invalid IPv6 address prefix '%u"),
+ prefix);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+valid_metric (gint64 metric, GError **error)
+{
+ if (metric < -1 || metric > G_MAXUINT32) {
+ if (error) {
+ char buf[64];
+
+ /* We can't concatenate G_GINT64_FORMAT into a translatable string */
+ g_snprintf (buf, sizeof (buf), "%" G_GINT64_FORMAT, metric);
+ g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_FAILED,
+ _("Invalid routing metric '%s'"), buf);
+ }
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+G_DEFINE_BOXED_TYPE (NMIPAddress, nm_ip_address, nm_ip_address_dup, nm_ip_address_unref)
+
+struct NMIPAddress {
+ guint refcount;
+
+ char *address;
+ int prefix, family;
+
+ GHashTable *attributes;
+};
+
+/**
+ * nm_ip_address_new:
+ * @family: the IP address family (<literal>AF_INET</literal> or
+ * <literal>AF_INET6</literal>)
+ * @addr: the IP address
+ * @prefix: the address prefix length
+ * @error: location to store error, or %NULL
+ *
+ * Creates a new #NMIPAddress object.
+ *
+ * Returns: (transfer full): the new #NMIPAddress object, or %NULL on error
+ **/
+NMIPAddress *
+nm_ip_address_new (int family,
+ const char *addr, guint prefix,
+ GError **error)
+{
+ NMIPAddress *address;
+
+ g_return_val_if_fail (family == AF_INET || family == AF_INET6, NULL);
+ g_return_val_if_fail (addr != NULL, NULL);
+
+ if (!valid_ip (family, addr, error))
+ return NULL;
+ if (!valid_prefix (family, prefix, error, FALSE))
+ return NULL;
+
+ address = g_slice_new0 (NMIPAddress);
+ address->refcount = 1;
+
+ address->family = family;
+ address->address = canonicalize_ip (family, addr, FALSE);
+ address->prefix = prefix;
+
+ return address;
+}
+
+/**
+ * nm_ip_address_new_binary:
+ * @family: the IP address family (<literal>AF_INET</literal> or
+ * <literal>AF_INET6</literal>)
+ * @addr: the IP address
+ * @prefix: the address prefix length
+ * @error: location to store error, or %NULL
+ *
+ * Creates a new #NMIPAddress object. @addr must point to a buffer of the
+ * correct size for @family.
+ *
+ * Returns: (transfer full): the new #NMIPAddress object, or %NULL on error
+ **/
+NMIPAddress *
+nm_ip_address_new_binary (int family,
+ gconstpointer addr, guint prefix,
+ GError **error)
+{
+ NMIPAddress *address;
+ char string[NM_UTILS_INET_ADDRSTRLEN];
+
+ g_return_val_if_fail (family == AF_INET || family == AF_INET6, NULL);
+ g_return_val_if_fail (addr != NULL, NULL);
+
+ if (!valid_prefix (family, prefix, error, FALSE))
+ return NULL;
+
+ address = g_slice_new0 (NMIPAddress);
+ address->refcount = 1;
+
+ address->family = family;
+ address->address = g_strdup (inet_ntop (family, addr, string, sizeof (string)));
+ address->prefix = prefix;
+
+ return address;
+}
+
+/**
+ * nm_ip_address_ref:
+ * @address: the #NMIPAddress
+ *
+ * Increases the reference count of the object.
+ **/
+void
+nm_ip_address_ref (NMIPAddress *address)
+{
+ g_return_if_fail (address != NULL);
+ g_return_if_fail (address->refcount > 0);
+
+ address->refcount++;
+}
+
+/**
+ * nm_ip_address_unref:
+ * @address: the #NMIPAddress
+ *
+ * Decreases the reference count of the object. If the reference count
+ * reaches zero, the object will be destroyed.
+ **/
+void
+nm_ip_address_unref (NMIPAddress *address)
+{
+ g_return_if_fail (address != NULL);
+ g_return_if_fail (address->refcount > 0);
+
+ address->refcount--;
+ if (address->refcount == 0) {
+ g_free (address->address);
+ if (address->attributes)
+ g_hash_table_unref (address->attributes);
+ g_slice_free (NMIPAddress, address);
+ }
+}
+
+/**
+ * nm_ip_address_equal:
+ * @address: the #NMIPAddress
+ * @other: the #NMIPAddress to compare @address to.
+ *
+ * Determines if two #NMIPAddress objects contain the same address and prefix
+ * (attributes are not compared).
+ *
+ * Returns: %TRUE if the objects contain the same values, %FALSE if they do not.
+ **/
+gboolean
+nm_ip_address_equal (NMIPAddress *address, NMIPAddress *other)
+{
+ g_return_val_if_fail (address != NULL, FALSE);
+ g_return_val_if_fail (address->refcount > 0, FALSE);
+
+ g_return_val_if_fail (other != NULL, FALSE);
+ g_return_val_if_fail (other->refcount > 0, FALSE);
+
+ if ( address->family != other->family
+ || address->prefix != other->prefix
+ || strcmp (address->address, other->address) != 0)
+ return FALSE;
+ return TRUE;
+}
+
+/**
+ * nm_ip_address_dup:
+ * @address: the #NMIPAddress
+ *
+ * Creates a copy of @address
+ *
+ * Returns: (transfer full): a copy of @address
+ **/
+NMIPAddress *
+nm_ip_address_dup (NMIPAddress *address)
+{
+ NMIPAddress *copy;
+
+ g_return_val_if_fail (address != NULL, NULL);
+ g_return_val_if_fail (address->refcount > 0, NULL);
+
+ copy = nm_ip_address_new (address->family,
+ address->address, address->prefix,
+ NULL);
+ if (address->attributes) {
+ GHashTableIter iter;
+ const char *key;
+ GVariant *value;
+
+ g_hash_table_iter_init (&iter, address->attributes);
+ while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value))
+ nm_ip_address_set_attribute (copy, key, value);
+ }
+
+ return copy;
+}
+
+/**
+ * nm_ip_address_get_family:
+ * @address: the #NMIPAddress
+ *
+ * Gets the IP address family (eg, AF_INET) property of this address
+ * object.
+ *
+ * Returns: the IP address family
+ **/
+int
+nm_ip_address_get_family (NMIPAddress *address)
+{
+ g_return_val_if_fail (address != NULL, 0);
+ g_return_val_if_fail (address->refcount > 0, 0);
+
+ return address->family;
+}
+
+/**
+ * nm_ip_address_get_address:
+ * @address: the #NMIPAddress
+ *
+ * Gets the IP address property of this address object.
+ *
+ * Returns: the IP address
+ **/
+const char *
+nm_ip_address_get_address (NMIPAddress *address)
+{
+ g_return_val_if_fail (address != NULL, NULL);
+ g_return_val_if_fail (address->refcount > 0, NULL);
+
+ return address->address;
+}
+
+/**
+ * nm_ip_address_set_address:
+ * @address: the #NMIPAddress
+ * @addr: the IP address, as a string
+ *
+ * Sets the IP address property of this address object.
+ *
+ * @addr must be a valid address of @address's family. If you aren't sure you
+ * have a valid address, use nm_utils_ipaddr_valid() to check it.
+ **/
+void
+nm_ip_address_set_address (NMIPAddress *address,
+ const char *addr)
+{
+ g_return_if_fail (address != NULL);
+ g_return_if_fail (addr != NULL);
+ g_return_if_fail (nm_utils_ipaddr_valid (address->family, addr));
+
+ g_free (address->address);
+ address->address = canonicalize_ip (address->family, addr, FALSE);
+}
+
+/**
+ * nm_ip_address_get_address_binary: (skip)
+ * @address: the #NMIPAddress
+ * @addr: a buffer in which to store the address in binary format.
+ *
+ * Gets the IP address property of this address object.
+ *
+ * @addr must point to a buffer that is the correct size for @address's family.
+ **/
+void
+nm_ip_address_get_address_binary (NMIPAddress *address,
+ gpointer addr)
+{
+ g_return_if_fail (address != NULL);
+ g_return_if_fail (addr != NULL);
+
+ inet_pton (address->family, address->address, addr);
+}
+
+/**
+ * nm_ip_address_set_address_binary: (skip)
+ * @address: the #NMIPAddress
+ * @addr: the address, in binary format
+ *
+ * Sets the IP address property of this address object.
+ *
+ * @addr must point to a buffer that is the correct size for @address's family.
+ **/
+void
+nm_ip_address_set_address_binary (NMIPAddress *address,
+ gconstpointer addr)
+{
+ char string[NM_UTILS_INET_ADDRSTRLEN];
+
+ g_return_if_fail (address != NULL);
+ g_return_if_fail (addr != NULL);
+
+ g_free (address->address);
+ address->address = g_strdup (inet_ntop (address->family, addr, string, sizeof (string)));
+}
+
+/**
+ * nm_ip_address_get_prefix:
+ * @address: the #NMIPAddress
+ *
+ * Gets the IP address prefix (ie "24" or "30" etc) property of this address
+ * object.
+ *
+ * Returns: the IP address prefix
+ **/
+guint
+nm_ip_address_get_prefix (NMIPAddress *address)
+{
+ g_return_val_if_fail (address != NULL, 0);
+ g_return_val_if_fail (address->refcount > 0, 0);
+
+ return address->prefix;
+}
+
+/**
+ * nm_ip_address_set_prefix:
+ * @address: the #NMIPAddress
+ * @prefix: the IP address prefix
+ *
+ * Sets the IP address prefix property of this address object.
+ **/
+void
+nm_ip_address_set_prefix (NMIPAddress *address,
+ guint prefix)
+{
+ g_return_if_fail (address != NULL);
+ g_return_if_fail (valid_prefix (address->family, prefix, NULL, FALSE));
+
+ address->prefix = prefix;
+}
+
+/**
+ * nm_ip_address_get_attribute_names:
+ * @address: the #NMIPAddress
+ *
+ * Gets an array of attribute names defined on @address.
+ *
+ * Returns: (transfer full): a %NULL-terminated array of attribute names,
+ **/
+char **
+nm_ip_address_get_attribute_names (NMIPAddress *address)
+{
+ GHashTableIter iter;
+ const char *key;
+ GPtrArray *names;
+
+ g_return_val_if_fail (address != NULL, NULL);
+
+ names = g_ptr_array_new ();
+
+ if (address->attributes) {
+ g_hash_table_iter_init (&iter, address->attributes);
+ while (g_hash_table_iter_next (&iter, (gpointer *) &key, NULL))
+ g_ptr_array_add (names, g_strdup (key));
+ }
+ g_ptr_array_add (names, NULL);
+
+ return (char **) g_ptr_array_free (names, FALSE);
+}
+
+/**
+ * nm_ip_address_get_attribute:
+ * @address: the #NMIPAddress
+ * @name: the name of an address attribute
+ *
+ * Gets the value of the attribute with name @name on @address
+ *
+ * Returns: (transfer none): the value of the attribute with name @name on
+ * @address, or %NULL if @address has no such attribute.
+ **/
+GVariant *
+nm_ip_address_get_attribute (NMIPAddress *address, const char *name)
+{
+ g_return_val_if_fail (address != NULL, NULL);
+ g_return_val_if_fail (name != NULL && *name != '\0', NULL);
+
+ if (address->attributes)
+ return g_hash_table_lookup (address->attributes, name);
+ else
+ return NULL;
+}
+
+/**
+ * nm_ip_address_set_attribute:
+ * @address: the #NMIPAddress
+ * @name: the name of an address attribute
+ * @value: (transfer none) (allow-none): the value
+ *
+ * Sets or clears the named attribute on @address to the given value.
+ **/
+void
+nm_ip_address_set_attribute (NMIPAddress *address, const char *name, GVariant *value)
+{
+ g_return_if_fail (address != NULL);
+ g_return_if_fail (name != NULL && *name != '\0');
+ g_return_if_fail (strcmp (name, "address") != 0 && strcmp (name, "prefix") != 0);
+
+ if (!address->attributes) {
+ address->attributes = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify) g_variant_unref);
+ }
+
+ if (value)
+ g_hash_table_insert (address->attributes, g_strdup (name), g_variant_ref_sink (value));
+ else
+ g_hash_table_remove (address->attributes, name);
+}
+
+
+G_DEFINE_BOXED_TYPE (NMIPRoute, nm_ip_route, nm_ip_route_dup, nm_ip_route_unref)
+
+struct NMIPRoute {
+ guint refcount;
+
+ int family;
+ char *dest;
+ guint prefix;
+ char *next_hop;
+ gint64 metric;
+
+ GHashTable *attributes;
+};
+
+/**
+ * nm_ip_route_new:
+ * @family: the IP address family (<literal>AF_INET</literal> or
+ * <literal>AF_INET6</literal>)
+ * @dest: the IP address of the route's destination
+ * @prefix: the address prefix length
+ * @next_hop: (allow-none): the IP address of the next hop (or %NULL)
+ * @metric: the route metric (or -1 for "default")
+ * @error: location to store error, or %NULL
+ *
+ * Creates a new #NMIPRoute object.
+ *
+ * Returns: (transfer full): the new #NMIPRoute object, or %NULL on error
+ **/
+NMIPRoute *
+nm_ip_route_new (int family,
+ const char *dest,
+ guint prefix,
+ const char *next_hop,
+ gint64 metric,
+ GError **error)
+{
+ NMIPRoute *route;
+
+ g_return_val_if_fail (family == AF_INET || family == AF_INET6, NULL);
+
+ if (!valid_ip (family, dest, error))
+ return NULL;
+ if (!valid_prefix (family, prefix, error, TRUE))
+ return NULL;
+ if (next_hop && !valid_ip (family, next_hop, error))
+ return NULL;
+ if (!valid_metric (metric, error))
+ return NULL;
+
+ route = g_slice_new0 (NMIPRoute);
+ route->refcount = 1;
+
+ route->family = family;
+ route->dest = canonicalize_ip (family, dest, FALSE);
+ route->prefix = prefix;
+ route->next_hop = canonicalize_ip (family, next_hop, TRUE);
+ route->metric = metric;
+
+ return route;
+}
+
+/**
+ * nm_ip_route_new_binary:
+ * @family: the IP address family (<literal>AF_INET</literal> or
+ * <literal>AF_INET6</literal>)
+ * @dest: the IP address of the route's destination
+ * @prefix: the address prefix length
+ * @next_hop: (allow-none): the IP address of the next hop (or %NULL)
+ * @metric: the route metric (or -1 for "default")
+ * @error: location to store error, or %NULL
+ *
+ * Creates a new #NMIPRoute object. @dest and @next_hop (if non-%NULL) must
+ * point to buffers of the correct size for @family.
+ *
+ * Returns: (transfer full): the new #NMIPRoute object, or %NULL on error
+ **/
+NMIPRoute *
+nm_ip_route_new_binary (int family,
+ gconstpointer dest,
+ guint prefix,
+ gconstpointer next_hop,
+ gint64 metric,
+ GError **error)
+{
+ NMIPRoute *route;
+ char string[NM_UTILS_INET_ADDRSTRLEN];
+
+ g_return_val_if_fail (family == AF_INET || family == AF_INET6, NULL);
+
+ if (!valid_prefix (family, prefix, error, TRUE))
+ return NULL;
+ if (!valid_metric (metric, error))
+ return NULL;
+
+ route = g_slice_new0 (NMIPRoute);
+ route->refcount = 1;
+
+ route->family = family;
+ route->dest = g_strdup (inet_ntop (family, dest, string, sizeof (string)));
+ route->prefix = prefix;
+ if (next_hop)
+ route->next_hop = g_strdup (inet_ntop (family, next_hop, string, sizeof (string)));
+ route->metric = metric;
+
+ return route;
+}
+
+/**
+ * nm_ip_route_ref:
+ * @route: the #NMIPRoute
+ *
+ * Increases the reference count of the object.
+ **/
+void
+nm_ip_route_ref (NMIPRoute *route)
+{
+ g_return_if_fail (route != NULL);
+ g_return_if_fail (route->refcount > 0);
+
+ route->refcount++;
+}
+
+/**
+ * nm_ip_route_unref:
+ * @route: the #NMIPRoute
+ *
+ * Decreases the reference count of the object. If the reference count
+ * reaches zero, the object will be destroyed.
+ **/
+void
+nm_ip_route_unref (NMIPRoute *route)
+{
+ g_return_if_fail (route != NULL);
+ g_return_if_fail (route->refcount > 0);
+
+ route->refcount--;
+ if (route->refcount == 0) {
+ g_free (route->dest);
+ g_free (route->next_hop);
+ if (route->attributes)
+ g_hash_table_unref (route->attributes);
+ g_slice_free (NMIPRoute, route);
+ }
+}
+
+/**
+ * nm_ip_route_equal:
+ * @route: the #NMIPRoute
+ * @other: the #NMIPRoute to compare @route to.
+ *
+ * Determines if two #NMIPRoute objects contain the same destination, prefix,
+ * next hop, and metric. (Attributes are not compared.)
+ *
+ * Returns: %TRUE if the objects contain the same values, %FALSE if they do not.
+ **/
+gboolean
+nm_ip_route_equal (NMIPRoute *route, NMIPRoute *other)
+{
+ g_return_val_if_fail (route != NULL, FALSE);
+ g_return_val_if_fail (route->refcount > 0, FALSE);
+
+ g_return_val_if_fail (other != NULL, FALSE);
+ g_return_val_if_fail (other->refcount > 0, FALSE);
+
+ if ( route->prefix != other->prefix
+ || route->metric != other->metric
+ || strcmp (route->dest, other->dest) != 0
+ || g_strcmp0 (route->next_hop, other->next_hop) != 0)
+ return FALSE;
+ return TRUE;
+}
+
+/**
+ * nm_ip_route_dup:
+ * @route: the #NMIPRoute
+ *
+ * Creates a copy of @route
+ *
+ * Returns: (transfer full): a copy of @route
+ **/
+NMIPRoute *
+nm_ip_route_dup (NMIPRoute *route)
+{
+ NMIPRoute *copy;
+
+ g_return_val_if_fail (route != NULL, NULL);
+ g_return_val_if_fail (route->refcount > 0, NULL);
+
+ copy = nm_ip_route_new (route->family,
+ route->dest, route->prefix,
+ route->next_hop, route->metric,
+ NULL);
+ if (route->attributes) {
+ GHashTableIter iter;
+ const char *key;
+ GVariant *value;
+
+ g_hash_table_iter_init (&iter, route->attributes);
+ while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value))
+ nm_ip_route_set_attribute (copy, key, value);
+ }
+
+ return copy;
+}
+
+/**
+ * nm_ip_route_get_family:
+ * @route: the #NMIPRoute
+ *
+ * Gets the IP address family (eg, AF_INET) property of this route
+ * object.
+ *
+ * Returns: the IP address family
+ **/
+int
+nm_ip_route_get_family (NMIPRoute *route)
+{
+ g_return_val_if_fail (route != NULL, 0);
+ g_return_val_if_fail (route->refcount > 0, 0);
+
+ return route->family;
+}
+
+/**
+ * nm_ip_route_get_dest:
+ * @route: the #NMIPRoute
+ *
+ * Gets the IP destination address property of this route object.
+ *
+ * Returns: the IP address of the route's destination
+ **/
+const char *
+nm_ip_route_get_dest (NMIPRoute *route)
+{
+ g_return_val_if_fail (route != NULL, NULL);
+ g_return_val_if_fail (route->refcount > 0, NULL);
+
+ return route->dest;
+}
+
+/**
+ * nm_ip_route_set_dest:
+ * @route: the #NMIPRoute
+ * @dest: the route's destination, as a string
+ *
+ * Sets the destination property of this route object.
+ *
+ * @dest must be a valid address of @route's family. If you aren't sure you
+ * have a valid address, use nm_utils_ipaddr_valid() to check it.
+ **/
+void
+nm_ip_route_set_dest (NMIPRoute *route,
+ const char *dest)
+{
+ g_return_if_fail (route != NULL);
+ g_return_if_fail (dest != NULL);
+ g_return_if_fail (nm_utils_ipaddr_valid (route->family, dest));
+
+ g_free (route->dest);
+ route->dest = canonicalize_ip (route->family, dest, FALSE);
+}
+
+/**
+ * nm_ip_route_get_dest_binary: (skip)
+ * @route: the #NMIPRoute
+ * @dest: a buffer in which to store the destination in binary format.
+ *
+ * Gets the destination property of this route object.
+ *
+ * @dest must point to a buffer that is the correct size for @route's family.
+ **/
+void
+nm_ip_route_get_dest_binary (NMIPRoute *route,
+ gpointer dest)
+{
+ g_return_if_fail (route != NULL);
+ g_return_if_fail (dest != NULL);
+
+ inet_pton (route->family, route->dest, dest);
+}
+
+/**
+ * nm_ip_route_set_dest_binary: (skip)
+ * @route: the #NMIPRoute
+ * @dest: the route's destination, in binary format
+ *
+ * Sets the destination property of this route object.
+ *
+ * @dest must point to a buffer that is the correct size for @route's family.
+ **/
+void
+nm_ip_route_set_dest_binary (NMIPRoute *route,
+ gconstpointer dest)
+{
+ char string[NM_UTILS_INET_ADDRSTRLEN];
+
+ g_return_if_fail (route != NULL);
+ g_return_if_fail (dest != NULL);
+
+ g_free (route->dest);
+ route->dest = g_strdup (inet_ntop (route->family, dest, string, sizeof (string)));
+}
+
+/**
+ * nm_ip_route_get_prefix:
+ * @route: the #NMIPRoute
+ *
+ * Gets the IP prefix (ie "24" or "30" etc) of this route.
+ *
+ * Returns: the IP prefix
+ **/
+guint
+nm_ip_route_get_prefix (NMIPRoute *route)
+{
+ g_return_val_if_fail (route != NULL, 0);
+ g_return_val_if_fail (route->refcount > 0, 0);
+
+ return route->prefix;
+}
+
+/**
+ * nm_ip_route_set_prefix:
+ * @route: the #NMIPRoute
+ * @prefix: the route prefix
+ *
+ * Sets the prefix property of this route object.
+ **/
+void
+nm_ip_route_set_prefix (NMIPRoute *route,
+ guint prefix)
+{
+ g_return_if_fail (route != NULL);
+ g_return_if_fail (valid_prefix (route->family, prefix, NULL, TRUE));
+
+ route->prefix = prefix;
+}
+
+/**
+ * nm_ip_route_get_next_hop:
+ * @route: the #NMIPRoute
+ *
+ * Gets the IP address of the next hop of this route; this will be %NULL if the
+ * route has no next hop.
+ *
+ * Returns: the IP address of the next hop, or %NULL if this is a device route.
+ **/
+const char *
+nm_ip_route_get_next_hop (NMIPRoute *route)
+{
+ g_return_val_if_fail (route != NULL, NULL);
+ g_return_val_if_fail (route->refcount > 0, NULL);
+
+ return route->next_hop;
+}
+
+/**
+ * nm_ip_route_set_next_hop:
+ * @route: the #NMIPRoute
+ * @next_hop: (allow-none): the route's next hop, as a string
+ *
+ * Sets the next-hop property of this route object.
+ *
+ * @next_hop (if non-%NULL) must be a valid address of @route's family. If you
+ * aren't sure you have a valid address, use nm_utils_ipaddr_valid() to check
+ * it.
+ **/
+void
+nm_ip_route_set_next_hop (NMIPRoute *route,
+ const char *next_hop)
+{
+ g_return_if_fail (route != NULL);
+ g_return_if_fail (!next_hop || nm_utils_ipaddr_valid (route->family, next_hop));
+
+ g_free (route->next_hop);
+ route->next_hop = canonicalize_ip (route->family, next_hop, TRUE);
+}
+
+/**
+ * nm_ip_route_get_next_hop_binary: (skip)
+ * @route: the #NMIPRoute
+ * @next_hop: a buffer in which to store the next hop in binary format.
+ *
+ * Gets the next hop property of this route object.
+ *
+ * @next_hop must point to a buffer that is the correct size for @route's family.
+ *
+ * Returns: %TRUE if @route has a next hop, %FALSE if not (in which case
+ * @next_hop will be zeroed out)
+ **/
+gboolean
+nm_ip_route_get_next_hop_binary (NMIPRoute *route,
+ gpointer next_hop)
+{
+ g_return_val_if_fail (route != NULL, FALSE);
+ g_return_val_if_fail (next_hop != NULL, FALSE);
+
+ if (route->next_hop) {
+ inet_pton (route->family, route->next_hop, next_hop);
+ return TRUE;
+ } else {
+ memset (next_hop, 0,
+ route->family == AF_INET ? sizeof (struct in_addr) : sizeof (struct in6_addr));
+ return FALSE;
+ }
+}
+
+/**
+ * nm_ip_route_set_next_hop_binary: (skip)
+ * @route: the #NMIPRoute
+ * @next_hop: the route's next hop, in binary format
+ *
+ * Sets the destination property of this route object.
+ *
+ * @next_hop (if non-%NULL) must point to a buffer that is the correct size for
+ * @route's family.
+ **/
+void
+nm_ip_route_set_next_hop_binary (NMIPRoute *route,
+ gconstpointer next_hop)
+{
+ char string[NM_UTILS_INET_ADDRSTRLEN];
+
+ g_return_if_fail (route != NULL);
+
+ g_free (route->next_hop);
+ if (next_hop)
+ route->next_hop = g_strdup (inet_ntop (route->family, next_hop, string, sizeof (string)));
+ else
+ route->next_hop = NULL;
+}
+
+/**
+ * nm_ip_route_get_metric:
+ * @route: the #NMIPRoute
+ *
+ * Gets the route metric property of this route object; lower values
+ * indicate "better" or more preferred routes; -1 indicates "default"
+ * (meaning NetworkManager will set it appropriately).
+ *
+ * Returns: the route metric
+ **/
+gint64
+nm_ip_route_get_metric (NMIPRoute *route)
+{
+ g_return_val_if_fail (route != NULL, 0);
+ g_return_val_if_fail (route->refcount > 0, 0);
+
+ return route->metric;
+}
+
+/**
+ * nm_ip_route_set_metric:
+ * @route: the #NMIPRoute
+ * @metric: the route metric (or -1 for "default")
+ *
+ * Sets the metric property of this route object.
+ **/
+void
+nm_ip_route_set_metric (NMIPRoute *route,
+ gint64 metric)
+{
+ g_return_if_fail (route != NULL);
+ g_return_if_fail (valid_metric (metric, NULL));
+
+ route->metric = metric;
+}
+
+/**
+ * nm_ip_route_get_attribute_names:
+ * @route: the #NMIPRoute
+ *
+ * Gets an array of attribute names defined on @route.
+ *
+ * Returns: (transfer full): a %NULL-terminated array of attribute names
+ **/
+char **
+nm_ip_route_get_attribute_names (NMIPRoute *route)
+{
+ GHashTableIter iter;
+ const char *key;
+ GPtrArray *names;
+
+ g_return_val_if_fail (route != NULL, NULL);
+
+ names = g_ptr_array_new ();
+
+ if (route->attributes) {
+ g_hash_table_iter_init (&iter, route->attributes);
+ while (g_hash_table_iter_next (&iter, (gpointer *) &key, NULL))
+ g_ptr_array_add (names, g_strdup (key));
+ }
+ g_ptr_array_add (names, NULL);
+
+ return (char **) g_ptr_array_free (names, FALSE);
+}
+
+/**
+ * nm_ip_route_get_attribute:
+ * @route: the #NMIPRoute
+ * @name: the name of an route attribute
+ *
+ * Gets the value of the attribute with name @name on @route
+ *
+ * Returns: (transfer none): the value of the attribute with name @name on
+ * @route, or %NULL if @route has no such attribute.
+ **/
+GVariant *
+nm_ip_route_get_attribute (NMIPRoute *route, const char *name)
+{
+ g_return_val_if_fail (route != NULL, NULL);
+ g_return_val_if_fail (name != NULL && *name != '\0', NULL);
+
+ if (route->attributes)
+ return g_hash_table_lookup (route->attributes, name);
+ else
+ return NULL;
+}
+
+/**
+ * nm_ip_route_set_attribute:
+ * @route: the #NMIPRoute
+ * @name: the name of a route attribute
+ * @value: (transfer none) (allow-none): the value
+ *
+ * Sets the named attribute on @route to the given value.
+ **/
+void
+nm_ip_route_set_attribute (NMIPRoute *route, const char *name, GVariant *value)
+{
+ g_return_if_fail (route != NULL);
+ g_return_if_fail (name != NULL && *name != '\0');
+ g_return_if_fail ( strcmp (name, "dest") != 0 && strcmp (name, "prefix") != 0
+ && strcmp (name, "next-hop") != 0 && strcmp (name, "metric") != 0);
+
+ if (!route->attributes) {
+ route->attributes = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify) g_variant_unref);
+ }
+
+ if (value)
+ g_hash_table_insert (route->attributes, g_strdup (name), g_variant_ref_sink (value));
+ else
+ g_hash_table_remove (route->attributes, name);
+}
+
+
+G_DEFINE_ABSTRACT_TYPE (NMSettingIPConfig, nm_setting_ip_config, NM_TYPE_SETTING)
+
+#define NM_SETTING_IP_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_IP_CONFIG, NMSettingIPConfigPrivate))
+
+typedef struct {
+ char *method;
+ GPtrArray *dns; /* array of IP address strings */
+ GPtrArray *dns_search; /* array of domain name strings */
+ GPtrArray *addresses; /* array of NMIPAddress */
+ GPtrArray *routes; /* array of NMIPRoute */
+ gint64 route_metric;
+ char *gateway;
+ gboolean ignore_auto_routes;
+ gboolean ignore_auto_dns;
+ char *dhcp_hostname;
+ gboolean dhcp_send_hostname;
+ gboolean never_default;
+ gboolean may_fail;
+} NMSettingIPConfigPrivate;
+
+enum {
+ PROP_0,
+ PROP_METHOD,
+ PROP_DNS,
+ PROP_DNS_SEARCH,
+ PROP_ADDRESSES,
+ PROP_GATEWAY,
+ PROP_ROUTES,
+ PROP_ROUTE_METRIC,
+ PROP_IGNORE_AUTO_ROUTES,
+ PROP_IGNORE_AUTO_DNS,
+ PROP_DHCP_HOSTNAME,
+ PROP_DHCP_SEND_HOSTNAME,
+ PROP_NEVER_DEFAULT,
+ PROP_MAY_FAIL,
+
+ LAST_PROP
+};
+
+#define NM_SETTING_IP_CONFIG_GET_FAMILY(setting) (NM_IS_SETTING_IP4_CONFIG (setting) ? AF_INET : AF_INET6)
+
+/**
+ * nm_setting_ip_config_get_method:
+ * @setting: the #NMSettingIPConfig
+ *
+ * Returns: the #NMSettingIPConfig:method property of the setting; see
+ * #NMSettingIP4Config and #NMSettingIP6Config for details of the
+ * methods available with each type.
+ **/
+const char *
+nm_setting_ip_config_get_method (NMSettingIPConfig *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), NULL);
+
+ return NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->method;
+}
+
+/**
+ * nm_setting_ip_config_get_num_dns:
+ * @setting: the #NMSettingIPConfig
+ *
+ * Returns: the number of configured DNS servers
+ **/
+guint
+nm_setting_ip_config_get_num_dns (NMSettingIPConfig *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), 0);
+
+ return NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->dns->len;
+}
+
+/**
+ * nm_setting_ip_config_get_dns:
+ * @setting: the #NMSettingIPConfig
+ * @i: index number of the DNS server to return
+ *
+ * Returns: the IP address of the DNS server at index @i
+ **/
+const char *
+nm_setting_ip_config_get_dns (NMSettingIPConfig *setting, int i)
+{
+ NMSettingIPConfigPrivate *priv;
+
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), NULL);
+
+ priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+ g_return_val_if_fail (i < priv->dns->len, NULL);
+
+ return priv->dns->pdata[i];
+}
+
+/**
+ * nm_setting_ip_config_add_dns:
+ * @setting: the #NMSettingIPConfig
+ * @dns: the IP address of the DNS server to add
+ *
+ * Adds a new DNS server to the setting.
+ *
+ * Returns: %TRUE if the DNS server was added; %FALSE if the server was already
+ * known
+ **/
+gboolean
+nm_setting_ip_config_add_dns (NMSettingIPConfig *setting, const char *dns)
+{
+ NMSettingIPConfigPrivate *priv;
+ char *dns_canonical;
+ int i;
+
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE);
+ g_return_val_if_fail (dns != NULL, FALSE);
+ g_return_val_if_fail (nm_utils_ipaddr_valid (NM_SETTING_IP_CONFIG_GET_FAMILY (setting), dns), FALSE);
+
+ priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+
+ dns_canonical = canonicalize_ip (NM_SETTING_IP_CONFIG_GET_FAMILY (setting), dns, FALSE);
+ for (i = 0; i < priv->dns->len; i++) {
+ if (!strcmp (dns_canonical, priv->dns->pdata[i])) {
+ g_free (dns_canonical);
+ return FALSE;
+ }
+ }
+
+ g_ptr_array_add (priv->dns, dns_canonical);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS);
+ return TRUE;
+}
+
+/**
+ * nm_setting_ip_config_remove_dns:
+ * @setting: the #NMSettingIPConfig
+ * @i: index number of the DNS server to remove
+ *
+ * Removes the DNS server at index @i.
+ **/
+void
+nm_setting_ip_config_remove_dns (NMSettingIPConfig *setting, int i)
+{
+ NMSettingIPConfigPrivate *priv;
+
+ g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting));
+
+ priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+ g_return_if_fail (i < priv->dns->len);
+
+ g_ptr_array_remove_index (priv->dns, i);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS);
+}
+
+/**
+ * nm_setting_ip_config_remove_dns_by_value:
+ * @setting: the #NMSettingIPConfig
+ * @dns: the DNS server to remove
+ *
+ * Removes the DNS server @dns.
+ *
+ * Returns: %TRUE if the DNS server was found and removed; %FALSE if it was not.
+ **/
+gboolean
+nm_setting_ip_config_remove_dns_by_value (NMSettingIPConfig *setting, const char *dns)
+{
+ NMSettingIPConfigPrivate *priv;
+ char *dns_canonical;
+ int i;
+
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE);
+ g_return_val_if_fail (dns != NULL, FALSE);
+ g_return_val_if_fail (nm_utils_ipaddr_valid (NM_SETTING_IP_CONFIG_GET_FAMILY (setting), dns), FALSE);
+
+ priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+
+ dns_canonical = canonicalize_ip (NM_SETTING_IP_CONFIG_GET_FAMILY (setting), dns, FALSE);
+ for (i = 0; i < priv->dns->len; i++) {
+ if (!strcmp (dns_canonical, priv->dns->pdata[i])) {
+ g_ptr_array_remove_index (priv->dns, i);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS);
+ g_free (dns_canonical);
+ return TRUE;
+ }
+ }
+ g_free (dns_canonical);
+ return FALSE;
+}
+
+/**
+ * nm_setting_ip_config_clear_dns:
+ * @setting: the #NMSettingIPConfig
+ *
+ * Removes all configured DNS servers.
+ **/
+void
+nm_setting_ip_config_clear_dns (NMSettingIPConfig *setting)
+{
+ NMSettingIPConfigPrivate *priv;
+
+ 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);
+}
+
+/**
+ * nm_setting_ip_config_get_num_dns_searches:
+ * @setting: the #NMSettingIPConfig
+ *
+ * Returns: the number of configured DNS search domains
+ **/
+guint
+nm_setting_ip_config_get_num_dns_searches (NMSettingIPConfig *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), 0);
+
+ return NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->dns_search->len;
+}
+
+/**
+ * nm_setting_ip_config_get_dns_search:
+ * @setting: the #NMSettingIPConfig
+ * @i: index number of the DNS search domain to return
+ *
+ * Returns: the DNS search domain at index @i
+ **/
+const char *
+nm_setting_ip_config_get_dns_search (NMSettingIPConfig *setting, int i)
+{
+ NMSettingIPConfigPrivate *priv;
+
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), NULL);
+
+ priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+ g_return_val_if_fail (i < priv->dns_search->len, NULL);
+
+ return priv->dns_search->pdata[i];
+}
+
+/**
+ * nm_setting_ip_config_add_dns_search:
+ * @setting: the #NMSettingIPConfig
+ * @dns_search: the search domain to add
+ *
+ * Adds a new DNS search domain to the setting.
+ *
+ * Returns: %TRUE if the DNS search domain was added; %FALSE if the search
+ * domain was already known
+ **/
+gboolean
+nm_setting_ip_config_add_dns_search (NMSettingIPConfig *setting,
+ const char *dns_search)
+{
+ NMSettingIPConfigPrivate *priv;
+ int i;
+
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE);
+ g_return_val_if_fail (dns_search != NULL, FALSE);
+ g_return_val_if_fail (dns_search[0] != '\0', FALSE);
+
+ priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+ for (i = 0; i < priv->dns_search->len; i++) {
+ if (!strcmp (dns_search, priv->dns_search->pdata[i]))
+ return FALSE;
+ }
+
+ g_ptr_array_add (priv->dns_search, g_strdup (dns_search));
+ g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS_SEARCH);
+ return TRUE;
+}
+
+/**
+ * nm_setting_ip_config_remove_dns_search:
+ * @setting: the #NMSettingIPConfig
+ * @i: index number of the DNS search domain
+ *
+ * Removes the DNS search domain at index @i.
+ **/
+void
+nm_setting_ip_config_remove_dns_search (NMSettingIPConfig *setting, int i)
+{
+ NMSettingIPConfigPrivate *priv;
+
+ g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting));
+
+ priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+ g_return_if_fail (i < priv->dns_search->len);
+
+ g_ptr_array_remove_index (priv->dns_search, i);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS_SEARCH);
+}
+
+/**
+ * nm_setting_ip_config_remove_dns_search_by_value:
+ * @setting: the #NMSettingIPConfig
+ * @dns_search: the search domain to remove
+ *
+ * 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,
+ const char *dns_search)
+{
+ NMSettingIPConfigPrivate *priv;
+ int i;
+
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE);
+ g_return_val_if_fail (dns_search != NULL, FALSE);
+ g_return_val_if_fail (dns_search[0] != '\0', FALSE);
+
+ priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+ for (i = 0; i < priv->dns_search->len; i++) {
+ if (!strcmp (dns_search, priv->dns_search->pdata[i])) {
+ g_ptr_array_remove_index (priv->dns_search, i);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_DNS_SEARCH);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * nm_setting_ip_config_clear_dns_searches:
+ * @setting: the #NMSettingIPConfig
+ *
+ * Removes all configured DNS search domains.
+ **/
+void
+nm_setting_ip_config_clear_dns_searches (NMSettingIPConfig *setting)
+{
+ NMSettingIPConfigPrivate *priv;
+
+ 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);
+}
+
+/**
+ * nm_setting_ip_config_get_num_addresses:
+ * @setting: the #NMSettingIPConfig
+ *
+ * Returns: the number of configured addresses
+ **/
+guint
+nm_setting_ip_config_get_num_addresses (NMSettingIPConfig *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), 0);
+
+ return NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->addresses->len;
+}
+
+/**
+ * nm_setting_ip_config_get_address:
+ * @setting: the #NMSettingIPConfig
+ * @i: index number of the address to return
+ *
+ * Returns: the address at index @i
+ **/
+NMIPAddress *
+nm_setting_ip_config_get_address (NMSettingIPConfig *setting, int i)
+{
+ NMSettingIPConfigPrivate *priv;
+
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), NULL);
+
+ priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+ g_return_val_if_fail (i < priv->addresses->len, NULL);
+
+ return priv->addresses->pdata[i];
+}
+
+/**
+ * nm_setting_ip_config_add_address:
+ * @setting: the #NMSettingIPConfig
+ * @address: the new address to add
+ *
+ * Adds a new IP address and associated information to the setting. The
+ * given address is duplicated internally and is not changed by this function.
+ *
+ * Returns: %TRUE if the address was added; %FALSE if the address was already
+ * known.
+ **/
+gboolean
+nm_setting_ip_config_add_address (NMSettingIPConfig *setting,
+ NMIPAddress *address)
+{
+ NMSettingIPConfigPrivate *priv;
+ int i;
+
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE);
+ g_return_val_if_fail (address != NULL, FALSE);
+ g_return_val_if_fail (address->family == NM_SETTING_IP_CONFIG_GET_FAMILY (setting), FALSE);
+
+ priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+ for (i = 0; i < priv->addresses->len; i++) {
+ if (nm_ip_address_equal (priv->addresses->pdata[i], address))
+ return FALSE;
+ }
+
+ g_ptr_array_add (priv->addresses, nm_ip_address_dup (address));
+
+ g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_ADDRESSES);
+ return TRUE;
+}
+
+/**
+ * nm_setting_ip_config_remove_address:
+ * @setting: the #NMSettingIPConfig
+ * @i: index number of the address to remove
+ *
+ * Removes the address at index @i.
+ **/
+void
+nm_setting_ip_config_remove_address (NMSettingIPConfig *setting, int i)
+{
+ NMSettingIPConfigPrivate *priv;
+
+ g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting));
+
+ priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+ g_return_if_fail (i < priv->addresses->len);
+
+ g_ptr_array_remove_index (priv->addresses, i);
+
+ g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_ADDRESSES);
+}
+
+/**
+ * nm_setting_ip_config_remove_address_by_value:
+ * @setting: the #NMSettingIPConfig
+ * @address: the IP address to remove
+ *
+ * Removes the address @address.
+ *
+ * Returns: %TRUE if the address was found and removed; %FALSE if it was not.
+ **/
+gboolean
+nm_setting_ip_config_remove_address_by_value (NMSettingIPConfig *setting,
+ NMIPAddress *address)
+{
+ NMSettingIPConfigPrivate *priv;
+ int i;
+
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE);
+ g_return_val_if_fail (address != NULL, FALSE);
+
+ priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+ for (i = 0; i < priv->addresses->len; i++) {
+ if (nm_ip_address_equal (priv->addresses->pdata[i], address)) {
+ g_ptr_array_remove_index (priv->addresses, i);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_ADDRESSES);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * nm_setting_ip_config_clear_addresses:
+ * @setting: the #NMSettingIPConfig
+ *
+ * Removes all configured addresses.
+ **/
+void
+nm_setting_ip_config_clear_addresses (NMSettingIPConfig *setting)
+{
+ NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (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);
+}
+
+/**
+ * nm_setting_ip_config_get_gateway:
+ * @setting: the #NMSettingIPConfig
+ *
+ * Returns: the IP address of the gateway associated with this configuration, or
+ * %NULL.
+ **/
+const char *
+nm_setting_ip_config_get_gateway (NMSettingIPConfig *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), NULL);
+
+ return NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->gateway;
+}
+
+/**
+ * nm_setting_ip_config_get_num_routes:
+ * @setting: the #NMSettingIPConfig
+ *
+ * Returns: the number of configured routes
+ **/
+guint
+nm_setting_ip_config_get_num_routes (NMSettingIPConfig *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), 0);
+
+ return NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->routes->len;
+}
+
+/**
+ * nm_setting_ip_config_get_route:
+ * @setting: the #NMSettingIPConfig
+ * @i: index number of the route to return
+ *
+ * Returns: the route at index @i
+ **/
+NMIPRoute *
+nm_setting_ip_config_get_route (NMSettingIPConfig *setting, int i)
+{
+ NMSettingIPConfigPrivate *priv;
+
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), NULL);
+
+ priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+ g_return_val_if_fail (i < priv->routes->len, NULL);
+
+ return priv->routes->pdata[i];
+}
+
+/**
+ * nm_setting_ip_config_add_route:
+ * @setting: the #NMSettingIPConfig
+ * @route: the route to add
+ *
+ * Adds a new route and associated information to the setting. The
+ * given route is duplicated internally and is not changed by this function.
+ *
+ * Returns: %TRUE if the route was added; %FALSE if the route was already known.
+ **/
+gboolean
+nm_setting_ip_config_add_route (NMSettingIPConfig *setting,
+ NMIPRoute *route)
+{
+ NMSettingIPConfigPrivate *priv;
+ int i;
+
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE);
+ g_return_val_if_fail (route != NULL, FALSE);
+ g_return_val_if_fail (route->family == NM_SETTING_IP_CONFIG_GET_FAMILY (setting), FALSE);
+
+ priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+ for (i = 0; i < priv->routes->len; i++) {
+ if (nm_ip_route_equal (priv->routes->pdata[i], route))
+ return FALSE;
+ }
+
+ g_ptr_array_add (priv->routes, nm_ip_route_dup (route));
+ g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_ROUTES);
+ return TRUE;
+}
+
+/**
+ * nm_setting_ip_config_remove_route:
+ * @setting: the #NMSettingIPConfig
+ * @i: index number of the route
+ *
+ * Removes the route at index @i.
+ **/
+void
+nm_setting_ip_config_remove_route (NMSettingIPConfig *setting, int i)
+{
+ NMSettingIPConfigPrivate *priv;
+
+ g_return_if_fail (NM_IS_SETTING_IP_CONFIG (setting));
+
+ priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+ g_return_if_fail (i < priv->routes->len);
+
+ g_ptr_array_remove_index (priv->routes, i);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_ROUTES);
+}
+
+/**
+ * nm_setting_ip_config_remove_route_by_value:
+ * @setting: the #NMSettingIPConfig
+ * @route: the route to remove
+ *
+ * Removes the route @route.
+ *
+ * Returns: %TRUE if the route was found and removed; %FALSE if it was not.
+ **/
+gboolean
+nm_setting_ip_config_remove_route_by_value (NMSettingIPConfig *setting,
+ NMIPRoute *route)
+{
+ NMSettingIPConfigPrivate *priv;
+ int i;
+
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE);
+ g_return_val_if_fail (route != NULL, FALSE);
+
+ priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+ for (i = 0; i < priv->routes->len; i++) {
+ if (nm_ip_route_equal (priv->routes->pdata[i], route)) {
+ g_ptr_array_remove_index (priv->routes, i);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_IP_CONFIG_ROUTES);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * nm_setting_ip_config_clear_routes:
+ * @setting: the #NMSettingIPConfig
+ *
+ * Removes all configured routes.
+ **/
+void
+nm_setting_ip_config_clear_routes (NMSettingIPConfig *setting)
+{
+ NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (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);
+}
+
+/**
+ * nm_setting_ip_config_get_route_metric:
+ * @setting: the #NMSettingIPConfig
+ *
+ * Returns the value contained in the #NMSettingIPConfig:route-metric
+ * property.
+ *
+ * Returns: the route metric that is used for routes that don't explicitly
+ * specify a metric. See #NMSettingIPConfig:route-metric for more details.
+ **/
+gint64
+nm_setting_ip_config_get_route_metric (NMSettingIPConfig *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), -1);
+
+ return NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->route_metric;
+}
+
+
+/**
+ * nm_setting_ip_config_get_ignore_auto_routes:
+ * @setting: the #NMSettingIPConfig
+ *
+ * Returns the value contained in the #NMSettingIPConfig:ignore-auto-routes
+ * property.
+ *
+ * Returns: %TRUE if automatically configured (ie via DHCP) routes should be
+ * ignored.
+ **/
+gboolean
+nm_setting_ip_config_get_ignore_auto_routes (NMSettingIPConfig *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE);
+
+ return NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->ignore_auto_routes;
+}
+
+/**
+ * nm_setting_ip_config_get_ignore_auto_dns:
+ * @setting: the #NMSettingIPConfig
+ *
+ * Returns the value contained in the #NMSettingIPConfig:ignore-auto-dns
+ * property.
+ *
+ * Returns: %TRUE if automatically configured (ie via DHCP) DNS information
+ * should be ignored.
+ **/
+gboolean
+nm_setting_ip_config_get_ignore_auto_dns (NMSettingIPConfig *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE);
+
+ return NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->ignore_auto_dns;
+}
+
+/**
+ * nm_setting_ip_config_get_dhcp_hostname:
+ * @setting: the #NMSettingIPConfig
+ *
+ * Returns the value contained in the #NMSettingIPConfig:dhcp-hostname
+ * property.
+ *
+ * Returns: the configured hostname to send to the DHCP server
+ **/
+const char *
+nm_setting_ip_config_get_dhcp_hostname (NMSettingIPConfig *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), NULL);
+
+ return NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->dhcp_hostname;
+}
+
+/**
+ * nm_setting_ip_config_get_dhcp_send_hostname:
+ * @setting: the #NMSettingIPConfig
+ *
+ * Returns the value contained in the #NMSettingIPConfig:dhcp-send-hostname
+ * property.
+ *
+ * Returns: %TRUE if NetworkManager should send the machine hostname to the
+ * DHCP server when requesting addresses to allow the server to automatically
+ * update DNS information for this machine.
+ **/
+gboolean
+nm_setting_ip_config_get_dhcp_send_hostname (NMSettingIPConfig *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE);
+
+ return NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->dhcp_send_hostname;
+}
+
+/**
+ * nm_setting_ip_config_get_never_default:
+ * @setting: the #NMSettingIPConfig
+ *
+ * Returns the value contained in the #NMSettingIPConfig:never-default
+ * property.
+ *
+ * Returns: %TRUE if this connection should never be the default
+ * connection
+ **/
+gboolean
+nm_setting_ip_config_get_never_default (NMSettingIPConfig *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE);
+
+ return NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->never_default;
+}
+
+/**
+ * nm_setting_ip_config_get_may_fail:
+ * @setting: the #NMSettingIPConfig
+ *
+ * Returns the value contained in the #NMSettingIPConfig:may-fail
+ * property.
+ *
+ * Returns: %TRUE if this connection doesn't require this type of IP
+ * addressing to complete for the connection to succeed.
+ **/
+gboolean
+nm_setting_ip_config_get_may_fail (NMSettingIPConfig *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_IP_CONFIG (setting), FALSE);
+
+ return NM_SETTING_IP_CONFIG_GET_PRIVATE (setting)->may_fail;
+}
+
+static gboolean
+verify_label (const char *label)
+{
+ const char *p;
+ char *iface;
+
+ p = strchr (label, ':');
+ if (!p)
+ return FALSE;
+ iface = g_strndup (label, p - label);
+ if (!nm_utils_iface_valid_name (iface)) {
+ g_free (iface);
+ return FALSE;
+ }
+ g_free (iface);
+
+ for (p++; *p; p++) {
+ if (!g_ascii_isalnum (*p) && *p != '_')
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+ int i;
+
+ if (!priv->method) {
+ g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_METHOD);
+ return FALSE;
+ }
+
+ if (priv->dhcp_hostname && !*priv->dhcp_hostname) {
+ g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_DHCP_HOSTNAME);
+ return FALSE;
+ }
+
+ /* Validate DNS */
+ for (i = 0; i < priv->dns->len; i++) {
+ const char *dns = priv->dns->pdata[i];
+
+ if (!nm_utils_ipaddr_valid (NM_SETTING_IP_CONFIG_GET_FAMILY (setting), dns)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("%d. DNS server address is invalid"),
+ i+1);
+ g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_DNS);
+ return FALSE;
+ }
+ }
+
+ /* Validate addresses */
+ for (i = 0; i < priv->addresses->len; i++) {
+ NMIPAddress *addr = (NMIPAddress *) priv->addresses->pdata[i];
+ GVariant *label;
+
+ if (nm_ip_address_get_family (addr) != NM_SETTING_IP_CONFIG_GET_FAMILY (setting)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("%d. IP address is invalid"),
+ i+1);
+ g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_ADDRESSES);
+ return FALSE;
+ }
+
+ label = nm_ip_address_get_attribute (addr, "label");
+ if (label) {
+ if (!g_variant_is_of_type (label, G_VARIANT_TYPE_STRING)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("%d. IP address has 'label' property with invalid type"),
+ i+1);
+ g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_ADDRESSES);
+ return FALSE;
+ }
+ if (!verify_label (g_variant_get_string (label, NULL))) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("%d. IP address has invalid label '%s'"),
+ i+1, g_variant_get_string (label, NULL));
+ g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_ADDRESSES);
+ return FALSE;
+ }
+ }
+ }
+
+ /* Validate gateway */
+ if (priv->gateway) {
+ if (!priv->addresses->len) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("gateway cannot be set if there are no addresses configured"));
+ g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_GATEWAY);
+ return FALSE;
+ }
+
+ if (!nm_utils_ipaddr_valid (NM_SETTING_IP_CONFIG_GET_FAMILY (setting), priv->gateway)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("gateway is invalid"));
+ g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_GATEWAY);
+ return FALSE;
+ }
+ }
+
+ /* Validate routes */
+ for (i = 0; i < priv->routes->len; i++) {
+ NMIPRoute *route = (NMIPRoute *) priv->routes->pdata[i];
+
+ if (nm_ip_route_get_family (route) != NM_SETTING_IP_CONFIG_GET_FAMILY (setting)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("%d. route is invalid"),
+ i+1);
+ g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_ROUTES);
+ return FALSE;
+ }
+ if (nm_ip_route_get_prefix (route) == 0) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("%d. route cannot be a default route"),
+ i+1);
+ g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), NM_SETTING_IP_CONFIG_ROUTES);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+static void
+nm_setting_ip_config_init (NMSettingIPConfig *setting)
+{
+ NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+
+ priv->dns = g_ptr_array_new_with_free_func (g_free);
+ priv->dns_search = g_ptr_array_new_with_free_func (g_free);
+ priv->addresses = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_address_unref);
+ priv->routes = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_route_unref);
+}
+
+static void
+finalize (GObject *object)
+{
+ NMSettingIPConfig *self = NM_SETTING_IP_CONFIG (object);
+ NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (self);
+
+ g_free (priv->method);
+ g_free (priv->gateway);
+ g_free (priv->dhcp_hostname);
+
+ g_ptr_array_unref (priv->dns);
+ g_ptr_array_unref (priv->dns_search);
+ g_ptr_array_unref (priv->addresses);
+ g_ptr_array_unref (priv->routes);
+
+ G_OBJECT_CLASS (nm_setting_ip_config_parent_class)->finalize (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingIPConfig *setting = NM_SETTING_IP_CONFIG (object);
+ NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+ const char *gateway;
+
+ switch (prop_id) {
+ case PROP_METHOD:
+ g_free (priv->method);
+ priv->method = g_value_dup_string (value);
+ break;
+ case PROP_DNS:
+ g_ptr_array_unref (priv->dns);
+ priv->dns = _nm_utils_strv_to_ptrarray (g_value_get_boxed (value));
+ break;
+ case PROP_DNS_SEARCH:
+ g_ptr_array_unref (priv->dns_search);
+ priv->dns_search = _nm_utils_strv_to_ptrarray (g_value_get_boxed (value));
+ break;
+ case PROP_ADDRESSES:
+ g_ptr_array_unref (priv->addresses);
+ priv->addresses = _nm_utils_copy_array (g_value_get_boxed (value),
+ (NMUtilsCopyFunc) nm_ip_address_dup,
+ (GDestroyNotify) nm_ip_address_unref);
+ break;
+ case PROP_GATEWAY:
+ gateway = g_value_get_string (value);
+ g_return_if_fail (!gateway || nm_utils_ipaddr_valid (NM_SETTING_IP_CONFIG_GET_FAMILY (setting), gateway));
+ g_free (priv->gateway);
+ priv->gateway = canonicalize_ip (NM_SETTING_IP_CONFIG_GET_FAMILY (setting), gateway, TRUE);
+ break;
+ case PROP_ROUTES:
+ g_ptr_array_unref (priv->routes);
+ priv->routes = _nm_utils_copy_array (g_value_get_boxed (value),
+ (NMUtilsCopyFunc) nm_ip_route_dup,
+ (GDestroyNotify) nm_ip_route_unref);
+ break;
+ case PROP_ROUTE_METRIC:
+ priv->route_metric = g_value_get_int64 (value);
+ break;
+ case PROP_IGNORE_AUTO_ROUTES:
+ priv->ignore_auto_routes = g_value_get_boolean (value);
+ break;
+ case PROP_IGNORE_AUTO_DNS:
+ priv->ignore_auto_dns = g_value_get_boolean (value);
+ break;
+ case PROP_DHCP_HOSTNAME:
+ g_free (priv->dhcp_hostname);
+ priv->dhcp_hostname = g_value_dup_string (value);
+ break;
+ case PROP_DHCP_SEND_HOSTNAME:
+ priv->dhcp_send_hostname = g_value_get_boolean (value);
+ break;
+ case PROP_NEVER_DEFAULT:
+ priv->never_default = g_value_get_boolean (value);
+ break;
+ case PROP_MAY_FAIL:
+ priv->may_fail = g_value_get_boolean (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)
+{
+ NMSettingIPConfig *setting = NM_SETTING_IP_CONFIG (object);
+ NMSettingIPConfigPrivate *priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+
+ switch (prop_id) {
+ case PROP_METHOD:
+ g_value_set_string (value, nm_setting_ip_config_get_method (setting));
+ break;
+ case PROP_DNS:
+ g_value_take_boxed (value, _nm_utils_ptrarray_to_strv (priv->dns));
+ break;
+ case PROP_DNS_SEARCH:
+ g_value_take_boxed (value, _nm_utils_ptrarray_to_strv (priv->dns_search));
+ break;
+ case PROP_ADDRESSES:
+ g_value_take_boxed (value, _nm_utils_copy_array (priv->addresses,
+ (NMUtilsCopyFunc) nm_ip_address_dup,
+ (GDestroyNotify) nm_ip_address_unref));
+ break;
+ case PROP_GATEWAY:
+ g_value_set_string (value, nm_setting_ip_config_get_gateway (setting));
+ break;
+ case PROP_ROUTES:
+ g_value_take_boxed (value, _nm_utils_copy_array (priv->routes,
+ (NMUtilsCopyFunc) nm_ip_route_dup,
+ (GDestroyNotify) nm_ip_route_unref));
+ break;
+ case PROP_ROUTE_METRIC:
+ g_value_set_int64 (value, priv->route_metric);
+ break;
+ case PROP_IGNORE_AUTO_ROUTES:
+ g_value_set_boolean (value, nm_setting_ip_config_get_ignore_auto_routes (setting));
+ break;
+ case PROP_IGNORE_AUTO_DNS:
+ g_value_set_boolean (value, nm_setting_ip_config_get_ignore_auto_dns (setting));
+ break;
+ case PROP_DHCP_HOSTNAME:
+ g_value_set_string (value, nm_setting_ip_config_get_dhcp_hostname (setting));
+ break;
+ case PROP_DHCP_SEND_HOSTNAME:
+ g_value_set_boolean (value, nm_setting_ip_config_get_dhcp_send_hostname (setting));
+ break;
+ case PROP_NEVER_DEFAULT:
+ g_value_set_boolean (value, priv->never_default);
+ break;
+ case PROP_MAY_FAIL:
+ g_value_set_boolean (value, priv->may_fail);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+ip_gateway_set (NMSetting *setting,
+ GVariant *connection_dict,
+ const char *property,
+ GVariant *value)
+{
+ /* Don't set from 'gateway' if we're going to use the gateway in 'addresses' */
+ if (_nm_setting_use_legacy_property (setting, connection_dict, "addresses", "gateway"))
+ return;
+
+ g_object_set (setting, property, g_variant_get_string (value, NULL), NULL);
+}
+
+static void
+nm_setting_ip_config_class_init (NMSettingIPConfigClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+ NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+ g_type_class_add_private (setting_class, sizeof (NMSettingIPConfigPrivate));
+
+ /* virtual methods */
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+ object_class->finalize = finalize;
+ parent_class->verify = verify;
+
+ /* Properties */
+
+ /**
+ * NMSettingIPConfig:method:
+ *
+ * IP configuration method.
+ *
+ * #NMSettingIP4Config and #NMSettingIP6Config both support "auto",
+ * "manual", and "link-local". See the subclass-specific documentation for
+ * other values.
+ *
+ * In general, for the "auto" method, properties such as
+ * #NMSettingIPConfig:dns and #NMSettingIPConfig:routes specify information
+ * that is added on to the information returned from automatic
+ * configuration. The #NMSettingIPConfig:ignore-auto-routes and
+ * #NMSettingIPConfig:ignore-auto-dns properties modify this behavior.
+ *
+ * For methods that imply no upstream network, such as "shared" or
+ * "link-local", these properties must be empty.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_METHOD,
+ g_param_spec_string (NM_SETTING_IP_CONFIG_METHOD, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingIPConfig:dns:
+ *
+ * Array of IP addresses of DNS servers.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_DNS,
+ g_param_spec_boxed (NM_SETTING_IP_CONFIG_DNS, "", "",
+ G_TYPE_STRV,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingIPConfig:dns-search:
+ *
+ * Array of DNS search domains.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_DNS_SEARCH,
+ g_param_spec_boxed (NM_SETTING_IP_CONFIG_DNS_SEARCH, "", "",
+ G_TYPE_STRV,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingIPConfig:addresses:
+ *
+ * Array of IP addresses.
+ *
+ * Element-Type: NMIPAddress
+ **/
+ g_object_class_install_property
+ (object_class, PROP_ADDRESSES,
+ g_param_spec_boxed (NM_SETTING_IP_CONFIG_ADDRESSES, "", "",
+ G_TYPE_PTR_ARRAY,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_INFERRABLE |
+ /* "addresses" is a legacy D-Bus property, because the
+ * "addresses" GObject property normally gets set from
+ * the "address-data" D-Bus property...
+ */
+ NM_SETTING_PARAM_LEGACY |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingIPConfig:gateway:
+ *
+ * The gateway associated with this configuration. This is only meaningful
+ * if #NMSettingIPConfig:addresses is also set.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_GATEWAY,
+ g_param_spec_string (NM_SETTING_IP_CONFIG_GATEWAY, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ 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:
+ *
+ * Array of IP routes.
+ *
+ * Element-Type: NMIPRoute
+ **/
+ g_object_class_install_property
+ (object_class, PROP_ROUTES,
+ g_param_spec_boxed (NM_SETTING_IP_CONFIG_ROUTES, "", "",
+ G_TYPE_PTR_ARRAY,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_INFERRABLE |
+ /* See :addresses above Re: LEGACY */
+ NM_SETTING_PARAM_LEGACY |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingIPConfig:route-metric:
+ *
+ * The default metric for routes that don't explicitly specify a metric.
+ * The default value -1 means that the metric is choosen automatically
+ * based on the device type.
+ * The metric applies to dynamic routes, manual (static) routes that
+ * don't have an explicit metric setting, address prefix routes, and
+ * the default route.
+ * Note that for IPv6, the kernel accepts zero (0) but coerces it to
+ * 1024 (user default). Hence, setting this property to zero effectively
+ * mean setting it to 1024.
+ * For IPv4, zero is a regular value for the metric.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_ROUTE_METRIC,
+ g_param_spec_int64 (NM_SETTING_IP_CONFIG_ROUTE_METRIC, "", "",
+ -1, G_MAXUINT32, -1,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingIPConfig:ignore-auto-routes:
+ *
+ * When #NMSettingIPConfig:method is set to "auto" and this property to
+ * %TRUE, automatically configured routes are ignored and only routes
+ * specified in the #NMSettingIPConfig:routes property, if any, are used.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_IGNORE_AUTO_ROUTES,
+ g_param_spec_boolean (NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, "", "",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingIPConfig:ignore-auto-dns:
+ *
+ * When #NMSettingIPConfig:method is set to "auto" and this property to
+ * %TRUE, automatically configured nameservers and search domains are
+ * ignored and only nameservers and search domains specified in the
+ * #NMSettingIPConfig:dns and #NMSettingIPConfig:dns-search properties, if
+ * any, are used.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_IGNORE_AUTO_DNS,
+ g_param_spec_boolean (NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, "", "",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingIPConfig:dhcp-hostname:
+ *
+ * If the #NMSettingIPConfig:dhcp-send-hostname property is %TRUE, then the
+ * specified name will be sent to the DHCP server when acquiring a lease.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_DHCP_HOSTNAME,
+ g_param_spec_string (NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingIPConfig:dhcp-send-hostname:
+ *
+ * If %TRUE, a hostname is sent to the DHCP server when acquiring a lease.
+ * Some DHCP servers use this hostname to update DNS databases, essentially
+ * providing a static hostname for the computer. If the
+ * #NMSettingIPConfig:dhcp-hostname property is %NULL and this property is
+ * %TRUE, the current persistent hostname of the computer is sent.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_DHCP_SEND_HOSTNAME,
+ g_param_spec_boolean (NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, "", "",
+ TRUE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingIPConfig:never-default:
+ *
+ * If %TRUE, this connection will never be the default connection for this
+ * IP type, meaning it will never be assigned the default route by
+ * NetworkManager.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_NEVER_DEFAULT,
+ g_param_spec_boolean (NM_SETTING_IP_CONFIG_NEVER_DEFAULT, "", "",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingIPConfig:may-fail:
+ *
+ * If %TRUE, allow overall network configuration to proceed even if the
+ * configuration specified by this property times out. Note that at least
+ * one IP configuration must succeed or overall network configuration will
+ * still fail. For example, in IPv6-only networks, setting this property to
+ * %TRUE on the #NMSettingIP4Config allows the overall network configuration
+ * to succeed if IPv4 configuration fails but IPv6 configuration completes
+ * successfully.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_MAY_FAIL,
+ g_param_spec_boolean (NM_SETTING_IP_CONFIG_MAY_FAIL, "", "",
+ TRUE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+}
diff --git a/libnm-core/nm-setting-ip-config.h b/libnm-core/nm-setting-ip-config.h
new file mode 100644
index 000000000..12763fa85
--- /dev/null
+++ b/libnm-core/nm-setting-ip-config.h
@@ -0,0 +1,221 @@
+/* -*- 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 2007 - 2014 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#ifndef NM_SETTING_IP_CONFIG_H
+#define NM_SETTING_IP_CONFIG_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
+
+typedef struct NMIPAddress NMIPAddress;
+
+GType nm_ip_address_get_type (void);
+
+NMIPAddress *nm_ip_address_new (int family,
+ const char *addr,
+ guint prefix,
+ GError **error);
+NMIPAddress *nm_ip_address_new_binary (int family,
+ gconstpointer addr,
+ guint prefix,
+ GError **error);
+
+void nm_ip_address_ref (NMIPAddress *address);
+void nm_ip_address_unref (NMIPAddress *address);
+gboolean nm_ip_address_equal (NMIPAddress *address,
+ NMIPAddress *other);
+NMIPAddress *nm_ip_address_dup (NMIPAddress *address);
+
+int nm_ip_address_get_family (NMIPAddress *address);
+const char *nm_ip_address_get_address (NMIPAddress *address);
+void nm_ip_address_set_address (NMIPAddress *address,
+ const char *addr);
+void nm_ip_address_get_address_binary (NMIPAddress *address,
+ gpointer addr);
+void nm_ip_address_set_address_binary (NMIPAddress *address,
+ gconstpointer addr);
+guint nm_ip_address_get_prefix (NMIPAddress *address);
+void nm_ip_address_set_prefix (NMIPAddress *address,
+ guint prefix);
+
+char **nm_ip_address_get_attribute_names (NMIPAddress *address);
+GVariant *nm_ip_address_get_attribute (NMIPAddress *address,
+ const char *name);
+void nm_ip_address_set_attribute (NMIPAddress *address,
+ const char *name,
+ GVariant *value);
+
+
+typedef struct NMIPRoute NMIPRoute;
+
+GType nm_ip_route_get_type (void);
+
+NMIPRoute *nm_ip_route_new (int family,
+ const char *dest,
+ guint prefix,
+ const char *next_hop,
+ gint64 metric,
+ GError **error);
+NMIPRoute *nm_ip_route_new_binary (int family,
+ gconstpointer dest,
+ guint prefix,
+ gconstpointer next_hop,
+ gint64 metric,
+ GError **error);
+
+void nm_ip_route_ref (NMIPRoute *route);
+void nm_ip_route_unref (NMIPRoute *route);
+gboolean nm_ip_route_equal (NMIPRoute *route,
+ NMIPRoute *other);
+NMIPRoute *nm_ip_route_dup (NMIPRoute *route);
+
+int nm_ip_route_get_family (NMIPRoute *route);
+const char *nm_ip_route_get_dest (NMIPRoute *route);
+void nm_ip_route_set_dest (NMIPRoute *route,
+ const char *dest);
+void nm_ip_route_get_dest_binary (NMIPRoute *route,
+ gpointer dest);
+void nm_ip_route_set_dest_binary (NMIPRoute *route,
+ gconstpointer dest);
+guint nm_ip_route_get_prefix (NMIPRoute *route);
+void nm_ip_route_set_prefix (NMIPRoute *route,
+ guint prefix);
+const char *nm_ip_route_get_next_hop (NMIPRoute *route);
+void nm_ip_route_set_next_hop (NMIPRoute *route,
+ const char *next_hop);
+gboolean nm_ip_route_get_next_hop_binary (NMIPRoute *route,
+ gpointer next_hop);
+void nm_ip_route_set_next_hop_binary (NMIPRoute *route,
+ gconstpointer next_hop);
+gint64 nm_ip_route_get_metric (NMIPRoute *route);
+void nm_ip_route_set_metric (NMIPRoute *route,
+ gint64 metric);
+
+char **nm_ip_route_get_attribute_names (NMIPRoute *route);
+GVariant *nm_ip_route_get_attribute (NMIPRoute *route,
+ const char *name);
+void nm_ip_route_set_attribute (NMIPRoute *route,
+ const char *name,
+ GVariant *value);
+
+
+#define NM_TYPE_SETTING_IP_CONFIG (nm_setting_ip_config_get_type ())
+#define NM_SETTING_IP_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_IP_CONFIG, NMSettingIPConfig))
+#define NM_SETTING_IP_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_IPCONFIG, NMSettingIPConfigClass))
+#define NM_IS_SETTING_IP_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_IP_CONFIG))
+#define NM_IS_SETTING_IP_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_IP_CONFIG))
+#define NM_SETTING_IP_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_IP_CONFIG, NMSettingIPConfigClass))
+
+#define NM_SETTING_IP_CONFIG_METHOD "method"
+#define NM_SETTING_IP_CONFIG_DNS "dns"
+#define NM_SETTING_IP_CONFIG_DNS_SEARCH "dns-search"
+#define NM_SETTING_IP_CONFIG_ADDRESSES "addresses"
+#define NM_SETTING_IP_CONFIG_GATEWAY "gateway"
+#define NM_SETTING_IP_CONFIG_ROUTES "routes"
+#define NM_SETTING_IP_CONFIG_ROUTE_METRIC "route-metric"
+#define NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES "ignore-auto-routes"
+#define NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS "ignore-auto-dns"
+#define NM_SETTING_IP_CONFIG_DHCP_HOSTNAME "dhcp-hostname"
+#define NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME "dhcp-send-hostname"
+#define NM_SETTING_IP_CONFIG_NEVER_DEFAULT "never-default"
+#define NM_SETTING_IP_CONFIG_MAY_FAIL "may-fail"
+
+struct _NMSettingIPConfig {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /* Padding for future expansion */
+ gpointer padding[8];
+} NMSettingIPConfigClass;
+
+GType nm_setting_ip_config_get_type (void);
+
+const char *nm_setting_ip_config_get_method (NMSettingIPConfig *setting);
+
+guint nm_setting_ip_config_get_num_dns (NMSettingIPConfig *setting);
+const char *nm_setting_ip_config_get_dns (NMSettingIPConfig *setting,
+ int i);
+gboolean nm_setting_ip_config_add_dns (NMSettingIPConfig *setting,
+ const char *dns);
+void nm_setting_ip_config_remove_dns (NMSettingIPConfig *setting,
+ int i);
+gboolean nm_setting_ip_config_remove_dns_by_value (NMSettingIPConfig *setting,
+ const char *dns);
+void nm_setting_ip_config_clear_dns (NMSettingIPConfig *setting);
+
+guint nm_setting_ip_config_get_num_dns_searches (NMSettingIPConfig *setting);
+const char *nm_setting_ip_config_get_dns_search (NMSettingIPConfig *setting,
+ int i);
+gboolean nm_setting_ip_config_add_dns_search (NMSettingIPConfig *setting,
+ const char *dns_search);
+void nm_setting_ip_config_remove_dns_search (NMSettingIPConfig *setting,
+ int i);
+gboolean nm_setting_ip_config_remove_dns_search_by_value (NMSettingIPConfig *setting,
+ const char *dns_search);
+void nm_setting_ip_config_clear_dns_searches (NMSettingIPConfig *setting);
+
+guint nm_setting_ip_config_get_num_addresses (NMSettingIPConfig *setting);
+NMIPAddress *nm_setting_ip_config_get_address (NMSettingIPConfig *setting,
+ int i);
+gboolean nm_setting_ip_config_add_address (NMSettingIPConfig *setting,
+ NMIPAddress *address);
+void nm_setting_ip_config_remove_address (NMSettingIPConfig *setting,
+ int i);
+gboolean nm_setting_ip_config_remove_address_by_value (NMSettingIPConfig *setting,
+ NMIPAddress *address);
+void nm_setting_ip_config_clear_addresses (NMSettingIPConfig *setting);
+
+const char *nm_setting_ip_config_get_gateway (NMSettingIPConfig *setting);
+
+guint nm_setting_ip_config_get_num_routes (NMSettingIPConfig *setting);
+NMIPRoute *nm_setting_ip_config_get_route (NMSettingIPConfig *setting,
+ int i);
+gboolean nm_setting_ip_config_add_route (NMSettingIPConfig *setting,
+ NMIPRoute *route);
+void nm_setting_ip_config_remove_route (NMSettingIPConfig *setting,
+ int i);
+gboolean nm_setting_ip_config_remove_route_by_value (NMSettingIPConfig *setting,
+ NMIPRoute *route);
+void nm_setting_ip_config_clear_routes (NMSettingIPConfig *setting);
+
+gint64 nm_setting_ip_config_get_route_metric (NMSettingIPConfig *setting);
+
+gboolean nm_setting_ip_config_get_ignore_auto_routes (NMSettingIPConfig *setting);
+gboolean nm_setting_ip_config_get_ignore_auto_dns (NMSettingIPConfig *setting);
+
+const char *nm_setting_ip_config_get_dhcp_hostname (NMSettingIPConfig *setting);
+gboolean nm_setting_ip_config_get_dhcp_send_hostname (NMSettingIPConfig *setting);
+
+gboolean nm_setting_ip_config_get_never_default (NMSettingIPConfig *setting);
+gboolean nm_setting_ip_config_get_may_fail (NMSettingIPConfig *setting);
+
+G_END_DECLS
+
+#endif /* NM_SETTING_IP_CONFIG_H */
diff --git a/libnm-core/nm-setting-ip4-config.c b/libnm-core/nm-setting-ip4-config.c
new file mode 100644
index 000000000..686192678
--- /dev/null
+++ b/libnm-core/nm-setting-ip4-config.c
@@ -0,0 +1,695 @@
+/* -*- 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 2014 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-ip4-config.h"
+#include "nm-setting-private.h"
+
+/**
+ * SECTION:nm-setting-ip4-config
+ * @short_description: Describes IPv4 addressing, routing, and name service properties
+ *
+ * The #NMSettingIP4Config object is a #NMSetting subclass that describes
+ * properties related to IPv4 addressing, routing, and Domain Name Service.
+ *
+ * #NMSettingIP4Config has few properties or methods of its own; it inherits
+ * almost everything from #NMSettingIPConfig.
+ *
+ * NetworkManager supports 5 values for the #NMSettingIPConfig:method property
+ * for IPv4. If "auto" is specified then the appropriate automatic method
+ * (DHCP, PPP, etc) is used for the interface and most other properties can be
+ * left unset. If "link-local" is specified, then a link-local address in the
+ * 169.254/16 range will be assigned to the interface. If "manual" is
+ * specified, static IP addressing is used and at least one IP address must be
+ * given in the "addresses" property. If "shared" is specified (indicating that
+ * this connection will provide network access to other computers) then the
+ * interface is assigned an address in the 10.42.x.1/24 range and a DHCP and
+ * forwarding DNS server are started, and the interface is NAT-ed to the current
+ * default network connection. "disabled" means IPv4 will not be used on this
+ * connection.
+ **/
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingIP4Config, nm_setting_ip4_config, NM_TYPE_SETTING_IP_CONFIG,
+ _nm_register_setting (IP4_CONFIG, 4))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_IP4_CONFIG)
+
+#define NM_SETTING_IP4_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_IP4_CONFIG, NMSettingIP4ConfigPrivate))
+
+typedef struct {
+ char *dhcp_client_id;
+} NMSettingIP4ConfigPrivate;
+
+enum {
+ PROP_0,
+ PROP_DHCP_CLIENT_ID,
+
+ LAST_PROP
+};
+
+/**
+ * nm_setting_ip4_config_new:
+ *
+ * Creates a new #NMSettingIP4Config object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingIP4Config object
+ **/
+NMSetting *
+nm_setting_ip4_config_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_IP4_CONFIG, NULL);
+}
+
+/**
+ * nm_setting_ip4_config_get_dhcp_client_id:
+ * @setting: the #NMSettingIP4Config
+ *
+ * Returns the value contained in the #NMSettingIP4Config:dhcp-client-id
+ * property.
+ *
+ * Returns: the configured Client ID to send to the DHCP server when requesting
+ * addresses via DHCP.
+ **/
+const char *
+nm_setting_ip4_config_get_dhcp_client_id (NMSettingIP4Config *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_IP4_CONFIG (setting), NULL);
+
+ return NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting)->dhcp_client_id;
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (setting);
+ NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG (setting);
+ NMSettingVerifyResult ret;
+ const char *method;
+
+ ret = NM_SETTING_CLASS (nm_setting_ip4_config_parent_class)->verify (setting, connection, error);
+ if (ret != NM_SETTING_VERIFY_SUCCESS)
+ return ret;
+
+ method = nm_setting_ip_config_get_method (s_ip);
+ /* Base class already checked that it exists */
+ g_assert (method);
+
+ if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) {
+ if (nm_setting_ip_config_get_num_addresses (s_ip) == 0) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("this property cannot be empty for '%s=%s'"),
+ NM_SETTING_IP_CONFIG_METHOD, method);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_ADDRESSES);
+ return FALSE;
+ }
+ } else if ( !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL)
+ || !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)
+ || !strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_DISABLED)) {
+ if (nm_setting_ip_config_get_num_dns (s_ip) > 0) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("this property is not allowed for '%s=%s'"),
+ NM_SETTING_IP_CONFIG_METHOD, method);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_DNS);
+ return FALSE;
+ }
+
+ if (nm_setting_ip_config_get_num_dns_searches (s_ip) > 0) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("this property is not allowed for '%s=%s'"),
+ NM_SETTING_IP_CONFIG_METHOD, method);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_DNS_SEARCH);
+ return FALSE;
+ }
+
+ /* Shared allows IP addresses; link-local and disabled do not */
+ if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) != 0) {
+ if (nm_setting_ip_config_get_num_addresses (s_ip) > 0) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("this property is not allowed for '%s=%s'"),
+ NM_SETTING_IP_CONFIG_METHOD, method);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_ADDRESSES);
+ return FALSE;
+ }
+ }
+ } else if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
+ /* nothing to do */
+ } else {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_METHOD);
+ return FALSE;
+ }
+
+ if (priv->dhcp_client_id && !strlen (priv->dhcp_client_id)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+nm_setting_ip4_config_init (NMSettingIP4Config *setting)
+{
+}
+
+static void
+finalize (GObject *object)
+{
+ NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (object);
+
+ g_free (priv->dhcp_client_id);
+
+ G_OBJECT_CLASS (nm_setting_ip4_config_parent_class)->finalize (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingIP4ConfigPrivate *priv = NM_SETTING_IP4_CONFIG_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_DHCP_CLIENT_ID:
+ g_free (priv->dhcp_client_id);
+ priv->dhcp_client_id = 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)
+{
+ NMSettingIP4Config *s_ip4 = NM_SETTING_IP4_CONFIG (object);
+
+ switch (prop_id) {
+ case PROP_DHCP_CLIENT_ID:
+ g_value_set_string (value, nm_setting_ip4_config_get_dhcp_client_id (s_ip4));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GVariant *
+ip4_dns_to_dbus (const GValue *prop_value)
+{
+ return nm_utils_ip4_dns_to_variant (g_value_get_boxed (prop_value));
+}
+
+static void
+ip4_dns_from_dbus (GVariant *dbus_value,
+ GValue *prop_value)
+{
+ g_value_take_boxed (prop_value, nm_utils_ip4_dns_from_variant (dbus_value));
+}
+
+static GVariant *
+ip4_addresses_get (NMSetting *setting,
+ const char *property)
+{
+ GPtrArray *addrs;
+ const char *gateway;
+ GVariant *ret;
+
+ g_object_get (setting, property, &addrs, NULL);
+ gateway = nm_setting_ip_config_get_gateway (NM_SETTING_IP_CONFIG (setting));
+ ret = nm_utils_ip4_addresses_to_variant (addrs, gateway);
+ g_ptr_array_unref (addrs);
+
+ return ret;
+}
+
+static void
+ip4_addresses_set (NMSetting *setting,
+ GVariant *connection_dict,
+ const char *property,
+ GVariant *value)
+{
+ GPtrArray *addrs;
+ GVariant *s_ip4;
+ char **labels, *gateway = NULL;
+ int i;
+
+ if (!_nm_setting_use_legacy_property (setting, connection_dict, "addresses", "address-data"))
+ return;
+
+ addrs = nm_utils_ip4_addresses_from_variant (value, &gateway);
+
+ s_ip4 = g_variant_lookup_value (connection_dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
+ if (g_variant_lookup (s_ip4, "address-labels", "^as", &labels)) {
+ for (i = 0; i < addrs->len && labels[i]; i++)
+ if (*labels[i])
+ nm_ip_address_set_attribute (addrs->pdata[i], "label", g_variant_new_string (labels[i]));
+ g_strfreev (labels);
+ }
+ g_variant_unref (s_ip4);
+
+ g_object_set (setting,
+ NM_SETTING_IP_CONFIG_ADDRESSES, addrs,
+ NM_SETTING_IP_CONFIG_GATEWAY, gateway,
+ NULL);
+ g_ptr_array_unref (addrs);
+ g_free (gateway);
+}
+
+static GVariant *
+ip4_address_labels_get (NMSetting *setting,
+ NMConnection *connection,
+ const char *property)
+{
+ NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG (setting);
+ gboolean have_labels = FALSE;
+ GPtrArray *labels;
+ GVariant *ret;
+ int num_addrs, i;
+
+ num_addrs = nm_setting_ip_config_get_num_addresses (s_ip);
+ for (i = 0; i < num_addrs; i++) {
+ NMIPAddress *addr = nm_setting_ip_config_get_address (s_ip, i);
+ GVariant *label = nm_ip_address_get_attribute (addr, "label");
+
+ if (label) {
+ have_labels = TRUE;
+ break;
+ }
+ }
+ if (!have_labels)
+ return NULL;
+
+ labels = g_ptr_array_sized_new (num_addrs);
+ for (i = 0; i < num_addrs; i++) {
+ NMIPAddress *addr = nm_setting_ip_config_get_address (s_ip, i);
+ GVariant *label = nm_ip_address_get_attribute (addr, "label");
+
+ g_ptr_array_add (labels, (char *) (label ? g_variant_get_string (label, NULL) : ""));
+ }
+
+ ret = g_variant_new_strv ((const char * const *) labels->pdata, labels->len);
+ g_ptr_array_unref (labels);
+
+ return ret;
+}
+
+static GVariant *
+ip4_address_data_get (NMSetting *setting,
+ NMConnection *connection,
+ const char *property)
+{
+ GPtrArray *addrs;
+ GVariant *ret;
+
+ g_object_get (setting, NM_SETTING_IP_CONFIG_ADDRESSES, &addrs, NULL);
+ ret = nm_utils_ip_addresses_to_variant (addrs);
+ g_ptr_array_unref (addrs);
+
+ return ret;
+}
+
+static void
+ip4_address_data_set (NMSetting *setting,
+ GVariant *connection_dict,
+ const char *property,
+ GVariant *value)
+{
+ GPtrArray *addrs;
+
+ /* Ignore 'address-data' if we're going to process 'addresses' */
+ if (_nm_setting_use_legacy_property (setting, connection_dict, "addresses", "address-data"))
+ return;
+
+ addrs = nm_utils_ip_addresses_from_variant (value, AF_INET);
+ g_object_set (setting, NM_SETTING_IP_CONFIG_ADDRESSES, addrs, NULL);
+ g_ptr_array_unref (addrs);
+}
+
+static GVariant *
+ip4_routes_get (NMSetting *setting,
+ const char *property)
+{
+ GPtrArray *routes;
+ GVariant *ret;
+
+ g_object_get (setting, property, &routes, NULL);
+ ret = nm_utils_ip4_routes_to_variant (routes);
+ g_ptr_array_unref (routes);
+
+ return ret;
+}
+
+static void
+ip4_routes_set (NMSetting *setting,
+ GVariant *connection_dict,
+ const char *property,
+ GVariant *value)
+{
+ GPtrArray *routes;
+
+ if (!_nm_setting_use_legacy_property (setting, connection_dict, "routes", "route-data"))
+ return;
+
+ routes = nm_utils_ip4_routes_from_variant (value);
+ g_object_set (setting, property, routes, NULL);
+ g_ptr_array_unref (routes);
+}
+
+static GVariant *
+ip4_route_data_get (NMSetting *setting,
+ NMConnection *connection,
+ const char *property)
+{
+ GPtrArray *routes;
+ GVariant *ret;
+
+ g_object_get (setting, NM_SETTING_IP_CONFIG_ROUTES, &routes, NULL);
+ ret = nm_utils_ip_routes_to_variant (routes);
+ g_ptr_array_unref (routes);
+
+ return ret;
+}
+
+static void
+ip4_route_data_set (NMSetting *setting,
+ GVariant *connection_dict,
+ const char *property,
+ GVariant *value)
+{
+ GPtrArray *routes;
+
+ /* Ignore 'route-data' if we're going to process 'routes' */
+ if (_nm_setting_use_legacy_property (setting, connection_dict, "routes", "route-data"))
+ return;
+
+ routes = nm_utils_ip_routes_from_variant (value, AF_INET);
+ g_object_set (setting, NM_SETTING_IP_CONFIG_ROUTES, routes, NULL);
+ g_ptr_array_unref (routes);
+}
+
+
+static void
+nm_setting_ip4_config_class_init (NMSettingIP4ConfigClass *ip4_class)
+{
+ NMSettingClass *setting_class = NM_SETTING_CLASS (ip4_class);
+ GObjectClass *object_class = G_OBJECT_CLASS (ip4_class);
+
+ 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 */
+
+ /* ---ifcfg-rh---
+ * property: method
+ * variable: BOOTPROTO
+ * format: string
+ * values: none, dhcp (bootp), static, ibft, autoip, shared
+ * default: none
+ * description: Method used for IPv4 protocol configuration.
+ * ---end---
+ */
+
+ /* ---keyfile---
+ * property: dns
+ * format: list of DNS IP addresses
+ * description: List of DNS servers.
+ * example: dns=1.2.3.4;8.8.8.8;8.8.4.4;
+ * ---end---
+ * ---ifcfg-rh---
+ * property: dns
+ * variable: DNS1, DNS2, ...
+ * format: string
+ * description: List of DNS servers. Even if NetworkManager supports many DNS
+ * servers, initscripts and resolver only care about the first three, usually.
+ * example: DNS1=1.2.3.4 DNS2=10.0.0.254 DNS3=8.8.8.8
+ * ---end---
+ */
+
+ /* ---ifcfg-rh---
+ * property: dns-search
+ * variable: DOMAIN
+ * format: string (space-separated domains)
+ * description: List of DNS search domains.
+ * ---end---
+ */
+
+ /* ---keyfile---
+ * property: addresses
+ * variable: address1, address2, ...
+ * format: address/plen
+ * description: List of static IP addresses.
+ * example: address1=192.168.100.100/24 address2=10.1.1.5/24
+ * ---end---
+ * ---ifcfg-rh---
+ * property: addresses
+ * variable: IPADDR, PREFIX, IPADDR1, PREFIX1, ...
+ * description: List of static IP addresses.
+ * example: IPADDR=10.5.5.23 PREFIX=24 IPADDR1=1.1.1.2 PREFIX1=16
+ * ---end---
+ */
+
+ /* ---keyfile---
+ * property: gateway
+ * variable: gateway
+ * format: string
+ * description: Gateway IP addresses as a string.
+ * example: gateway=192.168.100.1
+ * ---end---
+ * ---ifcfg-rh---
+ * property: gateway
+ * variable: GATEWAY
+ * description: Gateway IP address.
+ * example: GATEWAY=10.5.5.1
+ * ---end---
+ */
+
+ /* ---keyfile---
+ * property: routes
+ * variable: route1, route2, ...
+ * format: route/plen[,gateway,metric]
+ * description: List of IP routes.
+ * example: route1=8.8.8.0/24,10.1.1.1,77
+ * route2=7.7.0.0/16
+ * ---end---
+ * ---ifcfg-rh---
+ * property: routes
+ * variable: ADDRESS1, NETMASK1, GATEWAY1, METRIC1, ...
+ * description: List of static routes. They are not stored in ifcfg-* file,
+ * but in route-* file instead.
+ * ---end---
+ */
+
+ /* ---ifcfg-rh---
+ * property: ignore-auto-routes
+ * variable: PEERROUTES(+)
+ * default: yes
+ * description: PEERROUTES has the opposite meaning as 'ignore-auto-routes' property.
+ * ---end---
+ */
+
+ /* ---ifcfg-rh---
+ * property: ignore-auto-dns
+ * variable: PEERDNS
+ * default: yes
+ * description: PEERDNS has the opposite meaning as 'ignore-auto-dns' property.
+ * ---end---
+ */
+
+ /* ---ifcfg-rh---
+ * property: dhcp-send-hostname
+ * variable: DHCP_SEND_HOSTNAME(+)
+ * default: yes
+ * description: Whether DHCP_HOSTNAME should be sent to the DHCP server.
+ * ---end---
+ */
+
+ /* ---ifcfg-rh---
+ * property: dhcp-hostname
+ * variable: DHCP_HOSTNAME
+ * description: Hostname to send to the DHCP server.
+ * ---end---
+ */
+
+ /* ---ifcfg-rh---
+ * property: never-default
+ * variable: DEFROUTE (GATEWAYDEV in /etc/sysconfig/network)
+ * default: yes
+ * description: DEFROUTE=no tells NetworkManager that this connection
+ * should not be assigned the default route. DEFROUTE has the opposite
+ * meaning as 'never-default' property.
+ * ---end---
+ */
+
+ /* ---ifcfg-rh---
+ * property: may-fail
+ * variable: IPV4_FAILURE_FATAL(+)
+ * default: no
+ * description: IPV4_FAILURE_FATAL has the opposite meaning as 'may-fail' property.
+ * ---end---
+ */
+
+ /**
+ * NMSettingIP4Config:dhcp-client-id:
+ *
+ * A string sent to the DHCP server to identify the local machine which the
+ * DHCP server may use to customize the DHCP lease and options.
+ **/
+ /* ---ifcfg-rh---
+ * property: dhcp-client-id
+ * variable: DHCP_CLIENT_ID(+)
+ * description: A string sent to the DHCP server to identify the local machine.
+ * example: DHCP_CLIENT_ID=ax-srv-1
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_DHCP_CLIENT_ID,
+ g_param_spec_string (NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /* IP4-specific property overrides */
+
+ /* ---dbus---
+ * property: dns
+ * format: array of uint32
+ * description: Array of IP addresses of DNS servers (as network-byte-order
+ * 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);
+
+ /* ---dbus---
+ * property: addresses
+ * format: array of array of uint32
+ * description: Deprecated in favor of the 'address-data' and 'gateway'
+ * properties, but this can be used for backward-compatibility with older
+ * daemons. Note that if you send this property the daemon will ignore
+ * 'address-data' and 'gateway'.
+ *
+ * Array of IPv4 address structures. Each IPv4 address structure is
+ * composed of 3 32-bit values; the first being the IPv4 address (network
+ * byte order), the second the prefix (1 - 32), and last the IPv4 gateway
+ * (network byte order). The gateway may be left as 0 if no gateway exists
+ * 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);
+
+ /* ---dbus---
+ * property: address-data
+ * format: array of vardict
+ * description: Array of IPv4 addresses. Each address dictionary contains at
+ * least 'address' and 'prefix' entries, containing the IP address as a
+ * string, and the prefix length as a uint32. Additional attributes may
+ * 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);
+
+ /* ---dbus---
+ * property: routes
+ * format: array of array of uint32
+ * description: Deprecated in favor of the 'route-data' property, but this
+ * can be used for backward-compatibility with older daemons. Note that if
+ * you send this property the daemon will ignore 'route-data'.
+ *
+ * Array of IPv4 route structures. Each IPv4 route structure is composed
+ * of 4 32-bit values; the first being the destination IPv4 network or
+ * address (network byte order), the second the destination network or
+ * address prefix (1 - 32), the third being the next-hop (network byte
+ * order) if any, and the fourth being the route metric. If the metric is
+ * 0, NM will choose an appropriate default metric for the device. (There
+ * is no way to explicitly specify an actual metric of 0 with this
+ * 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);
+
+ /* ---dbus---
+ * property: route-data
+ * format: array of vardict
+ * description: Array of IPv4 routes. Each route dictionary contains at
+ * least 'dest' and 'prefix' entries, containing the destination IP
+ * address as a string, and the prefix length as a uint32. Most routes
+ * will also have a 'gateway' entry, containing the gateway IP address as
+ * a string. If the route has a 'metric' entry (containing a uint32), that
+ * will be used as the metric for the route (otherwise NM will pick a
+ * default value appropriate to the device). Additional attributes may
+ * 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);
+
+}
diff --git a/libnm-core/nm-setting-ip4-config.h b/libnm-core/nm-setting-ip4-config.h
new file mode 100644
index 000000000..e944dfe39
--- /dev/null
+++ b/libnm-core/nm-setting-ip4-config.h
@@ -0,0 +1,108 @@
+/* -*- 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 2007 - 2014 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#ifndef __NM_SETTING_IP4_CONFIG_H__
+#define __NM_SETTING_IP4_CONFIG_H__
+
+#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
+#error "Only <NetworkManager.h> can be included directly."
+#endif
+
+#include "nm-setting-ip-config.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_SETTING_IP4_CONFIG (nm_setting_ip4_config_get_type ())
+#define NM_SETTING_IP4_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_IP4_CONFIG, NMSettingIP4Config))
+#define NM_SETTING_IP4_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_IP4CONFIG, NMSettingIP4ConfigClass))
+#define NM_IS_SETTING_IP4_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_IP4_CONFIG))
+#define NM_IS_SETTING_IP4_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_IP4_CONFIG))
+#define NM_SETTING_IP4_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_IP4_CONFIG, NMSettingIP4ConfigClass))
+
+#define NM_SETTING_IP4_CONFIG_SETTING_NAME "ipv4"
+
+#define NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID "dhcp-client-id"
+
+/**
+ * NM_SETTING_IP4_CONFIG_METHOD_AUTO:
+ *
+ * IPv4 configuration should be automatically determined via a method appropriate
+ * for the hardware interface, ie DHCP or PPP or some other device-specific
+ * manner.
+ */
+#define NM_SETTING_IP4_CONFIG_METHOD_AUTO "auto"
+
+/**
+ * NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL:
+ *
+ * IPv4 configuration should be automatically configured for link-local-only
+ * operation.
+ */
+#define NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL "link-local"
+
+/**
+ * NM_SETTING_IP4_CONFIG_METHOD_MANUAL:
+ *
+ * All necessary IPv4 configuration (addresses, prefix, DNS, etc) is specified
+ * in the setting's properties.
+ */
+#define NM_SETTING_IP4_CONFIG_METHOD_MANUAL "manual"
+
+/**
+ * NM_SETTING_IP4_CONFIG_METHOD_SHARED:
+ *
+ * This connection specifies configuration that allows other computers to
+ * connect through it to the default network (usually the Internet). The
+ * connection's interface will be assigned a private address, and a DHCP server,
+ * caching DNS server, and Network Address Translation (NAT) functionality will
+ * be started on this connection's interface to allow other devices to connect
+ * through that interface to the default network.
+ */
+#define NM_SETTING_IP4_CONFIG_METHOD_SHARED "shared"
+
+/**
+ * NM_SETTING_IP4_CONFIG_METHOD_DISABLED:
+ *
+ * This connection does not use or require IPv4 address and it should be disabled.
+ */
+#define NM_SETTING_IP4_CONFIG_METHOD_DISABLED "disabled"
+
+struct _NMSettingIP4Config {
+ NMSettingIPConfig parent;
+};
+
+typedef struct {
+ NMSettingIPConfigClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingIP4ConfigClass;
+
+GType nm_setting_ip4_config_get_type (void);
+
+NMSetting *nm_setting_ip4_config_new (void);
+
+const char *nm_setting_ip4_config_get_dhcp_client_id (NMSettingIP4Config *setting);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_IP4_CONFIG_H__ */
diff --git a/libnm-core/nm-setting-ip6-config.c b/libnm-core/nm-setting-ip6-config.c
new file mode 100644
index 000000000..f5d903340
--- /dev/null
+++ b/libnm-core/nm-setting-ip6-config.c
@@ -0,0 +1,610 @@
+/* -*- 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 2007 - 2014 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-ip6-config.h"
+#include "nm-setting-private.h"
+#include "nm-core-enum-types.h"
+
+/**
+ * SECTION:nm-setting-ip6-config
+ * @short_description: Describes IPv6 addressing, routing, and name service properties
+ *
+ * The #NMSettingIP6Config object is a #NMSetting subclass that describes
+ * properties related to IPv6 addressing, routing, and Domain Name Service
+ *
+ * #NMSettingIP6Config has few properties or methods of its own; it inherits
+ * almost everything from #NMSettingIPConfig.
+ *
+ * NetworkManager supports 6 values for the #NMSettingIPConfig:method property
+ * for IPv6. If "auto" is specified then the appropriate automatic method (PPP,
+ * router advertisement, etc) is used for the device and most other properties
+ * can be left unset. To force the use of DHCP only, specify "dhcp"; this
+ * method is only valid for Ethernet- based hardware. If "link-local" is
+ * specified, then an IPv6 link-local address will be assigned to the interface.
+ * If "manual" is specified, static IP addressing is used and at least one IP
+ * address must be given in the "addresses" property. If "ignore" is specified,
+ * IPv6 configuration is not done. Note: the "shared" method is not yet
+ * supported.
+ **/
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingIP6Config, nm_setting_ip6_config, NM_TYPE_SETTING_IP_CONFIG,
+ _nm_register_setting (IP6_CONFIG, 4))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_IP6_CONFIG)
+
+#define NM_SETTING_IP6_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_IP6_CONFIG, NMSettingIP6ConfigPrivate))
+
+typedef struct {
+ NMSettingIP6ConfigPrivacy ip6_privacy;
+} NMSettingIP6ConfigPrivate;
+
+
+enum {
+ PROP_0,
+ PROP_IP6_PRIVACY,
+
+ LAST_PROP
+};
+
+/**
+ * nm_setting_ip6_config_new:
+ *
+ * Creates a new #NMSettingIP6Config object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingIP6Config object
+ **/
+NMSetting *
+nm_setting_ip6_config_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_IP6_CONFIG, NULL);
+}
+
+/**
+ * nm_setting_ip6_config_get_ip6_privacy:
+ * @setting: the #NMSettingIP6Config
+ *
+ * Returns the value contained in the #NMSettingIP6Config:ip6-privacy
+ * property.
+ *
+ * Returns: IPv6 Privacy Extensions configuration value (#NMSettingIP6ConfigPrivacy).
+ **/
+NMSettingIP6ConfigPrivacy
+nm_setting_ip6_config_get_ip6_privacy (NMSettingIP6Config *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN);
+
+ return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->ip6_privacy;
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG (setting);
+ NMSettingVerifyResult ret;
+ const char *method;
+
+ ret = NM_SETTING_CLASS (nm_setting_ip6_config_parent_class)->verify (setting, connection, error);
+ if (ret != NM_SETTING_VERIFY_SUCCESS)
+ return ret;
+
+ method = nm_setting_ip_config_get_method (s_ip);
+ /* Base class already checked that it exists */
+ g_assert (method);
+
+ if (!strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
+ if (nm_setting_ip_config_get_num_addresses (s_ip) == 0) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("this property cannot be empty for '%s=%s'"),
+ NM_SETTING_IP_CONFIG_METHOD, method);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_ADDRESSES);
+ return FALSE;
+ }
+ } else if ( !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)
+ || !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)
+ || !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_SHARED)) {
+ if (nm_setting_ip_config_get_num_dns (s_ip) > 0) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' not allowed for %s=%s"),
+ _("this property is not allowed for '%s=%s'"),
+ NM_SETTING_IP_CONFIG_METHOD, method);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_DNS);
+ return FALSE;
+ }
+
+ if (nm_setting_ip_config_get_num_dns_searches (s_ip) > 0) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("this property is not allowed for '%s=%s'"),
+ NM_SETTING_IP_CONFIG_METHOD, method);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_DNS_SEARCH);
+ return FALSE;
+ }
+
+ if (nm_setting_ip_config_get_num_addresses (s_ip) > 0) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("this property is not allowed for '%s=%s'"),
+ NM_SETTING_IP_CONFIG_METHOD, method);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_ADDRESSES);
+ return FALSE;
+ }
+ } else if ( !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)
+ || !strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_DHCP)) {
+ /* nothing to do */
+ } else {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP_CONFIG_METHOD);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+static void
+nm_setting_ip6_config_init (NMSettingIP6Config *setting)
+{
+}
+
+static GVariant *
+ip6_dns_to_dbus (const GValue *prop_value)
+{
+ return nm_utils_ip6_dns_to_variant (g_value_get_boxed (prop_value));
+}
+
+static void
+ip6_dns_from_dbus (GVariant *dbus_value,
+ GValue *prop_value)
+{
+ g_value_take_boxed (prop_value, nm_utils_ip6_dns_from_variant (dbus_value));
+}
+
+static GVariant *
+ip6_addresses_get (NMSetting *setting,
+ const char *property)
+{
+ GPtrArray *addrs;
+ const char *gateway;
+ GVariant *ret;
+
+ g_object_get (setting, property, &addrs, NULL);
+ gateway = nm_setting_ip_config_get_gateway (NM_SETTING_IP_CONFIG (setting));
+ ret = nm_utils_ip6_addresses_to_variant (addrs, gateway);
+ g_ptr_array_unref (addrs);
+
+ return ret;
+}
+
+static void
+ip6_addresses_set (NMSetting *setting,
+ GVariant *connection_dict,
+ const char *property,
+ GVariant *value)
+{
+ GPtrArray *addrs;
+ char *gateway = NULL;
+
+ if (!_nm_setting_use_legacy_property (setting, connection_dict, "addresses", "address-data"))
+ return;
+
+ addrs = nm_utils_ip6_addresses_from_variant (value, &gateway);
+
+ g_object_set (setting,
+ NM_SETTING_IP_CONFIG_ADDRESSES, addrs,
+ NM_SETTING_IP_CONFIG_GATEWAY, gateway,
+ NULL);
+ g_ptr_array_unref (addrs);
+ g_free (gateway);
+}
+
+static GVariant *
+ip6_address_data_get (NMSetting *setting,
+ NMConnection *connection,
+ const char *property)
+{
+ GPtrArray *addrs;
+ GVariant *ret;
+
+ g_object_get (setting, NM_SETTING_IP_CONFIG_ADDRESSES, &addrs, NULL);
+ ret = nm_utils_ip_addresses_to_variant (addrs);
+ g_ptr_array_unref (addrs);
+
+ return ret;
+}
+
+static void
+ip6_address_data_set (NMSetting *setting,
+ GVariant *connection_dict,
+ const char *property,
+ GVariant *value)
+{
+ GPtrArray *addrs;
+
+ /* Ignore 'address-data' if we're going to process 'addresses' */
+ if (_nm_setting_use_legacy_property (setting, connection_dict, "addresses", "address-data"))
+ return;
+
+ addrs = nm_utils_ip_addresses_from_variant (value, AF_INET6);
+ g_object_set (setting, NM_SETTING_IP_CONFIG_ADDRESSES, addrs, NULL);
+ g_ptr_array_unref (addrs);
+}
+
+static GVariant *
+ip6_routes_get (NMSetting *setting,
+ const char *property)
+{
+ GPtrArray *routes;
+ GVariant *ret;
+
+ g_object_get (setting, property, &routes, NULL);
+ ret = nm_utils_ip6_routes_to_variant (routes);
+ g_ptr_array_unref (routes);
+
+ return ret;
+}
+
+static void
+ip6_routes_set (NMSetting *setting,
+ GVariant *connection_dict,
+ const char *property,
+ GVariant *value)
+{
+ GPtrArray *routes;
+
+ if (!_nm_setting_use_legacy_property (setting, connection_dict, "routes", "route-data"))
+ return;
+
+ routes = nm_utils_ip6_routes_from_variant (value);
+ g_object_set (setting, property, routes, NULL);
+ g_ptr_array_unref (routes);
+}
+
+static GVariant *
+ip6_route_data_get (NMSetting *setting,
+ NMConnection *connection,
+ const char *property)
+{
+ GPtrArray *routes;
+ GVariant *ret;
+
+ g_object_get (setting, NM_SETTING_IP_CONFIG_ROUTES, &routes, NULL);
+ ret = nm_utils_ip_routes_to_variant (routes);
+ g_ptr_array_unref (routes);
+
+ return ret;
+}
+
+static void
+ip6_route_data_set (NMSetting *setting,
+ GVariant *connection_dict,
+ const char *property,
+ GVariant *value)
+{
+ GPtrArray *routes;
+
+ /* Ignore 'route-data' if we're going to process 'routes' */
+ if (_nm_setting_use_legacy_property (setting, connection_dict, "routes", "route-data"))
+ return;
+
+ routes = nm_utils_ip_routes_from_variant (value, AF_INET6);
+ g_object_set (setting, NM_SETTING_IP_CONFIG_ROUTES, routes, NULL);
+ g_ptr_array_unref (routes);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_IP6_PRIVACY:
+ priv->ip6_privacy = 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)
+{
+ NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_IP6_PRIVACY:
+ g_value_set_enum (value, priv->ip6_privacy);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (ip6_class);
+ NMSettingClass *setting_class = NM_SETTING_CLASS (ip6_class);
+
+ g_type_class_add_private (ip6_class, sizeof (NMSettingIP6ConfigPrivate));
+
+ /* virtual methods */
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+ setting_class->verify = verify;
+
+ /* Properties */
+
+ /* ---ifcfg-rh---
+ * property: method
+ * variable: IPV6INIT, IPV6FORWARDING, IPV6_AUTOCONF, DHCPV6C
+ * default: IPV6INIT=yes; IPV6FORWARDING=no; IPV6_AUTOCONF=!IPV6FORWARDING, DHCPV6=no
+ * description: Method used for IPv6 protocol configuration.
+ * ignore ~ IPV6INIT=no; auto ~ IPV6_AUTOCONF=yes; dhcp ~ IPV6_AUTOCONF=no and DHCPV6C=yes
+ * ---end---
+ */
+
+ /* ---keyfile---
+ * property: dns
+ * format: list of DNS IP addresses
+ * description: List of DNS servers.
+ * example: dns=2001:4860:4860::8888;2001:4860:4860::8844;
+ * ---end---
+ * ---ifcfg-rh---
+ * property: dns
+ * variable: DNS1, DNS2, ...
+ * format: string
+ * description: List of DNS servers. NetworkManager uses the variables both
+ * for IPv4 and IPv6.
+ * ---end---
+ */
+
+ /* ---ifcfg-rh---
+ * property: dns-search
+ * variable: DOMAIN
+ * format: string (space-separated domains)
+ * description: List of DNS search domains.
+ * ---end---
+ */
+
+ /* ---keyfile---
+ * property: addresses
+ * variable: address1, address2, ...
+ * format: address/plen
+ * description: List of static IP addresses.
+ * example: address1=abbe::cafe/96 address2=2001::1234
+ * ---end---
+ * ---ifcfg-rh---
+ * property: addresses
+ * variable: IPV6ADDR, IPV6ADDR_SECONDARIES
+ * description: List of static IP addresses.
+ * example: IPV6ADDR=ab12:9876::1
+ * IPV6ADDR_SECONDARIES="ab12:9876::2 ab12:9876::3"
+ * ---end---
+ */
+
+ /* ---keyfile---
+ * property: gateway
+ * variable: gateway
+ * format: string
+ * description: Gateway IP addresses as a string.
+ * example: gateway=abbe::1
+ * ---end---
+ * ---ifcfg-rh---
+ * property: gateway
+ * variable: IPV6_DEFAULTGW
+ * description: Gateway IP address.
+ * example: IPV6_DEFAULTGW=abbe::1
+ * ---end---
+ */
+
+ /* ---keyfile---
+ * property: routes
+ * variable: route1, route2, ...
+ * format: route/plen[,gateway,metric]
+ * description: List of IP routes.
+ * example: route1=2001:4860:4860::/64,2620:52:0:2219:222:68ff:fe11:5403
+ * ---end---
+ * ---ifcfg-rh---
+ * property: routes
+ * variable: (none)
+ * description: List of static routes. They are not stored in ifcfg-* file,
+ * but in route6-* file instead in the form of command line for 'ip route add'.
+ * ---end---
+ */
+
+ /* ---ifcfg-rh---
+ * property: ignore-auto-routes
+ * variable: IPV6_PEERROUTES(+)
+ * default: yes
+ * description: IPV6_PEERROUTES has the opposite meaning as 'ignore-auto-routes' property.
+ * ---end---
+ */
+
+ /* ---ifcfg-rh---
+ * property: ignore-auto-dns
+ * variable: IPV6_PEERDNS(+)
+ * default: yes
+ * description: IPV6_PEERDNS has the opposite meaning as 'ignore-auto-dns' property.
+ * ---end---
+ */
+
+ /* ---ifcfg-rh---
+ * property: dhcp-hostname
+ * variable: DHCP_HOSTNAME
+ * description: Hostname to send the DHCP server.
+ * ---end---
+ */
+
+ /* ---ifcfg-rh---
+ * property: never-default
+ * variable: IPV6_DEFROUTE(+), (and IPV6_DEFAULTGW, IPV6_DEFAULTDEV in /etc/sysconfig/network)
+ * default: IPV6_DEFROUTE=yes (when no variable specified)
+ * description: IPV6_DEFROUTE=no tells NetworkManager that this connection
+ * should not be assigned the default IPv6 route. IPV6_DEFROUTE has the opposite
+ * meaning as 'never-default' property.
+ * ---end---
+ */
+
+ /* ---ifcfg-rh---
+ * property: may-fail
+ * variable: IPV6_FAILURE_FATAL(+)
+ * default: no
+ * description: IPV6_FAILURE_FATAL has the opposite meaning as 'may-fail' property.
+ * ---end---
+ */
+
+ /**
+ * NMSettingIP6Config:ip6-privacy:
+ *
+ * Configure IPv6 Privacy Extensions for SLAAC, described in RFC4941. If
+ * enabled, it makes the kernel generate a temporary IPv6 address in
+ * addition to the public one generated from MAC address via modified
+ * EUI-64. This enhances privacy, but could cause problems in some
+ * applications, on the other hand. The permitted values are: 0: disabled,
+ * 1: enabled (prefer public address), 2: enabled (prefer temporary
+ * addresses).
+ **/
+ /* ---ifcfg-rh---
+ * property: ip6-privacy
+ * variable: IPV6_PRIVACY, IPV6_PRIVACY_PREFER_PUBLIC_IP(+)
+ * values: IPV6_PRIVACY: no, yes (rfc3041 or rfc4941);
+ * IPV6_PRIVACY_PREFER_PUBLIC_IP: yes, no
+ * default: no
+ * description: Configure IPv6 Privacy Extensions for SLAAC (RFC4941).
+ * example: IPV6_PRIVACY=rfc3041 IPV6_PRIVACY_PREFER_PUBLIC_IP=yes
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_IP6_PRIVACY,
+ g_param_spec_enum (NM_SETTING_IP6_CONFIG_IP6_PRIVACY, "", "",
+ NM_TYPE_SETTING_IP6_CONFIG_PRIVACY,
+ NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /* IP6-specific property overrides */
+
+ /* ---dbus---
+ * property: dns
+ * format: array of byte array
+ * 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);
+
+ /* ---dbus---
+ * property: addresses
+ * format: array of legacy IPv6 address struct (a(ayuay))
+ * description: Deprecated in favor of the 'address-data' and 'gateway'
+ * properties, but this can be used for backward-compatibility with older
+ * daemons. Note that if you send this property the daemon will ignore
+ * 'address-data' and 'gateway'.
+ *
+ * Array of IPv6 address structures. Each IPv6 address structure is
+ * composed of an IPv6 address, a prefix length (1 - 128), and an IPv6
+ * gateway address. The gateway may be zeroed out if no gateway exists for
+ * 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);
+
+ /* ---dbus---
+ * property: address-data
+ * format: array of vardict
+ * description: Array of IPv6 addresses. Each address dictionary contains at
+ * least 'address' and 'prefix' entries, containing the IP address as a
+ * string, and the prefix length as a uint32. Additional attributes may
+ * 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);
+
+ /* ---dbus---
+ * property: routes
+ * format: array of legacy IPv6 route struct (a(ayuayu))
+ * description: Deprecated in favor of the 'route-data' property, but this
+ * can be used for backward-compatibility with older daemons. Note that if
+ * you send this property the daemon will ignore 'route-data'.
+ *
+ * Array of IPv6 route structures. Each IPv6 route structure is
+ * composed of an IPv6 address, a prefix length (1 - 128), an IPv6
+ * next hop address (which may be zeroed out if there is no next hop),
+ * and a metric. If the metric is 0, NM will choose an appropriate
+ * 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);
+
+ /* ---dbus---
+ * property: route-data
+ * format: array of vardict
+ * description: Array of IPv6 routes. Each route dictionary contains at
+ * least 'dest' and 'prefix' entries, containing the destination IP
+ * address as a string, and the prefix length as a uint32. Most routes
+ * will also have a 'next-hop' entry, containing the next hop IP address as
+ * a string. If the route has a 'metric' entry (containing a uint32), that
+ * will be used as the metric for the route (otherwise NM will pick a
+ * default value appropriate to the device). Additional attributes may
+ * 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);
+}
diff --git a/libnm-core/nm-setting-ip6-config.h b/libnm-core/nm-setting-ip6-config.h
new file mode 100644
index 000000000..b791e937b
--- /dev/null
+++ b/libnm-core/nm-setting-ip6-config.h
@@ -0,0 +1,136 @@
+/* -*- 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 2007 - 2014 Red Hat, Inc.
+ */
+
+#ifndef __NM_SETTING_IP6_CONFIG_H__
+#define __NM_SETTING_IP6_CONFIG_H__
+
+#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
+#error "Only <NetworkManager.h> can be included directly."
+#endif
+
+#include "nm-setting-ip-config.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_SETTING_IP6_CONFIG (nm_setting_ip6_config_get_type ())
+#define NM_SETTING_IP6_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_IP6_CONFIG, NMSettingIP6Config))
+#define NM_SETTING_IP6_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_IP6CONFIG, NMSettingIP6ConfigClass))
+#define NM_IS_SETTING_IP6_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_IP6_CONFIG))
+#define NM_IS_SETTING_IP6_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_IP6_CONFIG))
+#define NM_SETTING_IP6_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_IP6_CONFIG, NMSettingIP6ConfigClass))
+
+#define NM_SETTING_IP6_CONFIG_SETTING_NAME "ipv6"
+
+#define NM_SETTING_IP6_CONFIG_IP6_PRIVACY "ip6-privacy"
+
+/**
+ * NM_SETTING_IP6_CONFIG_METHOD_IGNORE:
+ *
+ * IPv6 is not required or is handled by some other mechanism, and NetworkManager
+ * should not configure IPv6 for this connection.
+ */
+#define NM_SETTING_IP6_CONFIG_METHOD_IGNORE "ignore"
+
+/**
+ * NM_SETTING_IP6_CONFIG_METHOD_AUTO:
+ *
+ * IPv6 configuration should be automatically determined via a method appropriate
+ * for the hardware interface, ie router advertisements, DHCP, or PPP or some
+ * other device-specific manner.
+ */
+#define NM_SETTING_IP6_CONFIG_METHOD_AUTO "auto"
+
+/**
+ * NM_SETTING_IP6_CONFIG_METHOD_DHCP:
+ *
+ * IPv6 configuration should be automatically determined via DHCPv6 only and
+ * router advertisements should be ignored.
+ */
+#define NM_SETTING_IP6_CONFIG_METHOD_DHCP "dhcp"
+
+/**
+ * NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL:
+ *
+ * IPv6 configuration should be automatically configured for link-local-only
+ * operation.
+ */
+#define NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL "link-local"
+
+/**
+ * NM_SETTING_IP6_CONFIG_METHOD_MANUAL:
+ *
+ * All necessary IPv6 configuration (addresses, prefix, DNS, etc) is specified
+ * in the setting's properties.
+ */
+#define NM_SETTING_IP6_CONFIG_METHOD_MANUAL "manual"
+
+/**
+ * NM_SETTING_IP6_CONFIG_METHOD_SHARED:
+ *
+ * This connection specifies configuration that allows other computers to
+ * connect through it to the default network (usually the Internet). The
+ * connection's interface will be assigned a private address, and router
+ * advertisements, a caching DNS server, and Network Address Translation (NAT)
+ * functionality will be started on this connection's interface to allow other
+ * devices to connect through that interface to the default network. (not yet
+ * supported for IPv6)
+ */
+#define NM_SETTING_IP6_CONFIG_METHOD_SHARED "shared"
+
+/**
+ * NMSettingIP6ConfigPrivacy:
+ * @NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN: unknown or no value specified
+ * @NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED: IPv6 Privacy Extensions are disabled
+ * @NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR: IPv6 Privacy Extensions
+ * are enabled, but public addresses are preferred over temporary addresses
+ * @NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR: IPv6 Privacy Extensions
+ * are enabled and temporary addresses are preferred over public addresses
+ *
+ * #NMSettingIP6ConfigPrivacy values indicate if and how IPv6 Privacy
+ * Extensions are used (RFC4941).
+ */
+typedef enum {
+ NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN = -1,
+ NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED = 0,
+ NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR = 1,
+ NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR = 2
+} NMSettingIP6ConfigPrivacy;
+
+struct _NMSettingIP6Config {
+ NMSettingIPConfig parent;
+};
+
+typedef struct {
+ NMSettingIPConfigClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingIP6ConfigClass;
+
+GType nm_setting_ip6_config_get_type (void);
+
+NMSetting *nm_setting_ip6_config_new (void);
+
+NMSettingIP6ConfigPrivacy nm_setting_ip6_config_get_ip6_privacy (NMSettingIP6Config *setting);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_IP6_CONFIG_H__ */
diff --git a/libnm-core/nm-setting-olpc-mesh.c b/libnm-core/nm-setting-olpc-mesh.c
new file mode 100644
index 000000000..c1d54bee8
--- /dev/null
+++ b/libnm-core/nm-setting-olpc-mesh.c
@@ -0,0 +1,268 @@
+/* -*- 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 2007 - 2013 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ * Copyright 2009 One Laptop per Child
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-olpc-mesh.h"
+#include "nm-dbus-interface.h"
+#include "nm-utils.h"
+#include "nm-utils-private.h"
+#include "nm-setting-private.h"
+
+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, 1))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_OLPC_MESH)
+
+#define NM_SETTING_OLPC_MESH_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMeshPrivate))
+
+typedef struct {
+ GBytes *ssid;
+ guint32 channel;
+ char *dhcp_anycast_addr;
+} NMSettingOlpcMeshPrivate;
+
+enum {
+ PROP_0,
+ PROP_SSID,
+ PROP_CHANNEL,
+ PROP_DHCP_ANYCAST_ADDRESS,
+
+ LAST_PROP
+};
+
+/**
+ * nm_setting_olpc_mesh_new:
+ *
+ * Creates a new #NMSettingOlpcMesh object with default values.
+ *
+ * Returns: the new empty #NMSettingOlpcMesh object
+ **/
+NMSetting *nm_setting_olpc_mesh_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_OLPC_MESH, NULL);
+}
+
+static void
+nm_setting_olpc_mesh_init (NMSettingOlpcMesh *setting)
+{
+}
+
+/**
+ * nm_setting_olpc_mesh_get_ssid:
+ *
+ * Returns: (transfer none):
+ */
+GBytes *
+nm_setting_olpc_mesh_get_ssid (NMSettingOlpcMesh *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_OLPC_MESH (setting), NULL);
+
+ return NM_SETTING_OLPC_MESH_GET_PRIVATE (setting)->ssid;
+}
+
+guint32
+nm_setting_olpc_mesh_get_channel (NMSettingOlpcMesh *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_OLPC_MESH (setting), 0);
+
+ return NM_SETTING_OLPC_MESH_GET_PRIVATE (setting)->channel;
+}
+
+const char *
+nm_setting_olpc_mesh_get_dhcp_anycast_address (NMSettingOlpcMesh *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_OLPC_MESH (setting), NULL);
+
+ return NM_SETTING_OLPC_MESH_GET_PRIVATE (setting)->dhcp_anycast_addr;
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ NMSettingOlpcMeshPrivate *priv = NM_SETTING_OLPC_MESH_GET_PRIVATE (setting);
+ gsize length;
+
+ if (!priv->ssid) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_OLPC_MESH_SETTING_NAME, NM_SETTING_OLPC_MESH_SSID);
+ return FALSE;
+ }
+
+ length = g_bytes_get_size (priv->ssid);
+ if (length == 0 || length > 32) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("SSID length is out of range <1-32> bytes"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_OLPC_MESH_SETTING_NAME, NM_SETTING_OLPC_MESH_SSID);
+ return FALSE;
+ }
+
+ if (priv->channel == 0 || priv->channel > 13) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%d' is not a valid channel"),
+ priv->channel);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_OLPC_MESH_SETTING_NAME, NM_SETTING_OLPC_MESH_CHANNEL);
+ return FALSE;
+ }
+
+ if (priv->dhcp_anycast_addr && !nm_utils_hwaddr_valid (priv->dhcp_anycast_addr, ETH_ALEN)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_OLPC_MESH_SETTING_NAME, NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+finalize (GObject *object)
+{
+ NMSettingOlpcMeshPrivate *priv = NM_SETTING_OLPC_MESH_GET_PRIVATE (object);
+
+ if (priv->ssid)
+ g_bytes_unref (priv->ssid);
+ g_free (priv->dhcp_anycast_addr);
+
+ G_OBJECT_CLASS (nm_setting_olpc_mesh_parent_class)->finalize (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingOlpcMeshPrivate *priv = NM_SETTING_OLPC_MESH_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_SSID:
+ if (priv->ssid)
+ g_bytes_unref (priv->ssid);
+ priv->ssid = g_value_dup_boxed (value);
+ break;
+ case PROP_CHANNEL:
+ priv->channel = g_value_get_uint (value);
+ break;
+ case PROP_DHCP_ANYCAST_ADDRESS:
+ g_free (priv->dhcp_anycast_addr);
+ priv->dhcp_anycast_addr = 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)
+{
+ NMSettingOlpcMesh *setting = NM_SETTING_OLPC_MESH (object);
+
+ switch (prop_id) {
+ case PROP_SSID:
+ g_value_set_boxed (value, nm_setting_olpc_mesh_get_ssid (setting));
+ break;
+ case PROP_CHANNEL:
+ g_value_set_uint (value, nm_setting_olpc_mesh_get_channel (setting));
+ break;
+ case PROP_DHCP_ANYCAST_ADDRESS:
+ g_value_set_string (value, nm_setting_olpc_mesh_get_dhcp_anycast_address (setting));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_setting_olpc_mesh_class_init (NMSettingOlpcMeshClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+ NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+ g_type_class_add_private (setting_class, 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 */
+ /**
+ * NMSettingOlpcMesh:ssid:
+ *
+ * SSID of the mesh network to join.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_SSID,
+ g_param_spec_boxed (NM_SETTING_OLPC_MESH_SSID, "", "",
+ G_TYPE_BYTES,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingOlpcMesh:channel:
+ *
+ * Channel on which the mesh network to join is located.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_CHANNEL,
+ g_param_spec_uint (NM_SETTING_OLPC_MESH_CHANNEL, "", "",
+ 0, G_MAXUINT32, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingOlpcMesh:dhcp-anycast-address:
+ *
+ * Anycast DHCP MAC address used when requesting an IP address via DHCP.
+ * The specific anycast address used determines which DHCP server class
+ * answers the request.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_DHCP_ANYCAST_ADDRESS,
+ g_param_spec_string (NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS, "", "",
+ 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);
+}
diff --git a/libnm-core/nm-setting-olpc-mesh.h b/libnm-core/nm-setting-olpc-mesh.h
new file mode 100644
index 000000000..6a1656514
--- /dev/null
+++ b/libnm-core/nm-setting-olpc-mesh.h
@@ -0,0 +1,67 @@
+/* -*- 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 2007 - 2008 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ * Copyright 2009 One Laptop per Child
+ */
+
+#ifndef __NM_SETTING_OLPC_MESH_H__
+#define __NM_SETTING_OLPC_MESH_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_OLPC_MESH (nm_setting_olpc_mesh_get_type ())
+#define NM_SETTING_OLPC_MESH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMesh))
+#define NM_SETTING_OLPC_MESH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMeshClass))
+#define NM_IS_SETTING_OLPC_MESH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_OLPC_MESH))
+#define NM_IS_SETTING_OLPC_MESH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_OLPC_MESH))
+#define NM_SETTING_OLPC_MESH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_OLPC_MESH, NMSettingOlpcMeshClass))
+
+#define NM_SETTING_OLPC_MESH_SETTING_NAME "802-11-olpc-mesh"
+
+#define NM_SETTING_OLPC_MESH_SSID "ssid"
+#define NM_SETTING_OLPC_MESH_CHANNEL "channel"
+#define NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS "dhcp-anycast-address"
+
+struct _NMSettingOlpcMesh {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingOlpcMeshClass;
+
+GType nm_setting_olpc_mesh_get_type (void);
+
+NMSetting * nm_setting_olpc_mesh_new (void);
+GBytes * nm_setting_olpc_mesh_get_ssid (NMSettingOlpcMesh *setting);
+guint32 nm_setting_olpc_mesh_get_channel (NMSettingOlpcMesh *setting);
+const char * nm_setting_olpc_mesh_get_dhcp_anycast_address (NMSettingOlpcMesh *setting);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_OLPC_MESH_H__ */
diff --git a/libnm-core/nm-setting-ppp.c b/libnm-core/nm-setting-ppp.c
new file mode 100644
index 000000000..01f798ea7
--- /dev/null
+++ b/libnm-core/nm-setting-ppp.c
@@ -0,0 +1,803 @@
+/* -*- 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 2007 - 2013 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-ppp.h"
+#include "nm-setting-private.h"
+
+/**
+ * SECTION:nm-setting-ppp
+ * @short_description: Describes connection properties for devices/networks
+ * that require PPP to deliver IP capability
+ *
+ * The #NMSettingPpp object is a #NMSetting subclass that describes properties
+ * necessary for connection to networks that require PPP transport, like PPPoE
+ * 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, 3))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_PPP)
+
+#define NM_SETTING_PPP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_PPP, NMSettingPppPrivate))
+
+typedef struct {
+ gboolean noauth;
+ gboolean refuse_eap;
+ gboolean refuse_pap;
+ gboolean refuse_chap;
+ gboolean refuse_mschap;
+ gboolean refuse_mschapv2;
+ gboolean nobsdcomp;
+ gboolean nodeflate;
+ gboolean no_vj_comp;
+ gboolean require_mppe;
+ gboolean require_mppe_128;
+ gboolean mppe_stateful;
+ gboolean crtscts;
+ guint32 baud;
+ guint32 mru;
+ guint32 mtu;
+ guint32 lcp_echo_failure;
+ guint32 lcp_echo_interval;
+} NMSettingPppPrivate;
+
+enum {
+ PROP_0,
+ PROP_NOAUTH,
+ PROP_REFUSE_EAP,
+ PROP_REFUSE_PAP,
+ PROP_REFUSE_CHAP,
+ PROP_REFUSE_MSCHAP,
+ PROP_REFUSE_MSCHAPV2,
+ PROP_NOBSDCOMP,
+ PROP_NODEFLATE,
+ PROP_NO_VJ_COMP,
+ PROP_REQUIRE_MPPE,
+ PROP_REQUIRE_MPPE_128,
+ PROP_MPPE_STATEFUL,
+ PROP_CRTSCTS,
+ PROP_BAUD,
+ PROP_MRU,
+ PROP_MTU,
+ PROP_LCP_ECHO_FAILURE,
+ PROP_LCP_ECHO_INTERVAL,
+
+ LAST_PROP
+};
+
+/**
+ * nm_setting_ppp_new:
+ *
+ * Creates a new #NMSettingPpp object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingPpp object
+ **/
+NMSetting *
+nm_setting_ppp_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_PPP, NULL);
+}
+
+/**
+ * nm_setting_ppp_get_noauth:
+ * @setting: the #NMSettingPpp
+ *
+ * Returns: the #NMSettingPpp:noauth property of the setting
+ **/
+gboolean
+nm_setting_ppp_get_noauth (NMSettingPpp *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE);
+
+ return NM_SETTING_PPP_GET_PRIVATE (setting)->noauth;
+}
+
+/**
+ * nm_setting_ppp_get_refuse_eap:
+ * @setting: the #NMSettingPpp
+ *
+ * Returns: the #NMSettingPpp:refuse-eap property of the setting
+ **/
+gboolean
+nm_setting_ppp_get_refuse_eap (NMSettingPpp *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE);
+
+ return NM_SETTING_PPP_GET_PRIVATE (setting)->refuse_eap;
+}
+
+/**
+ * nm_setting_ppp_get_refuse_pap:
+ * @setting: the #NMSettingPpp
+ *
+ * Returns: the #NMSettingPpp:refuse-pap property of the setting
+ **/
+gboolean
+nm_setting_ppp_get_refuse_pap (NMSettingPpp *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE);
+
+ return NM_SETTING_PPP_GET_PRIVATE (setting)->refuse_pap;
+}
+
+/**
+ * nm_setting_ppp_get_refuse_chap:
+ * @setting: the #NMSettingPpp
+ *
+ * Returns: the #NMSettingPpp:refuse-chap property of the setting
+ **/
+gboolean
+nm_setting_ppp_get_refuse_chap (NMSettingPpp *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE);
+
+ return NM_SETTING_PPP_GET_PRIVATE (setting)->refuse_chap;
+}
+
+/**
+ * nm_setting_ppp_get_refuse_mschap:
+ * @setting: the #NMSettingPpp
+ *
+ * Returns: the #NMSettingPpp:refuse-mschap property of the setting
+ **/
+gboolean
+nm_setting_ppp_get_refuse_mschap (NMSettingPpp *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE);
+
+ return NM_SETTING_PPP_GET_PRIVATE (setting)->refuse_mschap;
+}
+
+/**
+ * nm_setting_ppp_get_refuse_mschapv2:
+ * @setting: the #NMSettingPpp
+ *
+ * Returns: the #NMSettingPpp:refuse-mschapv2 property of the setting
+ **/
+gboolean
+nm_setting_ppp_get_refuse_mschapv2 (NMSettingPpp *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE);
+
+ return NM_SETTING_PPP_GET_PRIVATE (setting)->refuse_mschapv2;
+}
+
+/**
+ * nm_setting_ppp_get_nobsdcomp:
+ * @setting: the #NMSettingPpp
+ *
+ * Returns: the #NMSettingPpp:nobsdcomp property of the setting
+ **/
+gboolean
+nm_setting_ppp_get_nobsdcomp (NMSettingPpp *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE);
+
+ return NM_SETTING_PPP_GET_PRIVATE (setting)->nobsdcomp;
+}
+
+/**
+ * nm_setting_ppp_get_nodeflate:
+ * @setting: the #NMSettingPpp
+ *
+ * Returns: the #NMSettingPpp:nodeflate property of the setting
+ **/
+gboolean
+nm_setting_ppp_get_nodeflate (NMSettingPpp *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE);
+
+ return NM_SETTING_PPP_GET_PRIVATE (setting)->nodeflate;
+}
+
+/**
+ * nm_setting_ppp_get_no_vj_comp:
+ * @setting: the #NMSettingPpp
+ *
+ * Returns: the #NMSettingPpp:no-vj-comp property of the setting
+ **/
+gboolean
+nm_setting_ppp_get_no_vj_comp (NMSettingPpp *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE);
+
+ return NM_SETTING_PPP_GET_PRIVATE (setting)->no_vj_comp;
+}
+
+/**
+ * nm_setting_ppp_get_require_mppe:
+ * @setting: the #NMSettingPpp
+ *
+ * Returns: the #NMSettingPpp:require-mppe property of the setting
+ **/
+gboolean
+nm_setting_ppp_get_require_mppe (NMSettingPpp *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE);
+
+ return NM_SETTING_PPP_GET_PRIVATE (setting)->require_mppe;
+}
+
+/**
+ * nm_setting_ppp_get_require_mppe_128:
+ * @setting: the #NMSettingPpp
+ *
+ * Returns: the #NMSettingPpp:require-mppe-128 property of the setting
+ **/
+gboolean
+nm_setting_ppp_get_require_mppe_128 (NMSettingPpp *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE);
+
+ return NM_SETTING_PPP_GET_PRIVATE (setting)->require_mppe_128;
+}
+
+/**
+ * nm_setting_ppp_get_mppe_stateful:
+ * @setting: the #NMSettingPpp
+ *
+ * Returns: the #NMSettingPpp:mppe-stateful property of the setting
+ **/
+gboolean
+nm_setting_ppp_get_mppe_stateful (NMSettingPpp *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE);
+
+ return NM_SETTING_PPP_GET_PRIVATE (setting)->mppe_stateful;
+}
+
+/**
+ * nm_setting_ppp_get_crtscts:
+ * @setting: the #NMSettingPpp
+ *
+ * Returns: the #NMSettingPpp:crtscts property of the setting
+ **/
+gboolean
+nm_setting_ppp_get_crtscts (NMSettingPpp *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_PPP (setting), FALSE);
+
+ return NM_SETTING_PPP_GET_PRIVATE (setting)->crtscts;
+}
+
+/**
+ * nm_setting_ppp_get_baud:
+ * @setting: the #NMSettingPpp
+ *
+ * Returns: the #NMSettingPpp:baud property of the setting
+ **/
+guint32
+nm_setting_ppp_get_baud (NMSettingPpp *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_PPP (setting), 0);
+
+ return NM_SETTING_PPP_GET_PRIVATE (setting)->baud;
+}
+
+/**
+ * nm_setting_ppp_get_mru:
+ * @setting: the #NMSettingPpp
+ *
+ * Returns: the #NMSettingPpp:mru property of the setting
+ **/
+guint32
+nm_setting_ppp_get_mru (NMSettingPpp *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_PPP (setting), 0);
+
+ return NM_SETTING_PPP_GET_PRIVATE (setting)->mru;
+}
+
+/**
+ * nm_setting_ppp_get_mtu:
+ * @setting: the #NMSettingPpp
+ *
+ * Returns: the #NMSettingPpp:mtu property of the setting
+ **/
+guint32
+nm_setting_ppp_get_mtu (NMSettingPpp *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_PPP (setting), 0);
+
+ return NM_SETTING_PPP_GET_PRIVATE (setting)->mtu;
+}
+
+/**
+ * nm_setting_ppp_get_lcp_echo_failure:
+ * @setting: the #NMSettingPpp
+ *
+ * Returns: the #NMSettingPpp:lcp-echo-failure property of the setting
+ **/
+guint32
+nm_setting_ppp_get_lcp_echo_failure (NMSettingPpp *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_PPP (setting), 0);
+
+ return NM_SETTING_PPP_GET_PRIVATE (setting)->lcp_echo_failure;
+}
+
+/**
+ * nm_setting_ppp_get_lcp_echo_interval:
+ * @setting: the #NMSettingPpp
+ *
+ * Returns: the #NMSettingPpp:lcp-echo-interval property of the setting
+ **/
+guint32
+nm_setting_ppp_get_lcp_echo_interval (NMSettingPpp *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_PPP (setting), 0);
+
+ return NM_SETTING_PPP_GET_PRIVATE (setting)->lcp_echo_interval;
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ NMSettingPppPrivate *priv = NM_SETTING_PPP_GET_PRIVATE (setting);
+
+ /* FIXME: Do we even want this or can we just let pppd evaluate the options? */
+ if (priv->mru > 0) {
+ if (priv->mru < 128 || priv->mru > 16384) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%d' is out of valid range <128-16384>"),
+ priv->mru);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_PPP_SETTING_NAME, NM_SETTING_PPP_MRU);
+ return FALSE;
+ }
+ }
+
+ if (priv->lcp_echo_failure > 0) {
+ /* lcp_echo_interval must also be non-zero */
+ if (priv->lcp_echo_interval == 0) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("setting this property requires non-zero '%s' property"),
+ NM_SETTING_PPP_LCP_ECHO_INTERVAL);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_PPP_SETTING_NAME, NM_SETTING_PPP_LCP_ECHO_FAILURE);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static void
+nm_setting_ppp_init (NMSettingPpp *setting)
+{
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingPppPrivate *priv = NM_SETTING_PPP_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_NOAUTH:
+ priv->noauth = g_value_get_boolean (value);
+ break;
+ case PROP_REFUSE_EAP:
+ priv->refuse_eap = g_value_get_boolean (value);
+ break;
+ case PROP_REFUSE_PAP:
+ priv->refuse_pap = g_value_get_boolean (value);
+ break;
+ case PROP_REFUSE_CHAP:
+ priv->refuse_chap = g_value_get_boolean (value);
+ break;
+ case PROP_REFUSE_MSCHAP:
+ priv->refuse_mschap = g_value_get_boolean (value);
+ break;
+ case PROP_REFUSE_MSCHAPV2:
+ priv->refuse_mschapv2 = g_value_get_boolean (value);
+ break;
+ case PROP_NOBSDCOMP:
+ priv->nobsdcomp = g_value_get_boolean (value);
+ break;
+ case PROP_NODEFLATE:
+ priv->nodeflate = g_value_get_boolean (value);
+ break;
+ case PROP_NO_VJ_COMP:
+ priv->no_vj_comp = g_value_get_boolean (value);
+ break;
+ case PROP_REQUIRE_MPPE:
+ priv->require_mppe = g_value_get_boolean (value);
+ break;
+ case PROP_REQUIRE_MPPE_128:
+ priv->require_mppe_128 = g_value_get_boolean (value);
+ break;
+ case PROP_MPPE_STATEFUL:
+ priv->mppe_stateful = g_value_get_boolean (value);
+ break;
+ case PROP_CRTSCTS:
+ priv->crtscts = g_value_get_boolean (value);
+ break;
+ case PROP_BAUD:
+ priv->baud = g_value_get_uint (value);
+ break;
+ case PROP_MRU:
+ priv->mru = g_value_get_uint (value);
+ break;
+ case PROP_MTU:
+ priv->mtu = g_value_get_uint (value);
+ break;
+ case PROP_LCP_ECHO_FAILURE:
+ priv->lcp_echo_failure = g_value_get_uint (value);
+ break;
+ case PROP_LCP_ECHO_INTERVAL:
+ priv->lcp_echo_interval = g_value_get_uint (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)
+{
+ NMSettingPpp *setting = NM_SETTING_PPP (object);
+
+ switch (prop_id) {
+ case PROP_NOAUTH:
+ g_value_set_boolean (value, nm_setting_ppp_get_noauth (setting));
+ break;
+ case PROP_REFUSE_EAP:
+ g_value_set_boolean (value, nm_setting_ppp_get_refuse_eap (setting));
+ break;
+ case PROP_REFUSE_PAP:
+ g_value_set_boolean (value, nm_setting_ppp_get_refuse_pap (setting));
+ break;
+ case PROP_REFUSE_CHAP:
+ g_value_set_boolean (value, nm_setting_ppp_get_refuse_chap (setting));
+ break;
+ case PROP_REFUSE_MSCHAP:
+ g_value_set_boolean (value, nm_setting_ppp_get_refuse_mschap (setting));
+ break;
+ case PROP_REFUSE_MSCHAPV2:
+ g_value_set_boolean (value, nm_setting_ppp_get_refuse_mschapv2 (setting));
+ break;
+ case PROP_NOBSDCOMP:
+ g_value_set_boolean (value, nm_setting_ppp_get_nobsdcomp (setting));
+ break;
+ case PROP_NODEFLATE:
+ g_value_set_boolean (value, nm_setting_ppp_get_nodeflate (setting));
+ break;
+ case PROP_NO_VJ_COMP:
+ g_value_set_boolean (value, nm_setting_ppp_get_no_vj_comp (setting));
+ break;
+ case PROP_REQUIRE_MPPE:
+ g_value_set_boolean (value, nm_setting_ppp_get_require_mppe (setting));
+ break;
+ case PROP_REQUIRE_MPPE_128:
+ g_value_set_boolean (value, nm_setting_ppp_get_require_mppe_128 (setting));
+ break;
+ case PROP_MPPE_STATEFUL:
+ g_value_set_boolean (value, nm_setting_ppp_get_mppe_stateful (setting));
+ break;
+ case PROP_CRTSCTS:
+ g_value_set_boolean (value, nm_setting_ppp_get_crtscts (setting));
+ break;
+ case PROP_BAUD:
+ g_value_set_uint (value, nm_setting_ppp_get_baud (setting));
+ break;
+ case PROP_MRU:
+ g_value_set_uint (value, nm_setting_ppp_get_mru (setting));
+ break;
+ case PROP_MTU:
+ g_value_set_uint (value, nm_setting_ppp_get_mtu (setting));
+ break;
+ case PROP_LCP_ECHO_FAILURE:
+ g_value_set_uint (value, nm_setting_ppp_get_lcp_echo_failure (setting));
+ break;
+ case PROP_LCP_ECHO_INTERVAL:
+ g_value_set_uint (value, nm_setting_ppp_get_lcp_echo_interval (setting));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_setting_ppp_class_init (NMSettingPppClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+ NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+ g_type_class_add_private (setting_class, sizeof (NMSettingPppPrivate));
+
+ /* virtual methods */
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+ parent_class->verify = verify;
+
+ /* Properties */
+ /**
+ * NMSettingPpp:noauth:
+ *
+ * If %TRUE, do not require the other side (usually the PPP server) to
+ * authenticate itself to the client. If %FALSE, require authentication
+ * from the remote side. In almost all cases, this should be %TRUE.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_NOAUTH,
+ g_param_spec_boolean (NM_SETTING_PPP_NOAUTH, "", "",
+ TRUE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingPpp:refuse-eap:
+ *
+ * If %TRUE, the EAP authentication method will not be used.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_REFUSE_EAP,
+ g_param_spec_boolean (NM_SETTING_PPP_REFUSE_EAP, "", "",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingPpp:refuse-pap:
+ *
+ * If %TRUE, the PAP authentication method will not be used.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_REFUSE_PAP,
+ g_param_spec_boolean (NM_SETTING_PPP_REFUSE_PAP, "", "",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingPpp:refuse-chap:
+ *
+ * If %TRUE, the CHAP authentication method will not be used.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_REFUSE_CHAP,
+ g_param_spec_boolean (NM_SETTING_PPP_REFUSE_CHAP, "", "",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingPpp:refuse-mschap:
+ *
+ * If %TRUE, the MSCHAP authentication method will not be used.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_REFUSE_MSCHAP,
+ g_param_spec_boolean (NM_SETTING_PPP_REFUSE_MSCHAP, "", "",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingPpp:refuse-mschapv2:
+ *
+ * If %TRUE, the MSCHAPv2 authentication method will not be used.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_REFUSE_MSCHAPV2,
+ g_param_spec_boolean (NM_SETTING_PPP_REFUSE_MSCHAPV2, "", "",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingPpp:nobsdcomp:
+ *
+ * If %TRUE, BSD compression will not be requested.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_NOBSDCOMP,
+ g_param_spec_boolean (NM_SETTING_PPP_NOBSDCOMP, "", "",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingPpp:nodeflate:
+ *
+ * If %TRUE, "deflate" compression will not be requested.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_NODEFLATE,
+ g_param_spec_boolean (NM_SETTING_PPP_NODEFLATE, "", "",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingPpp:no-vj-comp:
+ *
+ * If %TRUE, Van Jacobsen TCP header compression will not be requested.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_NO_VJ_COMP,
+ g_param_spec_boolean (NM_SETTING_PPP_NO_VJ_COMP, "", "",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingPpp:require-mppe:
+ *
+ * If %TRUE, MPPE (Microsoft Point-to-Point Encrpytion) will be required for
+ * the PPP session. If either 64-bit or 128-bit MPPE is not available the
+ * session will fail. Note that MPPE is not used on mobile broadband
+ * connections.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_REQUIRE_MPPE,
+ g_param_spec_boolean (NM_SETTING_PPP_REQUIRE_MPPE, "", "",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingPpp:require-mppe-128:
+ *
+ * If %TRUE, 128-bit MPPE (Microsoft Point-to-Point Encrpytion) will be
+ * required for the PPP session, and the "require-mppe" property must also
+ * be set to %TRUE. If 128-bit MPPE is not available the session will fail.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_REQUIRE_MPPE_128,
+ g_param_spec_boolean (NM_SETTING_PPP_REQUIRE_MPPE_128, "", "",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingPpp:mppe-stateful:
+ *
+ * If %TRUE, stateful MPPE is used. See pppd documentation for more
+ * information on stateful MPPE.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_MPPE_STATEFUL,
+ g_param_spec_boolean (NM_SETTING_PPP_MPPE_STATEFUL, "", "",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingPpp:crtscts:
+ *
+ * If %TRUE, specify that pppd should set the serial port to use hardware
+ * flow control with RTS and CTS signals. This value should normally be set
+ * to %FALSE.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_CRTSCTS,
+ g_param_spec_boolean (NM_SETTING_PPP_CRTSCTS, "", "",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingPpp:baud:
+ *
+ * If non-zero, instruct pppd to set the serial port to the specified
+ * baudrate. This value should normally be left as 0 to automatically
+ * choose the speed.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_BAUD,
+ g_param_spec_uint (NM_SETTING_PPP_BAUD, "", "",
+ 0, G_MAXUINT32, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingPpp:mru:
+ *
+ * If non-zero, instruct pppd to request that the peer send packets no
+ * larger than the specified size. If non-zero, the MRU should be between
+ * 128 and 16384.
+ */
+ g_object_class_install_property
+ (object_class, PROP_MRU,
+ g_param_spec_uint (NM_SETTING_PPP_MRU, "", "",
+ 0, 16384, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingPpp:mtu:
+ *
+ * If non-zero, instruct pppd to send packets no larger than the specified
+ * size.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_MTU,
+ g_param_spec_uint (NM_SETTING_PPP_MTU, "", "",
+ 0, G_MAXUINT32, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingPpp:lcp-echo-failure:
+ *
+ * If non-zero, instruct pppd to presume the connection to the peer has
+ * failed if the specified number of LCP echo-requests go unanswered by the
+ * peer. The "lcp-echo-interval" property must also be set to a non-zero
+ * value if this property is used.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_LCP_ECHO_FAILURE,
+ g_param_spec_uint (NM_SETTING_PPP_LCP_ECHO_FAILURE, "", "",
+ 0, G_MAXUINT32, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingPpp:lcp-echo-interval:
+ *
+ * If non-zero, instruct pppd to send an LCP echo-request frame to the peer
+ * every n seconds (where n is the specified value). Note that some PPP
+ * peers will respond to echo requests and some will not, and it is not
+ * possible to autodetect this.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_LCP_ECHO_INTERVAL,
+ g_param_spec_uint (NM_SETTING_PPP_LCP_ECHO_INTERVAL, "", "",
+ 0, G_MAXUINT32, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_STATIC_STRINGS));
+}
diff --git a/libnm-core/nm-setting-ppp.h b/libnm-core/nm-setting-ppp.h
new file mode 100644
index 000000000..2e0162cc5
--- /dev/null
+++ b/libnm-core/nm-setting-ppp.h
@@ -0,0 +1,97 @@
+/* -*- 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 2007 - 2008 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#ifndef __NM_SETTING_PPP_H__
+#define __NM_SETTING_PPP_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_PPP (nm_setting_ppp_get_type ())
+#define NM_SETTING_PPP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_PPP, NMSettingPpp))
+#define NM_SETTING_PPP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_PPP, NMSettingPppClass))
+#define NM_IS_SETTING_PPP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_PPP))
+#define NM_IS_SETTING_PPP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_PPP))
+#define NM_SETTING_PPP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_PPP, NMSettingPppClass))
+
+#define NM_SETTING_PPP_SETTING_NAME "ppp"
+
+#define NM_SETTING_PPP_NOAUTH "noauth"
+#define NM_SETTING_PPP_REFUSE_EAP "refuse-eap"
+#define NM_SETTING_PPP_REFUSE_PAP "refuse-pap"
+#define NM_SETTING_PPP_REFUSE_CHAP "refuse-chap"
+#define NM_SETTING_PPP_REFUSE_MSCHAP "refuse-mschap"
+#define NM_SETTING_PPP_REFUSE_MSCHAPV2 "refuse-mschapv2"
+#define NM_SETTING_PPP_NOBSDCOMP "nobsdcomp"
+#define NM_SETTING_PPP_NODEFLATE "nodeflate"
+#define NM_SETTING_PPP_NO_VJ_COMP "no-vj-comp"
+#define NM_SETTING_PPP_REQUIRE_MPPE "require-mppe"
+#define NM_SETTING_PPP_REQUIRE_MPPE_128 "require-mppe-128"
+#define NM_SETTING_PPP_MPPE_STATEFUL "mppe-stateful"
+#define NM_SETTING_PPP_CRTSCTS "crtscts"
+#define NM_SETTING_PPP_BAUD "baud"
+#define NM_SETTING_PPP_MRU "mru"
+#define NM_SETTING_PPP_MTU "mtu"
+#define NM_SETTING_PPP_LCP_ECHO_FAILURE "lcp-echo-failure"
+#define NM_SETTING_PPP_LCP_ECHO_INTERVAL "lcp-echo-interval"
+
+struct _NMSettingPpp {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingPppClass;
+
+GType nm_setting_ppp_get_type (void);
+
+NMSetting *nm_setting_ppp_new (void);
+gboolean nm_setting_ppp_get_noauth (NMSettingPpp *setting);
+gboolean nm_setting_ppp_get_refuse_eap (NMSettingPpp *setting);
+gboolean nm_setting_ppp_get_refuse_pap (NMSettingPpp *setting);
+gboolean nm_setting_ppp_get_refuse_chap (NMSettingPpp *setting);
+gboolean nm_setting_ppp_get_refuse_mschap (NMSettingPpp *setting);
+gboolean nm_setting_ppp_get_refuse_mschapv2 (NMSettingPpp *setting);
+gboolean nm_setting_ppp_get_nobsdcomp (NMSettingPpp *setting);
+gboolean nm_setting_ppp_get_nodeflate (NMSettingPpp *setting);
+gboolean nm_setting_ppp_get_no_vj_comp (NMSettingPpp *setting);
+gboolean nm_setting_ppp_get_require_mppe (NMSettingPpp *setting);
+gboolean nm_setting_ppp_get_require_mppe_128 (NMSettingPpp *setting);
+gboolean nm_setting_ppp_get_mppe_stateful (NMSettingPpp *setting);
+gboolean nm_setting_ppp_get_crtscts (NMSettingPpp *setting);
+guint32 nm_setting_ppp_get_baud (NMSettingPpp *setting);
+guint32 nm_setting_ppp_get_mru (NMSettingPpp *setting);
+guint32 nm_setting_ppp_get_mtu (NMSettingPpp *setting);
+guint32 nm_setting_ppp_get_lcp_echo_failure (NMSettingPpp *setting);
+guint32 nm_setting_ppp_get_lcp_echo_interval (NMSettingPpp *setting);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_PPP_H__ */
diff --git a/libnm-core/nm-setting-pppoe.c b/libnm-core/nm-setting-pppoe.c
new file mode 100644
index 000000000..ac6764d06
--- /dev/null
+++ b/libnm-core/nm-setting-pppoe.c
@@ -0,0 +1,322 @@
+/* -*- 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 2007 - 2013 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-pppoe.h"
+#include "nm-setting-ppp.h"
+#include "nm-setting-private.h"
+#include "nm-core-enum-types.h"
+
+/**
+ * SECTION:nm-setting-pppoe
+ * @short_description: Describes PPPoE connection properties
+ *
+ * The #NMSettingPppoe object is a #NMSetting subclass that describes
+ * properties necessary for connection to networks that require PPPoE connections
+ * 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, 3))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_PPPOE)
+
+#define NM_SETTING_PPPOE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_PPPOE, NMSettingPppoePrivate))
+
+typedef struct {
+ char *service;
+ char *username;
+ char *password;
+ NMSettingSecretFlags password_flags;
+} NMSettingPppoePrivate;
+
+enum {
+ PROP_0,
+ PROP_SERVICE,
+ PROP_USERNAME,
+ PROP_PASSWORD,
+ PROP_PASSWORD_FLAGS,
+
+ LAST_PROP
+};
+
+/**
+ * nm_setting_pppoe_new:
+ *
+ * Creates a new #NMSettingPppoe object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingPppoe object
+ **/
+NMSetting *
+nm_setting_pppoe_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_PPPOE, NULL);
+}
+
+/**
+ * nm_setting_pppoe_get_service:
+ * @setting: the #NMSettingPppoe
+ *
+ * Returns: the #NMSettingPppoe:service property of the setting
+ **/
+const char *
+nm_setting_pppoe_get_service (NMSettingPppoe *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_PPPOE (setting), NULL);
+
+ return NM_SETTING_PPPOE_GET_PRIVATE (setting)->service;
+}
+
+/**
+ * nm_setting_pppoe_get_username:
+ * @setting: the #NMSettingPppoe
+ *
+ * Returns: the #NMSettingPppoe:username property of the setting
+ **/
+const char *
+nm_setting_pppoe_get_username (NMSettingPppoe *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_PPPOE (setting), NULL);
+
+ return NM_SETTING_PPPOE_GET_PRIVATE (setting)->username;
+}
+
+/**
+ * nm_setting_pppoe_get_password:
+ * @setting: the #NMSettingPppoe
+ *
+ * Returns: the #NMSettingPppoe:password property of the setting
+ **/
+const char *
+nm_setting_pppoe_get_password (NMSettingPppoe *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_PPPOE (setting), NULL);
+
+ return NM_SETTING_PPPOE_GET_PRIVATE (setting)->password;
+}
+
+/**
+ * nm_setting_pppoe_get_password_flags:
+ * @setting: the #NMSettingPppoe
+ *
+ * Returns: the #NMSettingSecretFlags pertaining to the #NMSettingPppoe:password
+ **/
+NMSettingSecretFlags
+nm_setting_pppoe_get_password_flags (NMSettingPppoe *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_PPPOE (setting), NM_SETTING_SECRET_FLAG_NONE);
+
+ return NM_SETTING_PPPOE_GET_PRIVATE (setting)->password_flags;
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ NMSettingPppoePrivate *priv = NM_SETTING_PPPOE_GET_PRIVATE (setting);
+
+ if (!priv->username) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_PPPOE_SETTING_NAME, NM_SETTING_PPPOE_USERNAME);
+ return FALSE;
+ } else if (!strlen (priv->username)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_PPPOE_SETTING_NAME, NM_SETTING_PPPOE_USERNAME);
+ return FALSE;
+ }
+
+ if (priv->service && !strlen (priv->service)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_PPPOE_SETTING_NAME, NM_SETTING_PPPOE_SERVICE);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static GPtrArray *
+need_secrets (NMSetting *setting)
+{
+ NMSettingPppoePrivate *priv = NM_SETTING_PPPOE_GET_PRIVATE (setting);
+ GPtrArray *secrets = NULL;
+
+ if (priv->password)
+ return NULL;
+
+ if (!(priv->password_flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED)) {
+ secrets = g_ptr_array_sized_new (1);
+ g_ptr_array_add (secrets, NM_SETTING_PPPOE_PASSWORD);
+ }
+
+ return secrets;
+}
+
+static void
+nm_setting_pppoe_init (NMSettingPppoe *setting)
+{
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingPppoePrivate *priv = NM_SETTING_PPPOE_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_SERVICE:
+ g_free (priv->service);
+ priv->service = g_value_dup_string (value);
+ break;
+ case PROP_USERNAME:
+ g_free (priv->username);
+ priv->username = g_value_dup_string (value);
+ break;
+ case PROP_PASSWORD:
+ g_free (priv->password);
+ priv->password = g_value_dup_string (value);
+ break;
+ case PROP_PASSWORD_FLAGS:
+ priv->password_flags = g_value_get_flags (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)
+{
+ NMSettingPppoe *setting = NM_SETTING_PPPOE (object);
+
+ switch (prop_id) {
+ case PROP_SERVICE:
+ g_value_set_string (value, nm_setting_pppoe_get_service (setting));
+ break;
+ case PROP_USERNAME:
+ g_value_set_string (value, nm_setting_pppoe_get_username (setting));
+ break;
+ case PROP_PASSWORD:
+ g_value_set_string (value, nm_setting_pppoe_get_password (setting));
+ break;
+ case PROP_PASSWORD_FLAGS:
+ g_value_set_flags (value, nm_setting_pppoe_get_password_flags (setting));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+finalize (GObject *object)
+{
+ NMSettingPppoePrivate *priv = NM_SETTING_PPPOE_GET_PRIVATE (object);
+
+ g_free (priv->username);
+ g_free (priv->password);
+ g_free (priv->service);
+
+ G_OBJECT_CLASS (nm_setting_pppoe_parent_class)->finalize (object);
+}
+
+static void
+nm_setting_pppoe_class_init (NMSettingPppoeClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+ NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+ g_type_class_add_private (setting_class, 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 */
+ /**
+ * NMSettingPppoe:service:
+ *
+ * If specified, instruct PPPoE to only initiate sessions with access
+ * concentrators that provide the specified service. For most providers,
+ * this should be left blank. It is only required if there are multiple
+ * access concentrators or a specific service is known to be required.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_SERVICE,
+ g_param_spec_string (NM_SETTING_PPPOE_SERVICE, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingPppoe:username:
+ *
+ * Username used to authenticate with the PPPoE service.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_USERNAME,
+ g_param_spec_string (NM_SETTING_PPPOE_USERNAME, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingPppoe:password:
+ *
+ * Password used to authenticate with the PPPoE service.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_PASSWORD,
+ g_param_spec_string (NM_SETTING_PPPOE_PASSWORD, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_SECRET |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingPppoe:password-flags:
+ *
+ * Flags indicating how to handle the #NMSettingPppoe:password property.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_PASSWORD_FLAGS,
+ g_param_spec_flags (NM_SETTING_PPPOE_PASSWORD_FLAGS, "", "",
+ NM_TYPE_SETTING_SECRET_FLAGS,
+ NM_SETTING_SECRET_FLAG_NONE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+}
diff --git a/libnm-core/nm-setting-pppoe.h b/libnm-core/nm-setting-pppoe.h
new file mode 100644
index 000000000..b1e0d92fe
--- /dev/null
+++ b/libnm-core/nm-setting-pppoe.h
@@ -0,0 +1,69 @@
+/* -*- 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 2007 - 2011 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#ifndef __NM_SETTING_PPPOE_H__
+#define __NM_SETTING_PPPOE_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_PPPOE (nm_setting_pppoe_get_type ())
+#define NM_SETTING_PPPOE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_PPPOE, NMSettingPppoe))
+#define NM_SETTING_PPPOE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_PPPOE, NMSettingPppoeClass))
+#define NM_IS_SETTING_PPPOE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_PPPOE))
+#define NM_IS_SETTING_PPPOE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_PPPOE))
+#define NM_SETTING_PPPOE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_PPPOE, NMSettingPppoeClass))
+
+#define NM_SETTING_PPPOE_SETTING_NAME "pppoe"
+
+#define NM_SETTING_PPPOE_SERVICE "service"
+#define NM_SETTING_PPPOE_USERNAME "username"
+#define NM_SETTING_PPPOE_PASSWORD "password"
+#define NM_SETTING_PPPOE_PASSWORD_FLAGS "password-flags"
+
+struct _NMSettingPppoe {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingPppoeClass;
+
+GType nm_setting_pppoe_get_type (void);
+
+NMSetting *nm_setting_pppoe_new (void);
+const char *nm_setting_pppoe_get_service (NMSettingPppoe *setting);
+const char *nm_setting_pppoe_get_username (NMSettingPppoe *setting);
+const char *nm_setting_pppoe_get_password (NMSettingPppoe *setting);
+NMSettingSecretFlags nm_setting_pppoe_get_password_flags (NMSettingPppoe *setting);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_PPPOE_H__ */
diff --git a/libnm-core/nm-setting-private.h b/libnm-core/nm-setting-private.h
new file mode 100644
index 000000000..2d34d509a
--- /dev/null
+++ b/libnm-core/nm-setting-private.h
@@ -0,0 +1,158 @@
+/* -*- 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 2011 Red Hat, Inc.
+ */
+
+#ifndef __NM_SETTING_PRIVATE_H__
+#define __NM_SETTING_PRIVATE_H__
+
+#include "nm-setting.h"
+#include "nm-connection.h"
+#include "nm-core-enum-types.h"
+#include "nm-glib-compat.h"
+
+#include "nm-core-internal.h"
+
+/**
+ * NMSettingVerifyResult:
+ * @NM_SETTING_VERIFY_SUCCESS: the setting verifies successfully
+ * @NM_SETTING_VERIFY_ERROR: the setting has a serious misconfiguration
+ * @NM_SETTING_VERIFY_NORMALIZABLE: the setting is valid but has properties
+ * that should be normalized
+ * @NM_SETTING_VERIFY_NORMALIZABLE_ERROR: the setting is invalid but the
+ * errors can be fixed by nm_connection_normalize().
+ */
+typedef enum {
+ NM_SETTING_VERIFY_SUCCESS = TRUE,
+ NM_SETTING_VERIFY_ERROR = FALSE,
+ NM_SETTING_VERIFY_NORMALIZABLE = 2,
+ NM_SETTING_VERIFY_NORMALIZABLE_ERROR = 3,
+} NMSettingVerifyResult;
+
+void _nm_register_setting (const char *name,
+ const GType type,
+ const guint32 priority);
+
+#define _nm_register_setting(name, priority) \
+ G_STMT_START { \
+ _nm_register_setting (NM_SETTING_ ## name ## _SETTING_NAME "", g_define_type_id, priority); \
+ } G_STMT_END
+
+gboolean _nm_setting_is_base_type (NMSetting *setting);
+gboolean _nm_setting_type_is_base_type (GType type);
+gint _nm_setting_compare_priority (gconstpointer a, gconstpointer b);
+
+typedef enum NMSettingUpdateSecretResult {
+ NM_SETTING_UPDATE_SECRET_ERROR = FALSE,
+ NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED = TRUE,
+ NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED = 2,
+} NMSettingUpdateSecretResult;
+
+NMSettingUpdateSecretResult _nm_setting_update_secrets (NMSetting *setting,
+ GVariant *secrets,
+ GError **error);
+gboolean _nm_setting_clear_secrets (NMSetting *setting);
+gboolean _nm_setting_clear_secrets_with_flags (NMSetting *setting,
+ NMSettingClearSecretsWithFlagsFn func,
+ gpointer user_data);
+
+
+/* The property of the #NMSetting should be considered during comparisons that
+ * use the %NM_SETTING_COMPARE_FLAG_INFERRABLE flag. Properties that don't have
+ * this flag, are ignored when doing an infrerrable comparison. This flag should
+ * be set on all properties that are read from the kernel or the system when a
+ * connection is generated. eg, IP addresses/routes can be read from the
+ * kernel, but the 'autoconnect' property cannot, so
+ * %NM_SETTING_IP4_CONFIG_ADDRESSES gets the INFERRABLE flag, but
+ * %NM_SETTING_CONNECTION_AUTOCONNECT would not.
+ *
+ * This flag should not be used with properties where the default cannot be
+ * read separately from the current value, like MTU or wired duplex mode.
+ */
+#define NM_SETTING_PARAM_INFERRABLE (1 << (4 + G_PARAM_USER_SHIFT))
+
+/* This is a legacy property, which clients should not send to the daemon. */
+#define NM_SETTING_PARAM_LEGACY (1 << (5 + 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_init (); g_type_ensure (x); }
+
+GVariant *_nm_setting_get_deprecated_virtual_interface_name (NMSetting *setting,
+ NMConnection *connection,
+ const char *property);
+
+NMSettingVerifyResult _nm_setting_verify (NMSetting *setting,
+ NMConnection *connection,
+ GError **error);
+
+gboolean _nm_setting_slave_type_is_valid (const char *slave_type, const char **out_port_type);
+
+GVariant *_nm_setting_to_dbus (NMSetting *setting,
+ NMConnection *connection,
+ NMConnectionSerializationFlags flags);
+
+NMSetting *_nm_setting_new_from_dbus (GType setting_type,
+ GVariant *setting_dict,
+ GVariant *connection_dict,
+ GError **error);
+
+typedef GVariant * (*NMSettingPropertyGetFunc) (NMSetting *setting,
+ const char *property);
+typedef GVariant * (*NMSettingPropertySynthFunc) (NMSetting *setting,
+ NMConnection *connection,
+ const char *property);
+typedef void (*NMSettingPropertySetFunc) (NMSetting *setting,
+ GVariant *connection_dict,
+ const char *property,
+ GVariant *value);
+typedef void (*NMSettingPropertyNotSetFunc) (NMSetting *setting,
+ GVariant *connection_dict,
+ const char *property);
+
+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);
+
+gboolean _nm_setting_use_legacy_property (NMSetting *setting,
+ GVariant *connection_dict,
+ const char *legacy_property,
+ const char *new_property);
+
+GPtrArray *_nm_setting_need_secrets (NMSetting *setting);
+
+#endif /* NM_SETTING_PRIVATE_H */
diff --git a/libnm-core/nm-setting-serial.c b/libnm-core/nm-setting-serial.c
new file mode 100644
index 000000000..3fd780c83
--- /dev/null
+++ b/libnm-core/nm-setting-serial.c
@@ -0,0 +1,351 @@
+/* -*- 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 2007 - 2011 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include "nm-setting-serial.h"
+#include "nm-glib-compat.h"
+#include "nm-setting-private.h"
+
+/**
+ * SECTION:nm-setting-serial
+ * @short_description: Describes connection properties for devices that use
+ * serial communications
+ *
+ * The #NMSettingSerial object is a #NMSetting subclass that describes
+ * properties necessary for connections that may use serial communications,
+ * such as mobile broadband or analog telephone connections.
+ **/
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingSerial, nm_setting_serial, NM_TYPE_SETTING,
+ _nm_register_setting (SERIAL, 2))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_SERIAL)
+
+#define NM_SETTING_SERIAL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_SERIAL, NMSettingSerialPrivate))
+
+typedef struct {
+ guint baud;
+ guint bits;
+ char parity;
+ guint stopbits;
+ guint64 send_delay;
+} NMSettingSerialPrivate;
+
+
+enum {
+ PROP_0,
+ PROP_BAUD,
+ PROP_BITS,
+ PROP_PARITY,
+ PROP_STOPBITS,
+ PROP_SEND_DELAY,
+
+ LAST_PROP
+};
+
+/**
+ * nm_setting_serial_new:
+ *
+ * Creates a new #NMSettingSerial object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingSerial object
+ **/
+NMSetting *
+nm_setting_serial_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_SERIAL, NULL);
+}
+
+/**
+ * nm_setting_serial_get_baud:
+ * @setting: the #NMSettingSerial
+ *
+ * Returns: the #NMSettingSerial:baud property of the setting
+ **/
+guint
+nm_setting_serial_get_baud (NMSettingSerial *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_SERIAL (setting), 0);
+
+ return NM_SETTING_SERIAL_GET_PRIVATE (setting)->baud;
+}
+
+/**
+ * nm_setting_serial_get_bits:
+ * @setting: the #NMSettingSerial
+ *
+ * Returns: the #NMSettingSerial:bits property of the setting
+ **/
+guint
+nm_setting_serial_get_bits (NMSettingSerial *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_SERIAL (setting), 0);
+
+ return NM_SETTING_SERIAL_GET_PRIVATE (setting)->bits;
+}
+
+/**
+ * nm_setting_serial_get_parity:
+ * @setting: the #NMSettingSerial
+ *
+ * Returns: the #NMSettingSerial:parity property of the setting
+ **/
+NMSettingSerialParity
+nm_setting_serial_get_parity (NMSettingSerial *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_SERIAL (setting), 0);
+
+ return NM_SETTING_SERIAL_GET_PRIVATE (setting)->parity;
+}
+
+/**
+ * nm_setting_serial_get_stopbits:
+ * @setting: the #NMSettingSerial
+ *
+ * Returns: the #NMSettingSerial:stopbits property of the setting
+ **/
+guint
+nm_setting_serial_get_stopbits (NMSettingSerial *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_SERIAL (setting), 0);
+
+ return NM_SETTING_SERIAL_GET_PRIVATE (setting)->stopbits;
+}
+
+/**
+ * nm_setting_serial_get_send_delay:
+ * @setting: the #NMSettingSerial
+ *
+ * Returns: the #NMSettingSerial:send-delay property of the setting
+ **/
+guint64
+nm_setting_serial_get_send_delay (NMSettingSerial *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_SERIAL (setting), 0);
+
+ 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)
+{
+}
+
+static GVariant *
+parity_to_dbus (const GValue *from)
+{
+ switch (g_value_get_enum (from)) {
+ case NM_SETTING_SERIAL_PARITY_EVEN:
+ return g_variant_new_byte ('E');
+ case NM_SETTING_SERIAL_PARITY_ODD:
+ return g_variant_new_byte ('o');
+ case NM_SETTING_SERIAL_PARITY_NONE:
+ default:
+ return g_variant_new_byte ('n');
+ }
+}
+
+static void
+parity_from_dbus (GVariant *from, GValue *to)
+{
+ switch (g_variant_get_byte (from)) {
+ case 'E':
+ g_value_set_enum (to, NM_SETTING_SERIAL_PARITY_EVEN);
+ break;
+ case 'o':
+ g_value_set_enum (to, NM_SETTING_SERIAL_PARITY_ODD);
+ break;
+ case 'n':
+ default:
+ g_value_set_enum (to, NM_SETTING_SERIAL_PARITY_NONE);
+ break;
+ }
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingSerialPrivate *priv = NM_SETTING_SERIAL_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_BAUD:
+ priv->baud = g_value_get_uint (value);
+ break;
+ case PROP_BITS:
+ priv->bits = g_value_get_uint (value);
+ break;
+ case PROP_PARITY:
+ priv->parity = g_value_get_enum (value);
+ break;
+ case PROP_STOPBITS:
+ priv->stopbits = g_value_get_uint (value);
+ break;
+ case PROP_SEND_DELAY:
+ priv->send_delay = g_value_get_uint64 (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)
+{
+ NMSettingSerial *setting = NM_SETTING_SERIAL (object);
+
+ switch (prop_id) {
+ case PROP_BAUD:
+ g_value_set_uint (value, nm_setting_serial_get_baud (setting));
+ break;
+ case PROP_BITS:
+ g_value_set_uint (value, nm_setting_serial_get_bits (setting));
+ break;
+ case PROP_PARITY:
+ g_value_set_enum (value, nm_setting_serial_get_parity (setting));
+ break;
+ case PROP_STOPBITS:
+ g_value_set_uint (value, nm_setting_serial_get_stopbits (setting));
+ break;
+ case PROP_SEND_DELAY:
+ g_value_set_uint64 (value, nm_setting_serial_get_send_delay (setting));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_setting_serial_class_init (NMSettingSerialClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+ NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+ g_type_class_add_private (setting_class, sizeof (NMSettingSerialPrivate));
+
+ /* virtual methods */
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+ parent_class->verify = verify;
+
+ /* Properties */
+
+ /**
+ * NMSettingSerial:baud:
+ *
+ * Speed to use for communication over the serial port. Note that this
+ * value usually has no effect for mobile broadband modems as they generally
+ * ignore speed settings and use the highest available speed.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_BAUD,
+ g_param_spec_uint (NM_SETTING_SERIAL_BAUD, "", "",
+ 0, G_MAXUINT, 57600,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingSerial:bits:
+ *
+ * Byte-width of the serial communication. The 8 in "8n1" for example.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_BITS,
+ g_param_spec_uint (NM_SETTING_SERIAL_BITS, "", "",
+ 5, 8, 8,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingSerial:parity:
+ *
+ * Parity setting of the serial port.
+ **/
+ /* ---keyfile---
+ * property: parity
+ * format: 'e', 'o', or 'n'
+ * description: The connection parity; even, odd, or none. Note that older
+ * versions of NetworkManager stored this as an integer: 69 ('E') for even,
+ * 111 ('o') for odd, or 110 ('n') for none.
+ * example: parity=n
+ * ---end---
+ * ---dbus---
+ * property: parity
+ * format: byte
+ * description: The connection parity: 69 (ASCII 'E') for even parity,
+ * 111 (ASCII 'o') for odd, 110 (ASCII 'n') for none.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_PARITY,
+ g_param_spec_enum (NM_SETTING_SERIAL_PARITY, "", "",
+ NM_TYPE_SETTING_SERIAL_PARITY,
+ NM_SETTING_SERIAL_PARITY_NONE,
+ 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);
+
+ /**
+ * NMSettingSerial:stopbits:
+ *
+ * Number of stop bits for communication on the serial port. Either 1 or 2.
+ * The 1 in "8n1" for example.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_STOPBITS,
+ g_param_spec_uint (NM_SETTING_SERIAL_STOPBITS, "", "",
+ 1, 2, 1,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingSerial:send-delay:
+ *
+ * Time to delay between each byte sent to the modem, in microseconds.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_SEND_DELAY,
+ g_param_spec_uint64 (NM_SETTING_SERIAL_SEND_DELAY, "", "",
+ 0, G_MAXUINT64, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+}
diff --git a/libnm-core/nm-setting-serial.h b/libnm-core/nm-setting-serial.h
new file mode 100644
index 000000000..582892277
--- /dev/null
+++ b/libnm-core/nm-setting-serial.h
@@ -0,0 +1,85 @@
+/* -*- 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 2007 - 2008 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#ifndef __NM_SETTING_SERIAL_H__
+#define __NM_SETTING_SERIAL_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_SERIAL (nm_setting_serial_get_type ())
+#define NM_SETTING_SERIAL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_SERIAL, NMSettingSerial))
+#define NM_SETTING_SERIAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_SERIAL, NMSettingSerialClass))
+#define NM_IS_SETTING_SERIAL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_SERIAL))
+#define NM_IS_SETTING_SERIAL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_SERIAL))
+#define NM_SETTING_SERIAL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_SERIAL, NMSettingSerialClass))
+
+#define NM_SETTING_SERIAL_SETTING_NAME "serial"
+
+/**
+ * NMSettingSerialParity:
+ * @NM_SETTING_SERIAL_PARITY_NONE: No parity bits (default)
+ * @NM_SETTING_SERIAL_PARITY_EVEN: Even parity
+ * @NM_SETTING_SERIAL_PARITY_ODD: Odd parity
+ *
+ * The parity setting of a serial port.
+ */
+typedef enum {
+ NM_SETTING_SERIAL_PARITY_NONE = 0,
+ NM_SETTING_SERIAL_PARITY_EVEN,
+ NM_SETTING_SERIAL_PARITY_ODD
+} NMSettingSerialParity;
+
+#define NM_SETTING_SERIAL_BAUD "baud"
+#define NM_SETTING_SERIAL_BITS "bits"
+#define NM_SETTING_SERIAL_PARITY "parity"
+#define NM_SETTING_SERIAL_STOPBITS "stopbits"
+#define NM_SETTING_SERIAL_SEND_DELAY "send-delay"
+
+struct _NMSettingSerial {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingSerialClass;
+
+GType nm_setting_serial_get_type (void);
+
+NMSetting *nm_setting_serial_new (void);
+guint nm_setting_serial_get_baud (NMSettingSerial *setting);
+guint nm_setting_serial_get_bits (NMSettingSerial *setting);
+NMSettingSerialParity nm_setting_serial_get_parity (NMSettingSerial *setting);
+guint nm_setting_serial_get_stopbits (NMSettingSerial *setting);
+guint64 nm_setting_serial_get_send_delay (NMSettingSerial *setting);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_SERIAL_H__ */
diff --git a/libnm-core/nm-setting-team-port.c b/libnm-core/nm-setting-team-port.c
new file mode 100644
index 000000000..b5125753c
--- /dev/null
+++ b/libnm-core/nm-setting-team-port.c
@@ -0,0 +1,192 @@
+/* -*- 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 2013 Jiri Pirko <jiri@resnulli.us>
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-team-port.h"
+#include "nm-utils.h"
+#include "nm-utils-private.h"
+#include "nm-connection-private.h"
+#include "nm-setting-connection.h"
+#include "nm-setting-team.h"
+
+/**
+ * SECTION:nm-setting-team-port
+ * @short_description: Describes connection properties for team ports
+ *
+ * The #NMSettingTeamPort object is a #NMSetting subclass that describes
+ * 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, 3))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_TEAM_PORT)
+
+#define NM_SETTING_TEAM_PORT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_TEAM_PORT, NMSettingTeamPortPrivate))
+
+typedef struct {
+ char *config;
+} NMSettingTeamPortPrivate;
+
+enum {
+ PROP_0,
+ PROP_CONFIG,
+ LAST_PROP
+};
+
+/**
+ * nm_setting_team_port_new:
+ *
+ * Creates a new #NMSettingTeamPort object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingTeamPort object
+ **/
+NMSetting *
+nm_setting_team_port_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_TEAM_PORT, NULL);
+}
+
+/**
+ * nm_setting_team_port_get_config:
+ * @setting: the #NMSettingTeamPort
+ *
+ * Returns: the #NMSettingTeamPort:config property of the setting
+ **/
+const char *
+nm_setting_team_port_get_config (NMSettingTeamPort *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_TEAM_PORT (setting), NULL);
+
+ return NM_SETTING_TEAM_PORT_GET_PRIVATE (setting)->config;
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ if (connection) {
+ NMSettingConnection *s_con;
+ const char *slave_type;
+
+ s_con = nm_connection_get_setting_connection (connection);
+ if (!s_con) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_SETTING,
+ _("missing setting"));
+ g_prefix_error (error, "%s: ", NM_SETTING_CONNECTION_SETTING_NAME);
+ return FALSE;
+ }
+
+ slave_type = nm_setting_connection_get_slave_type (s_con);
+ if ( slave_type
+ && strcmp (slave_type, NM_SETTING_TEAM_SETTING_NAME)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("A connection with a '%s' setting must have the slave-type set to '%s'. Instead it is '%s'"),
+ NM_SETTING_TEAM_PORT_SETTING_NAME,
+ NM_SETTING_TEAM_SETTING_NAME,
+ slave_type);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_SLAVE_TYPE);
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+static void
+nm_setting_team_port_init (NMSettingTeamPort *setting)
+{
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingTeamPortPrivate *priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_CONFIG:
+ priv->config = 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)
+{
+ NMSettingTeamPort *setting = NM_SETTING_TEAM_PORT (object);
+
+ switch (prop_id) {
+ case PROP_CONFIG:
+ g_value_set_string (value, nm_setting_team_port_get_config (setting));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_setting_team_port_class_init (NMSettingTeamPortClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+ NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+ g_type_class_add_private (setting_class, sizeof (NMSettingTeamPortPrivate));
+
+ /* virtual methods */
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+ parent_class->verify = verify;
+
+ /* Properties */
+ /**
+ * NMSettingTeamPort:config:
+ *
+ * The JSON configuration for the team port. The property should contain raw
+ * JSON configuration data suitable for teamd, because the value is passed
+ * directly to teamd. If not specified, the default configuration is
+ * used. See man teamd.conf for the format details.
+ **/
+ /* ---ifcfg-rh---
+ * property: config
+ * variable: TEAM_PORT_CONFIG
+ * description: Team port configuration in JSON. See man teamd.conf for details.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_CONFIG,
+ g_param_spec_string (NM_SETTING_TEAM_PORT_CONFIG, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+}
diff --git a/libnm-core/nm-setting-team-port.h b/libnm-core/nm-setting-team-port.h
new file mode 100644
index 000000000..86efb97c4
--- /dev/null
+++ b/libnm-core/nm-setting-team-port.h
@@ -0,0 +1,62 @@
+/* -*- 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 2013 Jiri Pirko <jiri@resnulli.us>
+ */
+
+#ifndef __NM_SETTING_TEAM_PORT_H__
+#define __NM_SETTING_TEAM_PORT_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_TEAM_PORT (nm_setting_team_port_get_type ())
+#define NM_SETTING_TEAM_PORT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_TEAM_PORT, NMSettingTeamPort))
+#define NM_SETTING_TEAM_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_TEAM_PORT, NMSettingTeamPortClass))
+#define NM_IS_SETTING_TEAM_PORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_TEAM_PORT))
+#define NM_IS_SETTING_TEAM_PORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_TEAM_PORT))
+#define NM_SETTING_TEAM_PORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_TEAM_PORT, NMSettingTeamPortClass))
+
+#define NM_SETTING_TEAM_PORT_SETTING_NAME "team-port"
+
+#define NM_SETTING_TEAM_PORT_CONFIG "config"
+
+struct _NMSettingTeamPort {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingTeamPortClass;
+
+GType nm_setting_team_port_get_type (void);
+
+NMSetting * nm_setting_team_port_new (void);
+
+const char * nm_setting_team_port_get_config (NMSettingTeamPort *setting);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_TEAM_PORT_H__ */
diff --git a/libnm-core/nm-setting-team.c b/libnm-core/nm-setting-team.c
new file mode 100644
index 000000000..04b98243f
--- /dev/null
+++ b/libnm-core/nm-setting-team.c
@@ -0,0 +1,186 @@
+/* -*- 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 2013 Jiri Pirko <jiri@resnulli.us>
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-team.h"
+#include "nm-utils.h"
+#include "nm-utils-private.h"
+#include "nm-connection-private.h"
+
+/**
+ * SECTION:nm-setting-team
+ * @short_description: Describes connection properties for teams
+ *
+ * The #NMSettingTeam object is a #NMSetting subclass that describes properties
+ * necessary for team connections.
+ **/
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingTeam, nm_setting_team, NM_TYPE_SETTING,
+ _nm_register_setting (TEAM, 1))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_TEAM)
+
+#define NM_SETTING_TEAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_TEAM, NMSettingTeamPrivate))
+
+typedef struct {
+ char *config;
+} NMSettingTeamPrivate;
+
+enum {
+ PROP_0,
+ PROP_CONFIG,
+ LAST_PROP
+};
+
+/**
+ * nm_setting_team_new:
+ *
+ * Creates a new #NMSettingTeam object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingTeam object
+ **/
+NMSetting *
+nm_setting_team_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_TEAM, NULL);
+}
+
+/**
+ * nm_setting_team_get_config:
+ * @setting: the #NMSettingTeam
+ *
+ * Returns: the #NMSettingTeam:config property of the setting
+ **/
+const char *
+nm_setting_team_get_config (NMSettingTeam *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_TEAM (setting), NULL);
+
+ return NM_SETTING_TEAM_GET_PRIVATE (setting)->config;
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ return _nm_connection_verify_required_interface_name (connection, error);
+}
+
+static void
+nm_setting_team_init (NMSettingTeam *setting)
+{
+}
+
+static void
+finalize (GObject *object)
+{
+ NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE (object);
+
+ g_free (priv->config);
+
+ G_OBJECT_CLASS (nm_setting_team_parent_class)->finalize (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingTeamPrivate *priv = NM_SETTING_TEAM_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_CONFIG:
+ g_free (priv->config);
+ priv->config = 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)
+{
+ NMSettingTeam *setting = NM_SETTING_TEAM (object);
+
+ switch (prop_id) {
+ case PROP_CONFIG:
+ g_value_set_string (value, nm_setting_team_get_config (setting));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_setting_team_class_init (NMSettingTeamClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+ NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+ g_type_class_add_private (setting_class, sizeof (NMSettingTeamPrivate));
+
+ /* virtual methods */
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+ object_class->finalize = finalize;
+ parent_class->verify = verify;
+
+ /* Properties */
+ /**
+ * NMSettingTeam:config:
+ *
+ * The JSON configuration for the team network interface. The property
+ * should contain raw JSON configuration data suitable for teamd, because
+ * the value is passed directly to teamd. If not specified, the default
+ * configuration is used. See man teamd.conf for the format details.
+ **/
+ /* ---ifcfg-rh---
+ * property: config
+ * variable: TEAM_CONFIG
+ * description: Team configuration in JSON. See man teamd.conf for details.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_CONFIG,
+ g_param_spec_string (NM_SETTING_TEAM_CONFIG, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /* ---dbus---
+ * property: interface-name
+ * format: string
+ * description: Deprecated in favor of connection.interface-name, but can
+ * be used for backward-compatibility with older daemons, to set the
+ * 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);
+}
diff --git a/libnm-core/nm-setting-team.h b/libnm-core/nm-setting-team.h
new file mode 100644
index 000000000..d66eb6858
--- /dev/null
+++ b/libnm-core/nm-setting-team.h
@@ -0,0 +1,62 @@
+/* -*- 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 2013 Jiri Pirko <jiri@resnulli.us>
+ */
+
+#ifndef __NM_SETTING_TEAM_H__
+#define __NM_SETTING_TEAM_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_TEAM (nm_setting_team_get_type ())
+#define NM_SETTING_TEAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_TEAM, NMSettingTeam))
+#define NM_SETTING_TEAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_TEAM, NMSettingTeamClass))
+#define NM_IS_SETTING_TEAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_TEAM))
+#define NM_IS_SETTING_TEAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_TEAM))
+#define NM_SETTING_TEAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_TEAM, NMSettingTeamClass))
+
+#define NM_SETTING_TEAM_SETTING_NAME "team"
+
+#define NM_SETTING_TEAM_CONFIG "config"
+
+struct _NMSettingTeam {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingTeamClass;
+
+GType nm_setting_team_get_type (void);
+
+NMSetting * nm_setting_team_new (void);
+
+const char * nm_setting_team_get_config (NMSettingTeam *setting);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_TEAM_H__ */
diff --git a/libnm-core/nm-setting-vlan.c b/libnm-core/nm-setting-vlan.c
new file mode 100644
index 000000000..f622ddcbf
--- /dev/null
+++ b/libnm-core/nm-setting-vlan.c
@@ -0,0 +1,822 @@
+/* -*- 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 2011 - 2014 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-vlan.h"
+#include "nm-utils.h"
+#include "nm-setting-connection.h"
+#include "nm-setting-private.h"
+#include "nm-setting-wired.h"
+#include "nm-connection-private.h"
+
+/**
+ * SECTION:nm-setting-vlan
+ * @short_description: Describes connection properties for VLAN interfaces
+ *
+ * The #NMSettingVlan object is a #NMSetting subclass that describes properties
+ * necessary for connection to VLAN interfaces.
+ **/
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingVlan, nm_setting_vlan, NM_TYPE_SETTING,
+ _nm_register_setting (VLAN, 1))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_VLAN)
+
+#define NM_SETTING_VLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_VLAN, NMSettingVlanPrivate))
+
+typedef struct {
+ char *parent;
+ guint32 id;
+ guint32 flags;
+ GSList *ingress_priority_map;
+ GSList *egress_priority_map;
+} NMSettingVlanPrivate;
+
+enum {
+ PROP_0,
+ PROP_PARENT,
+ PROP_ID,
+ PROP_FLAGS,
+ PROP_INGRESS_PRIORITY_MAP,
+ PROP_EGRESS_PRIORITY_MAP,
+ LAST_PROP
+};
+
+#define MAX_SKB_PRIO G_MAXUINT32
+#define MAX_8021P_PRIO 7 /* Max 802.1p priority */
+
+typedef struct {
+ guint32 from;
+ guint32 to;
+} PriorityMap;
+
+/**
+ * nm_setting_vlan_new:
+ *
+ * Creates a new #NMSettingVlan object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingVlan object
+ **/
+NMSetting *
+nm_setting_vlan_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_VLAN, NULL);
+}
+
+/**
+ * nm_setting_vlan_get_parent:
+ * @setting: the #NMSettingVlan
+ *
+ * Returns: the #NMSettingVlan:parent property of the setting
+ **/
+const char *
+nm_setting_vlan_get_parent (NMSettingVlan *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), NULL);
+ return NM_SETTING_VLAN_GET_PRIVATE (setting)->parent;
+}
+
+/**
+ * nm_setting_vlan_get_id:
+ * @setting: the #NMSettingVlan
+ *
+ * Returns: the #NMSettingVlan:id property of the setting
+ **/
+guint32
+nm_setting_vlan_get_id (NMSettingVlan *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), 0);
+ return NM_SETTING_VLAN_GET_PRIVATE (setting)->id;
+}
+
+/**
+ * nm_setting_vlan_get_flags:
+ * @setting: the #NMSettingVlan
+ *
+ * Returns: the #NMSettingVlan:flags property of the setting
+ **/
+guint32
+nm_setting_vlan_get_flags (NMSettingVlan *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), 0);
+ return NM_SETTING_VLAN_GET_PRIVATE (setting)->flags;
+}
+
+static guint32
+get_max_prio (NMVlanPriorityMap map, gboolean from)
+{
+ if (map == NM_VLAN_INGRESS_MAP)
+ return from ? MAX_8021P_PRIO : MAX_SKB_PRIO;
+ else if (map == NM_VLAN_EGRESS_MAP)
+ return from ? MAX_SKB_PRIO : MAX_8021P_PRIO;
+ g_assert_not_reached ();
+}
+
+static PriorityMap *
+priority_map_new_from_str (NMVlanPriorityMap map, const char *str)
+{
+ PriorityMap *p = NULL;
+ gchar **t = NULL;
+ guint32 len;
+ guint64 from, to;
+
+ g_return_val_if_fail (str && str[0], NULL);
+
+ t = g_strsplit (str, ":", 0);
+ len = g_strv_length (t);
+ if (len == 2) {
+ from = g_ascii_strtoull (t[0], NULL, 10);
+ to = g_ascii_strtoull (t[1], NULL, 10);
+
+ if ((from <= get_max_prio (map, TRUE)) && (to <= get_max_prio (map, FALSE))) {
+ p = g_malloc0 (sizeof (PriorityMap));
+ p->from = from;
+ p->to = to;
+ }
+ } else {
+ /* Warn */
+ g_warn_if_fail (len == 2);
+ }
+
+ g_strfreev (t);
+ return p;
+}
+
+static void
+priority_map_free (PriorityMap *map)
+{
+ g_return_if_fail (map != NULL);
+ g_free (map);
+}
+
+static GSList *
+get_map (NMSettingVlan *self, NMVlanPriorityMap map)
+{
+ if (map == NM_VLAN_INGRESS_MAP)
+ return NM_SETTING_VLAN_GET_PRIVATE (self)->ingress_priority_map;
+ else if (map == NM_VLAN_EGRESS_MAP)
+ return NM_SETTING_VLAN_GET_PRIVATE (self)->egress_priority_map;
+ g_assert_not_reached ();
+ return NULL;
+}
+
+static void
+set_map (NMSettingVlan *self, NMVlanPriorityMap map, GSList *list)
+{
+ if (map == NM_VLAN_INGRESS_MAP) {
+ NM_SETTING_VLAN_GET_PRIVATE (self)->ingress_priority_map = list;
+ g_object_notify (G_OBJECT (self), NM_SETTING_VLAN_INGRESS_PRIORITY_MAP);
+ } else if (map == NM_VLAN_EGRESS_MAP) {
+ NM_SETTING_VLAN_GET_PRIVATE (self)->egress_priority_map = list;
+ g_object_notify (G_OBJECT (self), NM_SETTING_VLAN_EGRESS_PRIORITY_MAP);
+ } else
+ g_assert_not_reached ();
+}
+
+/**
+ * nm_setting_vlan_add_priority_str:
+ * @setting: the #NMSettingVlan
+ * @map: the type of priority map
+ * @str: the string which contains a priority map, like "3:7"
+ *
+ * Adds a priority map entry into either the #NMSettingVlan:ingress_priority_map
+ * or the #NMSettingVlan:egress_priority_map properties. The priority map maps
+ * the Linux SKB priorities to 802.1p priorities.
+ *
+ * Returns: %TRUE if the entry was successfully added to the list, or it
+ * overwrote the old value, %FALSE if error
+ */
+gboolean
+nm_setting_vlan_add_priority_str (NMSettingVlan *setting,
+ NMVlanPriorityMap map,
+ const char *str)
+{
+ GSList *list = NULL, *iter = NULL;
+ PriorityMap *item = NULL;
+
+ g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), FALSE);
+ g_return_val_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE);
+ g_return_val_if_fail (str && str[0], FALSE);
+
+ list = get_map (setting, map);
+
+ item = priority_map_new_from_str (map, str);
+ if (!item)
+ g_return_val_if_reached (FALSE);
+
+ /* Duplicates get replaced */
+ for (iter = list; iter; iter = g_slist_next (iter)) {
+ PriorityMap *p = iter->data;
+
+ if (p->from == item->from) {
+ p->to = item->to;
+ g_free (item);
+ if (map == NM_VLAN_INGRESS_MAP)
+ g_object_notify (G_OBJECT (setting), NM_SETTING_VLAN_INGRESS_PRIORITY_MAP);
+ else
+ g_object_notify (G_OBJECT (setting), NM_SETTING_VLAN_EGRESS_PRIORITY_MAP);
+ return TRUE;
+ }
+ }
+
+ set_map (setting, map, g_slist_append (list, item));
+ return TRUE;
+}
+
+/**
+ * nm_setting_vlan_get_num_priorities:
+ * @setting: the #NMSettingVlan
+ * @map: the type of priority map
+ *
+ * Returns the number of entires in the
+ * #NMSettingVlan:ingress_priority_map or #NMSettingVlan:egress_priority_map
+ * properties of this setting.
+ *
+ * Returns: return the number of ingress/egress priority entries, -1 if error
+ **/
+gint32
+nm_setting_vlan_get_num_priorities (NMSettingVlan *setting, NMVlanPriorityMap map)
+{
+ g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), -1);
+ g_return_val_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, -1);
+
+ return g_slist_length (get_map (setting, map));
+}
+
+/**
+ * nm_setting_vlan_get_priority:
+ * @setting: the #NMSettingVlan
+ * @map: the type of priority map
+ * @idx: the zero-based index of the ingress/egress priority map entry
+ * @out_from: (out): on return the value of the priority map's 'from' item
+ * @out_to: (out): on return the value of priority map's 'to' item
+ *
+ * Retrieve one of the entries of the #NMSettingVlan:ingress_priority_map
+ * or #NMSettingVlan:egress_priority_map properties of this setting.
+ *
+ * Returns: %TRUE if a priority map was returned, %FALSE if error
+ **/
+gboolean
+nm_setting_vlan_get_priority (NMSettingVlan *setting,
+ NMVlanPriorityMap map,
+ guint32 idx,
+ guint32 *out_from,
+ guint32 *out_to)
+{
+ GSList *list = NULL;
+ PriorityMap *item = NULL;
+
+ g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), FALSE);
+ g_return_val_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE);
+ g_return_val_if_fail (out_from != NULL, FALSE);
+ g_return_val_if_fail (out_to != NULL, FALSE);
+
+ list = get_map (setting, map);
+ g_return_val_if_fail (idx < g_slist_length (list), FALSE);
+
+ item = g_slist_nth_data (list, idx);
+ g_assert (item);
+ *out_from = item->from;
+ *out_to = item->to;
+ return TRUE;
+}
+
+/**
+ * nm_setting_vlan_add_priority:
+ * @setting: the #NMSettingVlan
+ * @map: the type of priority map
+ * @from: the priority to map to @to
+ * @to: the priority to map @from to
+ *
+ * Adds a priority mapping to the #NMSettingVlan:ingress_priority_map or
+ * #NMSettingVlan:egress_priority_map properties of the setting. If @from is
+ * already in the given priority map, this function will overwrite the
+ * existing entry with the new @to.
+ *
+ * If @map is #NM_VLAN_INGRESS_MAP then @from is the incoming 802.1q VLAN
+ * Priority Code Point (PCP) value, and @to is the Linux SKB priority value.
+ *
+ * If @map is #NM_VLAN_EGRESS_MAP then @from is the Linux SKB priority value and
+ * @to is the outgoing 802.1q VLAN Priority Code Point (PCP) value.
+ *
+ * Returns: %TRUE if the new priority mapping was successfully added to the
+ * list, %FALSE if error
+ */
+gboolean
+nm_setting_vlan_add_priority (NMSettingVlan *setting,
+ NMVlanPriorityMap map,
+ guint32 from,
+ guint32 to)
+{
+ GSList *list = NULL, *iter = NULL;
+ PriorityMap *item;
+
+ g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), FALSE);
+ g_return_val_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE);
+
+ list = get_map (setting, map);
+ for (iter = list; iter; iter = g_slist_next (iter)) {
+ item = iter->data;
+ if (item->from == from) {
+ item->to = to;
+ if (map == NM_VLAN_INGRESS_MAP)
+ g_object_notify (G_OBJECT (setting), NM_SETTING_VLAN_INGRESS_PRIORITY_MAP);
+ else
+ g_object_notify (G_OBJECT (setting), NM_SETTING_VLAN_EGRESS_PRIORITY_MAP);
+ return TRUE;
+ }
+ }
+
+ item = g_malloc0 (sizeof (PriorityMap));
+ item->from = from;
+ item->to = to;
+ set_map (setting, map, g_slist_append (list, item));
+
+ return TRUE;
+}
+
+/**
+ * nm_setting_vlan_remove_priority:
+ * @setting: the #NMSettingVlan
+ * @map: the type of priority map
+ * @idx: the zero-based index of the priority map to remove
+ *
+ * Removes the priority map at index @idx from the
+ * #NMSettingVlan:ingress_priority_map or #NMSettingVlan:egress_priority_map
+ * properties.
+ */
+void
+nm_setting_vlan_remove_priority (NMSettingVlan *setting,
+ NMVlanPriorityMap map,
+ guint32 idx)
+{
+ GSList *list = NULL, *item = NULL;
+
+ g_return_if_fail (NM_IS_SETTING_VLAN (setting));
+ g_return_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP);
+
+ list = get_map (setting, map);
+ g_return_if_fail (idx < g_slist_length (list));
+
+ item = g_slist_nth (list, idx);
+ priority_map_free ((PriorityMap *) (item->data));
+ set_map (setting, map, g_slist_delete_link (list, item));
+}
+
+/**
+ * nm_setting_vlan_remove_priority_by_value:
+ * @setting: the #NMSettingVlan
+ * @map: the type of priority map
+ * @from: the priority to map to @to
+ * @to: the priority to map @from to
+ *
+ * Removes the priority map @form:@to from the #NMSettingVlan:ingress_priority_map
+ * or #NMSettingVlan:egress_priority_map (according to @map argument)
+ * properties.
+ *
+ * Returns: %TRUE if the priority mapping was found and removed; %FALSE if it was not.
+ */
+gboolean
+nm_setting_vlan_remove_priority_by_value (NMSettingVlan *setting,
+ NMVlanPriorityMap map,
+ guint32 from,
+ guint32 to)
+{
+ GSList *list = NULL, *iter = NULL;
+ PriorityMap *item;
+
+ g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), FALSE);
+ g_return_val_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE);
+
+ list = get_map (setting, map);
+ for (iter = list; iter; iter = g_slist_next (iter)) {
+ item = iter->data;
+ if (item->from == from && item->to == to) {
+ priority_map_free ((PriorityMap *) (iter->data));
+ set_map (setting, map, g_slist_delete_link (list, iter));
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * nm_setting_vlan_remove_priority_str_by_value:
+ * @setting: the #NMSettingVlan
+ * @map: the type of priority map
+ * @str: the string which contains a priority map, like "3:7"
+ *
+ * Removes the priority map @str from the #NMSettingVlan:ingress_priority_map
+ * or #NMSettingVlan:egress_priority_map (according to @map argument)
+ * properties.
+ *
+ * Returns: %TRUE if the priority mapping was found and removed; %FALSE if it was not.
+ */
+gboolean
+nm_setting_vlan_remove_priority_str_by_value (NMSettingVlan *setting,
+ NMVlanPriorityMap map,
+ const char *str)
+{
+ PriorityMap *item;
+ gboolean found;
+
+ g_return_val_if_fail (NM_IS_SETTING_VLAN (setting), FALSE);
+ g_return_val_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP, FALSE);
+
+ item = priority_map_new_from_str (map, str);
+ if (!item)
+ return FALSE;
+
+ found = nm_setting_vlan_remove_priority_by_value (setting, map, item->from, item->to);
+ g_free (item);
+ return found;
+}
+
+/**
+ * nm_setting_vlan_clear_priorities:
+ * @setting: the #NMSettingVlan
+ * @map: the type of priority map
+ *
+ * Clear all the entires from #NMSettingVlan:ingress_priority_map or
+ * #NMSettingVlan:egress_priority_map properties.
+ */
+void
+nm_setting_vlan_clear_priorities (NMSettingVlan *setting, NMVlanPriorityMap map)
+{
+ GSList *list = NULL;
+
+ g_return_if_fail (NM_IS_SETTING_VLAN (setting));
+ g_return_if_fail (map == NM_VLAN_INGRESS_MAP || map == NM_VLAN_EGRESS_MAP);
+
+ list = get_map (setting, map);
+ g_slist_free_full (list, g_free);
+ set_map (setting, map, NULL);
+}
+
+/*********************************************************************/
+
+static void
+nm_setting_vlan_init (NMSettingVlan *setting)
+{
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ NMSettingVlanPrivate *priv = NM_SETTING_VLAN_GET_PRIVATE (setting);
+ NMSettingConnection *s_con;
+ NMSettingWired *s_wired;
+
+ if (connection) {
+ s_con = nm_connection_get_setting_connection (connection);
+ s_wired = nm_connection_get_setting_wired (connection);
+ } else {
+ s_con = NULL;
+ s_wired = NULL;
+ }
+
+ if (priv->parent) {
+ if (nm_utils_is_uuid (priv->parent)) {
+ /* If we have an NMSettingConnection:master with slave-type="vlan",
+ * 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_VLAN_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_VLAN_SETTING_NAME, NM_SETTING_VLAN_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_VLAN_SETTING_NAME, NM_SETTING_VLAN_PARENT);
+ return FALSE;
+ }
+ } else {
+ /* If parent is NULL, the parent must be specified via
+ * NMSettingWired:mac-address.
+ */
+ if ( connection
+ && (!s_wired || !nm_setting_wired_get_mac_address (s_wired))) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is not specified and neither is '%s:%s'"),
+ NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_MAC_ADDRESS);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_VLAN_SETTING_NAME, NM_SETTING_VLAN_PARENT);
+ return FALSE;
+ }
+ }
+
+ if (priv->flags & ~(NM_VLAN_FLAG_REORDER_HEADERS |
+ NM_VLAN_FLAG_GVRP |
+ NM_VLAN_FLAG_LOOSE_BINDING)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("flags are invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_VLAN_SETTING_NAME, NM_SETTING_VLAN_FLAGS);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static GSList *
+priority_strv_to_maplist (NMVlanPriorityMap map, char **strv)
+{
+ GSList *list = NULL;
+ int i;
+
+ for (i = 0; strv[i]; i++) {
+ PriorityMap *item;
+
+ item = priority_map_new_from_str (map, strv[i]);
+ if (item)
+ list = g_slist_prepend (list, item);
+ }
+ return g_slist_reverse (list);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingVlan *setting = NM_SETTING_VLAN (object);
+ NMSettingVlanPrivate *priv = NM_SETTING_VLAN_GET_PRIVATE (setting);
+
+ switch (prop_id) {
+ case PROP_PARENT:
+ g_free (priv->parent);
+ priv->parent = g_value_dup_string (value);
+ break;
+ case PROP_ID:
+ priv->id = g_value_get_uint (value);
+ break;
+ case PROP_FLAGS:
+ priv->flags = g_value_get_flags (value);
+ break;
+ case PROP_INGRESS_PRIORITY_MAP:
+ g_slist_free_full (priv->ingress_priority_map, g_free);
+ priv->ingress_priority_map =
+ priority_strv_to_maplist (NM_VLAN_INGRESS_MAP, g_value_get_boxed (value));
+ break;
+ case PROP_EGRESS_PRIORITY_MAP:
+ g_slist_free_full (priv->egress_priority_map, g_free);
+ priv->egress_priority_map =
+ priority_strv_to_maplist (NM_VLAN_EGRESS_MAP, g_value_get_boxed (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static char **
+priority_maplist_to_strv (GSList *list)
+{
+ GSList *iter;
+ GPtrArray *strv;
+
+ strv = g_ptr_array_new ();
+
+ for (iter = list; iter; iter = g_slist_next (iter)) {
+ PriorityMap *item = iter->data;
+
+ g_ptr_array_add (strv, g_strdup_printf ("%d:%d", item->from, item->to));
+ }
+ g_ptr_array_add (strv, NULL);
+
+ return (char **) g_ptr_array_free (strv, FALSE);
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ NMSettingVlan *setting = NM_SETTING_VLAN (object);
+ NMSettingVlanPrivate *priv = NM_SETTING_VLAN_GET_PRIVATE (setting);
+
+ switch (prop_id) {
+ case PROP_PARENT:
+ g_value_set_string (value, priv->parent);
+ break;
+ case PROP_ID:
+ g_value_set_uint (value, priv->id);
+ break;
+ case PROP_FLAGS:
+ g_value_set_flags (value, priv->flags);
+ break;
+ case PROP_INGRESS_PRIORITY_MAP:
+ g_value_take_boxed (value, priority_maplist_to_strv (priv->ingress_priority_map));
+ break;
+ case PROP_EGRESS_PRIORITY_MAP:
+ g_value_take_boxed (value, priority_maplist_to_strv (priv->egress_priority_map));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+finalize (GObject *object)
+{
+ NMSettingVlan *setting = NM_SETTING_VLAN (object);
+ NMSettingVlanPrivate *priv = NM_SETTING_VLAN_GET_PRIVATE (setting);
+
+ g_free (priv->parent);
+ g_slist_free_full (priv->ingress_priority_map, g_free);
+ g_slist_free_full (priv->egress_priority_map, g_free);
+
+ G_OBJECT_CLASS (nm_setting_vlan_parent_class)->finalize (object);
+}
+
+static void
+nm_setting_vlan_class_init (NMSettingVlanClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+ NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+ g_type_class_add_private (setting_class, 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 */
+
+ /**
+ * NMSettingVlan:parent:
+ *
+ * If given, specifies the parent interface name or parent connection UUID
+ * from which this VLAN interface should be created. If this property is
+ * not specified, the connection must contain an #NMSettingWired setting
+ * with a #NMSettingWired:mac-address property.
+ **/
+ /* ---ifcfg-rh---
+ * property: parent
+ * variable: DEVICE or PHYSDEV
+ * description: Parent interface of the VLAN.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_PARENT,
+ g_param_spec_string (NM_SETTING_VLAN_PARENT, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingVlan:id:
+ *
+ * The VLAN identifier that the interface created by this connection should
+ * be assigned.
+ **/
+ /* ---ifcfg-rh---
+ * property: id
+ * variable: VLAN_ID or DEVICE
+ * description: VLAN identifier.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_ID,
+ g_param_spec_uint (NM_SETTING_VLAN_ID, "", "",
+ 0, 4095, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingVlan:flags:
+ *
+ * One or more flags which control the behavior and features of the VLAN
+ * interface. Flags include %NM_VLAN_FLAG_REORDER_HEADERS (reordering of
+ * output packet headers), %NM_VLAN_FLAG_GVRP (use of the GVRP protocol),
+ * and %NM_VLAN_FLAG_LOOSE_BINDING (loose binding of the interface to its
+ * master device's operating state).
+ **/
+ /* ---ifcfg-rh---
+ * property: flags
+ * variable: VLAN_FLAGS, REORDER_HDR
+ * values: "GVRP", "LOOSE_BINDING" for VLAN_FLAGS; 0 or 1 for REORDER_HDR
+ * description: Parent interface of the VLAN.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_FLAGS,
+ g_param_spec_flags (NM_SETTING_VLAN_FLAGS, "", "",
+ NM_TYPE_VLAN_FLAGS,
+ 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingVlan:ingress-priority-map:
+ *
+ * For incoming packets, a list of mappings from 802.1p priorities to Linux
+ * SKB priorities. The mapping is given in the format "from:to" where both
+ * "from" and "to" are unsigned integers, ie "7:3".
+ **/
+ /* ---ifcfg-rh---
+ * property: ingress-property-map
+ * variable: VLAN_INGRESS_PRIORITY_MAP
+ * description: Ingress priority mapping.
+ * example: VLAN_INGRESS_PRIORITY_MAP=4:2,3:5
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_INGRESS_PRIORITY_MAP,
+ g_param_spec_boxed (NM_SETTING_VLAN_INGRESS_PRIORITY_MAP, "", "",
+ G_TYPE_STRV,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingVlan:egress-priority-map:
+ *
+ * For outgoing packets, a list of mappings from Linux SKB priorities to
+ * 802.1p priorities. The mapping is given in the format "from:to" where
+ * both "from" and "to" are unsigned integers, ie "7:3".
+ **/
+ /* ---ifcfg-rh---
+ * property: egress-property-map
+ * variable: VLAN_EGRESS_PRIORITY_MAP
+ * description: Egress priority mapping.
+ * example: VLAN_EGRESS_PRIORITY_MAP=5:4,4:1,3:7
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_EGRESS_PRIORITY_MAP,
+ g_param_spec_boxed (NM_SETTING_VLAN_EGRESS_PRIORITY_MAP, "", "",
+ G_TYPE_STRV,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /* ---ifcfg-rh---
+ * property: interface-name
+ * variable: PHYSDEV and VLAN_ID, or DEVICE
+ * description: VLAN interface name.
+ * If all variables are set, parent device from PHYSDEV takes precedence over DEVICE,
+ * but VLAN id from DEVICE takes precedence over VLAN_ID.
+ * example: PHYSDEV=eth0, VLAN_ID=12; or DEVICE=eth0.12
+ * ---end---
+ * ---dbus---
+ * property: interface-name
+ * format: string
+ * description: Deprecated in favor of connection.interface-name, but can
+ * be used for backward-compatibility with older daemons, to set the
+ * 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);
+}
diff --git a/libnm-core/nm-setting-vlan.h b/libnm-core/nm-setting-vlan.h
new file mode 100644
index 000000000..30305d327
--- /dev/null
+++ b/libnm-core/nm-setting-vlan.h
@@ -0,0 +1,134 @@
+/* -*- 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 2011 - 2014 Red Hat, Inc.
+ */
+
+#ifndef __NM_SETTING_VLAN_H__
+#define __NM_SETTING_VLAN_H__
+
+#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
+#error "Only <NetworkManager.h> can be included directly."
+#endif
+
+#include "nm-setting.h"
+#include <linux/if_vlan.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_SETTING_VLAN (nm_setting_vlan_get_type ())
+#define NM_SETTING_VLAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_VLAN, NMSettingVlan))
+#define NM_SETTING_VLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_VLANCONFIG, NMSettingVlanClass))
+#define NM_IS_SETTING_VLAN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_VLAN))
+#define NM_IS_SETTING_VLAN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_VLAN))
+#define NM_SETTING_VLAN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_VLAN, NMSettingVlanClass))
+
+#define NM_SETTING_VLAN_SETTING_NAME "vlan"
+
+#define NM_SETTING_VLAN_PARENT "parent"
+#define NM_SETTING_VLAN_ID "id"
+#define NM_SETTING_VLAN_FLAGS "flags"
+#define NM_SETTING_VLAN_INGRESS_PRIORITY_MAP "ingress-priority-map"
+#define NM_SETTING_VLAN_EGRESS_PRIORITY_MAP "egress-priority-map"
+
+struct _NMSettingVlan {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingVlanClass;
+
+/**
+ * NMVlanPriorityMap:
+ * @NM_VLAN_INGRESS_MAP: map for incoming data
+ * @NM_VLAN_EGRESS_MAP: map for outgoing data
+ *
+ * A selector for traffic priority maps; these map Linux SKB priorities
+ * to 802.1p priorities used in VLANs.
+ **/
+typedef enum {
+ NM_VLAN_INGRESS_MAP,
+ NM_VLAN_EGRESS_MAP
+} NMVlanPriorityMap;
+
+/**
+ * NMVlanFlags:
+ * @NM_VLAN_FLAG_REORDER_HEADERS: indicates that this interface should reorder
+ * outgoing packet headers to look more like a non-VLAN Ethernet interface
+ * @NM_VLAN_FLAG_GVRP: indicates that this interface should use GVRP to register
+ * itself with it's switch
+ * @NM_VLAN_FLAG_LOOSE_BINDING: indicates that this interface's operating
+ * state is tied to the underlying network interface but other details
+ * (like routing) are not.
+ *
+ * #NMVlanFlags values control the behavior of the VLAN interface.
+ **/
+typedef enum { /*< flags >*/
+ NM_VLAN_FLAG_REORDER_HEADERS = 0x1,
+ NM_VLAN_FLAG_GVRP = 0x2,
+ NM_VLAN_FLAG_LOOSE_BINDING = 0x4,
+
+ /* NOTE: if adding flags update nm-setting-vlan.c::verify() */
+} NMVlanFlags;
+
+GType nm_setting_vlan_get_type (void);
+NMSetting *nm_setting_vlan_new (void);
+
+const char *nm_setting_vlan_get_parent (NMSettingVlan *setting);
+guint32 nm_setting_vlan_get_id (NMSettingVlan *setting);
+guint32 nm_setting_vlan_get_flags (NMSettingVlan *setting);
+
+gint32 nm_setting_vlan_get_num_priorities (NMSettingVlan *setting, NMVlanPriorityMap map);
+
+gboolean nm_setting_vlan_get_priority (NMSettingVlan *setting,
+ NMVlanPriorityMap map,
+ guint32 idx,
+ guint32 *out_from,
+ guint32 *out_to);
+
+gboolean nm_setting_vlan_add_priority (NMSettingVlan *setting,
+ NMVlanPriorityMap map,
+ guint32 from,
+ guint32 to);
+
+void nm_setting_vlan_remove_priority (NMSettingVlan *setting,
+ NMVlanPriorityMap map,
+ guint32 idx);
+
+gboolean nm_setting_vlan_remove_priority_by_value (NMSettingVlan *setting,
+ NMVlanPriorityMap map,
+ guint32 from,
+ guint32 to);
+
+gboolean nm_setting_vlan_remove_priority_str_by_value (NMSettingVlan *setting,
+ NMVlanPriorityMap map,
+ const char *str);
+
+void nm_setting_vlan_clear_priorities (NMSettingVlan *setting, NMVlanPriorityMap map);
+
+gboolean nm_setting_vlan_add_priority_str (NMSettingVlan *setting,
+ NMVlanPriorityMap map,
+ const char *str);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_VLAN_H__ */
diff --git a/libnm-core/nm-setting-vpn.c b/libnm-core/nm-setting-vpn.c
new file mode 100644
index 000000000..e6fffa879
--- /dev/null
+++ b/libnm-core/nm-setting-vpn.c
@@ -0,0 +1,913 @@
+/* -*- 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 2007 - 2013 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-vpn.h"
+#include "nm-utils.h"
+#include "nm-utils-private.h"
+#include "nm-setting-private.h"
+
+/**
+ * SECTION:nm-setting-vpn
+ * @short_description: Describes connection properties for Virtual Private Networks
+ *
+ * The #NMSettingVpn object is a #NMSetting subclass that describes properties
+ * necessary for connection to Virtual Private Networks. NetworkManager uses
+ * a plugin architecture to allow easier use of new VPN types, and this
+ * setting abstracts the configuration for those plugins. Since the configuration
+ * options are only known to the VPN plugins themselves, the VPN configuration
+ * options are stored as key/value pairs of strings rather than GObject
+ * properties.
+ **/
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingVpn, nm_setting_vpn, NM_TYPE_SETTING,
+ _nm_register_setting (VPN, 1))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_VPN)
+
+#define NM_SETTING_VPN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_VPN, NMSettingVpnPrivate))
+
+typedef struct {
+ char *service_type;
+
+ /* username of the user requesting this connection, thus
+ * it's really only valid for user connections, and it also
+ * should never be saved out to persistent config.
+ */
+ char *user_name;
+
+ /* Whether the VPN stays up across link changes, until the user
+ * explicitly disconnects it.
+ */
+ gboolean persistent;
+
+ /* The hash table is created at setting object
+ * init time and should not be replaced. It is
+ * a char * -> char * mapping, and both the key
+ * and value are owned by the hash table, and should
+ * be allocated with functions whose value can be
+ * freed with g_free(). Should not contain secrets.
+ */
+ GHashTable *data;
+
+ /* The hash table is created at setting object
+ * init time and should not be replaced. It is
+ * a char * -> char * mapping, and both the key
+ * and value are owned by the hash table, and should
+ * be allocated with functions whose value can be
+ * freed with g_free(). Should contain secrets only.
+ */
+ GHashTable *secrets;
+} NMSettingVpnPrivate;
+
+enum {
+ PROP_0,
+ PROP_SERVICE_TYPE,
+ PROP_USER_NAME,
+ PROP_PERSISTENT,
+ PROP_DATA,
+ PROP_SECRETS,
+
+ LAST_PROP
+};
+
+/**
+ * nm_setting_vpn_new:
+ *
+ * Creates a new #NMSettingVpn object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingVpn object
+ **/
+NMSetting *
+nm_setting_vpn_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_VPN, NULL);
+}
+
+/**
+ * nm_setting_vpn_get_service_type:
+ * @setting: the #NMSettingVpn
+ *
+ * Returns the service name of the VPN, which identifies the specific VPN
+ * plugin that should be used to connect to this VPN.
+ *
+ * Returns: the VPN plugin's service name
+ **/
+const char *
+nm_setting_vpn_get_service_type (NMSettingVpn *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_VPN (setting), NULL);
+
+ return NM_SETTING_VPN_GET_PRIVATE (setting)->service_type;
+}
+
+/**
+ * nm_setting_vpn_get_user_name:
+ * @setting: the #NMSettingVpn
+ *
+ * Returns: the #NMSettingVpn:user-name property of the setting
+ **/
+const char *
+nm_setting_vpn_get_user_name (NMSettingVpn *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_VPN (setting), NULL);
+
+ return NM_SETTING_VPN_GET_PRIVATE (setting)->user_name;
+}
+
+/**
+ * nm_setting_vpn_get_persistent:
+ * @setting: the #NMSettingVpn
+ *
+ * Returns: the #NMSettingVpn:persistent property of the setting
+ **/
+gboolean
+nm_setting_vpn_get_persistent (NMSettingVpn *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_VPN (setting), FALSE);
+
+ return NM_SETTING_VPN_GET_PRIVATE (setting)->persistent;
+}
+
+/**
+ * nm_setting_vpn_get_num_data_items:
+ * @setting: the #NMSettingVpn
+ *
+ * Gets number of key/value pairs of VPN configuration data.
+ *
+ * Returns: the number of VPN plugin specific configuration data items
+ **/
+guint32
+nm_setting_vpn_get_num_data_items (NMSettingVpn *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_VPN (setting), 0);
+
+ return g_hash_table_size (NM_SETTING_VPN_GET_PRIVATE (setting)->data);
+}
+
+/**
+ * nm_setting_vpn_add_data_item:
+ * @setting: the #NMSettingVpn
+ * @key: a name that uniquely identifies the given value @item
+ * @item: the value to be referenced by @key
+ *
+ * Establishes a relationship between @key and @item internally in the
+ * setting which may be retrieved later. Should not be used to store passwords
+ * or other secrets, which is what nm_setting_vpn_add_secret() is for.
+ **/
+void
+nm_setting_vpn_add_data_item (NMSettingVpn *setting,
+ const char *key,
+ const char *item)
+{
+ g_return_if_fail (NM_IS_SETTING_VPN (setting));
+ g_return_if_fail (key != NULL);
+ g_return_if_fail (strlen (key) > 0);
+ g_return_if_fail (item != NULL);
+ g_return_if_fail (strlen (item) > 0);
+
+ g_hash_table_insert (NM_SETTING_VPN_GET_PRIVATE (setting)->data,
+ g_strdup (key), g_strdup (item));
+ g_object_notify (G_OBJECT (setting), NM_SETTING_VPN_DATA);
+}
+
+/**
+ * nm_setting_vpn_get_data_item:
+ * @setting: the #NMSettingVpn
+ * @key: the name of the data item to retrieve
+ *
+ * Retrieves the data item of a key/value relationship previously established
+ * by nm_setting_vpn_add_data_item().
+ *
+ * Returns: the data item, if any
+ **/
+const char *
+nm_setting_vpn_get_data_item (NMSettingVpn *setting, const char *key)
+{
+ g_return_val_if_fail (NM_IS_SETTING_VPN (setting), NULL);
+
+ return (const char *) g_hash_table_lookup (NM_SETTING_VPN_GET_PRIVATE (setting)->data, key);
+}
+
+/**
+ * nm_setting_vpn_remove_data_item:
+ * @setting: the #NMSettingVpn
+ * @key: the name of the data item to remove
+ *
+ * Deletes a key/value relationship previously established by
+ * nm_setting_vpn_add_data_item().
+ *
+ * Returns: %TRUE if the data item was found and removed from the internal list,
+ * %FALSE if it was not.
+ **/
+gboolean
+nm_setting_vpn_remove_data_item (NMSettingVpn *setting, const char *key)
+{
+ gboolean found;
+
+ g_return_val_if_fail (NM_IS_SETTING_VPN (setting), FALSE);
+
+ found = g_hash_table_remove (NM_SETTING_VPN_GET_PRIVATE (setting)->data, key);
+ if (found)
+ g_object_notify (G_OBJECT (setting), NM_SETTING_VPN_DATA);
+ return found;
+}
+
+static void
+foreach_item_helper (GHashTable *hash,
+ NMVpnIterFunc func,
+ gpointer user_data)
+{
+ GList *keys, *liter;
+ GSList *copied = NULL, *siter;
+
+ g_return_if_fail (hash != NULL);
+
+ /* Grab keys and copy them so that the callback func can modify
+ * the hash table items if it wants to.
+ */
+ keys = g_hash_table_get_keys (hash);
+ for (liter = keys; liter; liter = g_list_next (liter))
+ copied = g_slist_prepend (copied, g_strdup (liter->data));
+ copied = g_slist_reverse (copied);
+ g_list_free (keys);
+
+ for (siter = copied; siter; siter = g_slist_next (siter)) {
+ gpointer value;
+
+ value = g_hash_table_lookup (hash, siter->data);
+ func (siter->data, value, user_data);
+ }
+
+ g_slist_free_full (copied, g_free);
+}
+
+/**
+ * nm_setting_vpn_foreach_data_item:
+ * @setting: a #NMSettingVpn
+ * @func: (scope call): an user provided function
+ * @user_data: data to be passed to @func
+ *
+ * Iterates all data items stored in this setting. It is safe to add, remove,
+ * and modify data items inside @func, though any additions or removals made
+ * during iteration will not be part of the iteration.
+ */
+void
+nm_setting_vpn_foreach_data_item (NMSettingVpn *setting,
+ NMVpnIterFunc func,
+ gpointer user_data)
+{
+ g_return_if_fail (NM_IS_SETTING_VPN (setting));
+
+ foreach_item_helper (NM_SETTING_VPN_GET_PRIVATE (setting)->data, func, user_data);
+}
+
+/**
+ * nm_setting_vpn_get_num_secrets:
+ * @setting: the #NMSettingVpn
+ *
+ * Gets number of VPN plugin specific secrets in the setting.
+ *
+ * Returns: the number of VPN plugin specific secrets
+ **/
+guint32
+nm_setting_vpn_get_num_secrets (NMSettingVpn *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_VPN (setting), 0);
+
+ return g_hash_table_size (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets);
+}
+
+/**
+ * nm_setting_vpn_add_secret:
+ * @setting: the #NMSettingVpn
+ * @key: a name that uniquely identifies the given secret @secret
+ * @secret: the secret to be referenced by @key
+ *
+ * Establishes a relationship between @key and @secret internally in the
+ * setting which may be retrieved later.
+ **/
+void
+nm_setting_vpn_add_secret (NMSettingVpn *setting,
+ const char *key,
+ const char *secret)
+{
+ g_return_if_fail (NM_IS_SETTING_VPN (setting));
+ g_return_if_fail (key != NULL);
+ g_return_if_fail (strlen (key) > 0);
+ g_return_if_fail (secret != NULL);
+ g_return_if_fail (strlen (secret) > 0);
+
+ g_hash_table_insert (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets,
+ g_strdup (key), g_strdup (secret));
+ g_object_notify (G_OBJECT (setting), NM_SETTING_VPN_SECRETS);
+}
+
+/**
+ * nm_setting_vpn_get_secret:
+ * @setting: the #NMSettingVpn
+ * @key: the name of the secret to retrieve
+ *
+ * Retrieves the secret of a key/value relationship previously established
+ * by nm_setting_vpn_add_secret().
+ *
+ * Returns: the secret, if any
+ **/
+const char *
+nm_setting_vpn_get_secret (NMSettingVpn *setting, const char *key)
+{
+ g_return_val_if_fail (NM_IS_SETTING_VPN (setting), NULL);
+
+ return (const char *) g_hash_table_lookup (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets, key);
+}
+
+/**
+ * nm_setting_vpn_remove_secret:
+ * @setting: the #NMSettingVpn
+ * @key: the name of the secret to remove
+ *
+ * Deletes a key/value relationship previously established by
+ * nm_setting_vpn_add_secret().
+ *
+ * Returns: %TRUE if the secret was found and removed from the internal list,
+ * %FALSE if it was not.
+ **/
+gboolean
+nm_setting_vpn_remove_secret (NMSettingVpn *setting, const char *key)
+{
+ gboolean found;
+
+ g_return_val_if_fail (NM_IS_SETTING_VPN (setting), FALSE);
+
+ found = g_hash_table_remove (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets, key);
+ if (found)
+ g_object_notify (G_OBJECT (setting), NM_SETTING_VPN_SECRETS);
+ return found;
+}
+
+/**
+ * nm_setting_vpn_foreach_secret:
+ * @setting: a #NMSettingVpn
+ * @func: (scope call): an user provided function
+ * @user_data: data to be passed to @func
+ *
+ * Iterates all secrets stored in this setting. It is safe to add, remove,
+ * and modify secrets inside @func, though any additions or removals made during
+ * iteration will not be part of the iteration.
+ */
+void
+nm_setting_vpn_foreach_secret (NMSettingVpn *setting,
+ NMVpnIterFunc func,
+ gpointer user_data)
+{
+ g_return_if_fail (NM_IS_SETTING_VPN (setting));
+
+ foreach_item_helper (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets, func, user_data);
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting);
+
+ if (!priv->service_type) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_VPN_SETTING_NAME, NM_SETTING_VPN_SERVICE_TYPE);
+ return FALSE;
+ }
+
+ if (!strlen (priv->service_type)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_VPN_SETTING_NAME, NM_SETTING_VPN_SERVICE_TYPE);
+ return FALSE;
+ }
+
+ /* default username can be NULL, but can't be zero-length */
+ if (priv->user_name && !strlen (priv->user_name)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_VPN_SETTING_NAME, NM_SETTING_VPN_USER_NAME);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static NMSettingUpdateSecretResult
+update_secret_string (NMSetting *setting,
+ const char *key,
+ const char *value,
+ GError **error)
+{
+ NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting);
+
+ g_return_val_if_fail (key != NULL, NM_SETTING_UPDATE_SECRET_ERROR);
+ g_return_val_if_fail (value != NULL, NM_SETTING_UPDATE_SECRET_ERROR);
+
+ if (!value || !strlen (value)) {
+ g_set_error (error, NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("secret was empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_VPN_SETTING_NAME, key);
+ return NM_SETTING_UPDATE_SECRET_ERROR;
+ }
+
+ if (g_strcmp0 (g_hash_table_lookup (priv->secrets, key), value) == 0)
+ return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
+
+ g_hash_table_insert (priv->secrets, g_strdup (key), g_strdup (value));
+ return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED;
+}
+
+static NMSettingUpdateSecretResult
+update_secret_dict (NMSetting *setting,
+ GVariant *secrets,
+ GError **error)
+{
+ NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting);
+ GVariantIter iter;
+ const char *name, *value;
+ NMSettingUpdateSecretResult result = NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
+
+ g_return_val_if_fail (secrets != NULL, NM_SETTING_UPDATE_SECRET_ERROR);
+
+ /* Make sure the items are valid */
+ g_variant_iter_init (&iter, secrets);
+ while (g_variant_iter_next (&iter, "{&s&s}", &name, &value)) {
+ if (!name || !strlen (name)) {
+ g_set_error_literal (error, NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_SETTING,
+ _("setting contained a secret with an empty name"));
+ g_prefix_error (error, "%s: ", NM_SETTING_VPN_SETTING_NAME);
+ return NM_SETTING_UPDATE_SECRET_ERROR;
+ }
+
+ if (!value || !strlen (value)) {
+ g_set_error (error, NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("secret value was empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_VPN_SETTING_NAME, name);
+ return NM_SETTING_UPDATE_SECRET_ERROR;
+ }
+ }
+
+ /* Now add the items to the settings' secrets list */
+ g_variant_iter_init (&iter, secrets);
+ while (g_variant_iter_next (&iter, "{&s&s}", &name, &value)) {
+ if (value == NULL) {
+ g_warn_if_fail (value != NULL);
+ continue;
+ }
+ if (strlen (value) == 0) {
+ g_warn_if_fail (strlen (value) > 0);
+ continue;
+ }
+
+ if (g_strcmp0 (g_hash_table_lookup (priv->secrets, name), value) == 0)
+ continue;
+
+ g_hash_table_insert (priv->secrets, g_strdup (name), g_strdup (value));
+ result = NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED;
+ }
+
+ return result;
+}
+
+static int
+update_one_secret (NMSetting *setting, const char *key, GVariant *value, GError **error)
+{
+ NMSettingUpdateSecretResult success = NM_SETTING_UPDATE_SECRET_ERROR;
+
+ g_return_val_if_fail (key != NULL, NM_SETTING_UPDATE_SECRET_ERROR);
+ g_return_val_if_fail (value != NULL, NM_SETTING_UPDATE_SECRET_ERROR);
+
+ if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) {
+ /* Passing the string properties individually isn't correct, and won't
+ * produce the correct result, but for some reason that's how it used
+ * to be done. So even though it's not correct, keep the code around
+ * for compatibility's sake.
+ */
+ success = update_secret_string (setting, key, g_variant_get_string (value, NULL), error);
+ } else if (g_variant_is_of_type (value, G_VARIANT_TYPE ("a{ss}"))) {
+ if (strcmp (key, NM_SETTING_VPN_SECRETS) != 0) {
+ g_set_error_literal (error, NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET,
+ _("not a secret property"));
+ g_prefix_error (error, "%s.%s ", NM_SETTING_VPN_SETTING_NAME, key);
+ } else
+ success = update_secret_dict (setting, value, error);
+ } else {
+ g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("secret is not of correct type"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_VPN_SETTING_NAME, key);
+ }
+
+ if (success == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED)
+ g_object_notify (G_OBJECT (setting), NM_SETTING_VPN_SECRETS);
+
+ return success;
+}
+
+static gboolean
+get_secret_flags (NMSetting *setting,
+ const char *secret_name,
+ gboolean verify_secret,
+ NMSettingSecretFlags *out_flags,
+ GError **error)
+{
+ NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting);
+ gboolean success = FALSE;
+ char *flags_key;
+ gpointer val;
+ unsigned long tmp;
+ NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
+
+ flags_key = g_strdup_printf ("%s-flags", secret_name);
+ if (g_hash_table_lookup_extended (priv->data, flags_key, NULL, &val)) {
+ errno = 0;
+ tmp = strtoul ((const char *) val, NULL, 10);
+ if ((errno == 0) && (tmp <= NM_SETTING_SECRET_FLAGS_ALL)) {
+ flags = (NMSettingSecretFlags) tmp;
+ success = TRUE;
+ } else {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("failed to convert value '%s' to uint"),
+ (const char *) val);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_VPN_SETTING_NAME, flags_key);
+ }
+ } else {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("secret flags property not found"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_VPN_SETTING_NAME, flags_key);
+ }
+ g_free (flags_key);
+ if (out_flags)
+ *out_flags = flags;
+ return success;
+}
+
+static gboolean
+set_secret_flags (NMSetting *setting,
+ const char *secret_name,
+ gboolean verify_secret,
+ NMSettingSecretFlags flags,
+ GError **error)
+{
+ g_hash_table_insert (NM_SETTING_VPN_GET_PRIVATE (setting)->data,
+ g_strdup_printf ("%s-flags", secret_name),
+ g_strdup_printf ("%u", flags));
+ g_object_notify (G_OBJECT (setting), NM_SETTING_VPN_SECRETS);
+ return TRUE;
+}
+
+static GPtrArray *
+need_secrets (NMSetting *setting)
+{
+ /* Assume that VPN connections need secrets since they almost always will */
+ return g_ptr_array_sized_new (1);
+}
+
+static gboolean
+compare_one_secret (NMSettingVpn *a,
+ NMSettingVpn *b,
+ NMSettingCompareFlags flags)
+{
+ GHashTable *a_secrets, *b_secrets;
+ GHashTableIter iter;
+ const char *key, *val;
+
+ a_secrets = NM_SETTING_VPN_GET_PRIVATE (a)->secrets;
+ b_secrets = NM_SETTING_VPN_GET_PRIVATE (b)->secrets;
+
+ g_hash_table_iter_init (&iter, a_secrets);
+ while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &val)) {
+ NMSettingSecretFlags a_secret_flags = NM_SETTING_SECRET_FLAG_NONE;
+ NMSettingSecretFlags b_secret_flags = NM_SETTING_SECRET_FLAG_NONE;
+
+ nm_setting_get_secret_flags (NM_SETTING (a), key, &a_secret_flags, NULL);
+ nm_setting_get_secret_flags (NM_SETTING (b), key, &b_secret_flags, NULL);
+
+ /* If the secret flags aren't the same, the settings aren't the same */
+ if (a_secret_flags != b_secret_flags)
+ return FALSE;
+
+ if ( (flags & NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS)
+ && (a_secret_flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED))
+ continue;
+
+ if ( (flags & NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)
+ && (a_secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED))
+ continue;
+
+ /* Now compare the values themselves */
+ if (g_strcmp0 (val, nm_setting_vpn_get_secret (b, key)) != 0)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+compare_property (NMSetting *setting,
+ NMSetting *other,
+ const GParamSpec *prop_spec,
+ NMSettingCompareFlags flags)
+{
+ gboolean same;
+
+ /* We only need to treat the 'secrets' property specially */
+ if (g_strcmp0 (prop_spec->name, NM_SETTING_VPN_SECRETS) != 0)
+ return NM_SETTING_CLASS (nm_setting_vpn_parent_class)->compare_property (setting, other, prop_spec, flags);
+
+ /* Compare A to B to ensure everything in A is found in B */
+ same = compare_one_secret (NM_SETTING_VPN (setting), NM_SETTING_VPN (other), flags);
+ if (same) {
+ /* And then B to A to ensure everything in B is also found in A */
+ same = compare_one_secret (NM_SETTING_VPN (other), NM_SETTING_VPN (setting), flags);
+ }
+
+ return same;
+}
+
+static gboolean
+clear_secrets_with_flags (NMSetting *setting,
+ GParamSpec *pspec,
+ NMSettingClearSecretsWithFlagsFn func,
+ gpointer user_data)
+{
+ NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting);
+ GHashTableIter iter;
+ const char *secret;
+ gboolean changed = TRUE;
+
+ if (priv->secrets == NULL)
+ return FALSE;
+
+ /* Iterate through secrets hash and check each entry */
+ g_hash_table_iter_init (&iter, priv->secrets);
+ while (g_hash_table_iter_next (&iter, (gpointer) &secret, NULL)) {
+ NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
+
+ nm_setting_get_secret_flags (setting, secret, &flags, NULL);
+ if (func (setting, pspec->name, flags, user_data) == TRUE) {
+ g_hash_table_iter_remove (&iter);
+ changed = TRUE;
+ }
+ }
+
+ if (changed)
+ g_object_notify (G_OBJECT (setting), NM_SETTING_VPN_SECRETS);
+
+ return changed;
+}
+
+static void
+destroy_one_secret (gpointer data)
+{
+ char *secret = (char *) data;
+
+ /* Don't leave the secret lying around in memory */
+ memset (secret, 0, strlen (secret));
+ g_free (secret);
+}
+
+static void
+nm_setting_vpn_init (NMSettingVpn *setting)
+{
+ NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting);
+
+ priv->data = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ priv->secrets = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, destroy_one_secret);
+}
+
+static void
+finalize (GObject *object)
+{
+ NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (object);
+
+ g_free (priv->service_type);
+ g_free (priv->user_name);
+ g_hash_table_destroy (priv->data);
+ g_hash_table_destroy (priv->secrets);
+
+ G_OBJECT_CLASS (nm_setting_vpn_parent_class)->finalize (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_SERVICE_TYPE:
+ g_free (priv->service_type);
+ priv->service_type = g_value_dup_string (value);
+ break;
+ case PROP_USER_NAME:
+ g_free (priv->user_name);
+ priv->user_name = g_value_dup_string (value);
+ break;
+ case PROP_PERSISTENT:
+ priv->persistent = g_value_get_boolean (value);
+ break;
+ case PROP_DATA:
+ g_hash_table_unref (priv->data);
+ priv->data = _nm_utils_copy_strdict (g_value_get_boxed (value));
+ break;
+ case PROP_SECRETS:
+ g_hash_table_unref (priv->secrets);
+ priv->secrets = _nm_utils_copy_strdict (g_value_get_boxed (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)
+{
+ NMSettingVpn *setting = NM_SETTING_VPN (object);
+ NMSettingVpnPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting);
+
+ switch (prop_id) {
+ case PROP_SERVICE_TYPE:
+ g_value_set_string (value, nm_setting_vpn_get_service_type (setting));
+ break;
+ case PROP_USER_NAME:
+ g_value_set_string (value, nm_setting_vpn_get_user_name (setting));
+ break;
+ case PROP_PERSISTENT:
+ g_value_set_boolean (value, priv->persistent);
+ break;
+ case PROP_DATA:
+ g_value_take_boxed (value, _nm_utils_copy_strdict (priv->data));
+ break;
+ case PROP_SECRETS:
+ g_value_take_boxed (value, _nm_utils_copy_strdict (priv->secrets));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_setting_vpn_class_init (NMSettingVpnClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+ NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+ g_type_class_add_private (setting_class, 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;
+
+ /* Properties */
+ /**
+ * NMSettingVpn:service-type:
+ *
+ * D-Bus service name of the VPN plugin that this setting uses to connect to
+ * its network. i.e. org.freedesktop.NetworkManager.vpnc for the vpnc
+ * plugin.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_SERVICE_TYPE,
+ g_param_spec_string (NM_SETTING_VPN_SERVICE_TYPE, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingVpn:user-name:
+ *
+ * If the VPN connection requires a user name for authentication, that name
+ * should be provided here. If the connection is available to more than one
+ * user, and the VPN requires each user to supply a different name, then
+ * leave this property empty. If this property is empty, NetworkManager
+ * will automatically supply the username of the user which requested the
+ * VPN connection.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_USER_NAME,
+ g_param_spec_string (NM_SETTING_VPN_USER_NAME, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingVpn:persistent:
+ *
+ * If the VPN service supports persistence, and this property is %TRUE,
+ * the VPN will attempt to stay connected across link changes and outages,
+ * until explicitly disconnected.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_PERSISTENT,
+ g_param_spec_boolean (NM_SETTING_VPN_PERSISTENT, "", "",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingVpn:data:
+ *
+ * Dictionary of key/value pairs of VPN plugin specific data. Both keys and
+ * values must be strings.
+ *
+ * Type: GHashTable(utf8,utf8)
+ **/
+ /* ---keyfile---
+ * property: data
+ * variable: separate variables named after keys of the dictionary
+ * description: The keys of the data dictionary are used as variable names directly
+ * under [vpn] section.
+ * example: remote=ovpn.corp.com cipher=AES-256-CBC username=joe
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_DATA,
+ g_param_spec_boxed (NM_SETTING_VPN_DATA, "", "",
+ 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);
+
+ /**
+ * NMSettingVpn:secrets:
+ *
+ * Dictionary of key/value pairs of VPN plugin specific secrets like
+ * passwords or private keys. Both keys and values must be strings.
+ *
+ * Type: GHashTable(utf8,utf8)
+ **/
+ /* ---keyfile---
+ * property: secrets
+ * variable: separate variables named after keys of the dictionary
+ * description: The keys of the secrets dictionary are used as variable names directly
+ * under [vpn-secrets] section.
+ * example: password=Popocatepetl
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_SECRETS,
+ g_param_spec_boxed (NM_SETTING_VPN_SECRETS, "", "",
+ G_TYPE_HASH_TABLE,
+ 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);
+}
diff --git a/libnm-core/nm-setting-vpn.h b/libnm-core/nm-setting-vpn.h
new file mode 100644
index 000000000..487549afa
--- /dev/null
+++ b/libnm-core/nm-setting-vpn.h
@@ -0,0 +1,102 @@
+/* -*- 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 2007 - 2013 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#ifndef __NM_SETTING_VPN_H__
+#define __NM_SETTING_VPN_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_VPN (nm_setting_vpn_get_type ())
+#define NM_SETTING_VPN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_VPN, NMSettingVpn))
+#define NM_SETTING_VPN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_VPN, NMSettingVpnClass))
+#define NM_IS_SETTING_VPN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_VPN))
+#define NM_IS_SETTING_VPN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_VPN))
+#define NM_SETTING_VPN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_VPN, NMSettingVpnClass))
+
+#define NM_SETTING_VPN_SETTING_NAME "vpn"
+
+#define NM_SETTING_VPN_SERVICE_TYPE "service-type"
+#define NM_SETTING_VPN_USER_NAME "user-name"
+#define NM_SETTING_VPN_PERSISTENT "persistent"
+#define NM_SETTING_VPN_DATA "data"
+#define NM_SETTING_VPN_SECRETS "secrets"
+
+struct _NMSettingVpn {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingVpnClass;
+
+/**
+ * NMVpnIterFunc:
+ * @key: the name of the data or secret item
+ * @value: the value of the data or secret item
+ * @user_data: User data passed to nm_setting_vpn_foreach_data_item() or
+ * nm_setting_vpn_foreach_secret()
+ **/
+typedef void (*NMVpnIterFunc) (const char *key, const char *value, gpointer user_data);
+
+GType nm_setting_vpn_get_type (void);
+
+NMSetting *nm_setting_vpn_new (void);
+const char *nm_setting_vpn_get_service_type (NMSettingVpn *setting);
+const char *nm_setting_vpn_get_user_name (NMSettingVpn *setting);
+gboolean nm_setting_vpn_get_persistent (NMSettingVpn *setting);
+
+guint32 nm_setting_vpn_get_num_data_items (NMSettingVpn *setting);
+void nm_setting_vpn_add_data_item (NMSettingVpn *setting,
+ const char *key,
+ const char *item);
+const char * nm_setting_vpn_get_data_item (NMSettingVpn *setting,
+ const char *key);
+gboolean nm_setting_vpn_remove_data_item (NMSettingVpn *setting,
+ const char *key);
+void nm_setting_vpn_foreach_data_item (NMSettingVpn *setting,
+ NMVpnIterFunc func,
+ gpointer user_data);
+
+guint32 nm_setting_vpn_get_num_secrets (NMSettingVpn *setting);
+void nm_setting_vpn_add_secret (NMSettingVpn *setting,
+ const char *key,
+ const char *secret);
+const char * nm_setting_vpn_get_secret (NMSettingVpn *setting,
+ const char *key);
+gboolean nm_setting_vpn_remove_secret (NMSettingVpn *setting,
+ const char *key);
+void nm_setting_vpn_foreach_secret (NMSettingVpn *setting,
+ NMVpnIterFunc func,
+ gpointer user_data);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_VPN_H__ */
diff --git a/libnm-core/nm-setting-wimax.c b/libnm-core/nm-setting-wimax.c
new file mode 100644
index 000000000..541c0bbfe
--- /dev/null
+++ b/libnm-core/nm-setting-wimax.c
@@ -0,0 +1,245 @@
+/* -*- 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 2011 - 2013 Red Hat, Inc.
+ * Copyright 2009 Novell, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <net/ethernet.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-wimax.h"
+#include "nm-setting-private.h"
+#include "nm-utils.h"
+#include "nm-utils-private.h"
+
+/**
+ * SECTION:nm-setting-wimax
+ * @short_description: Describes 802.16e Mobile WiMAX connection properties
+ *
+ * The #NMSettingWimax object is a #NMSetting subclass that describes properties
+ * necessary for connection to 802.16e Mobile WiMAX networks.
+ **/
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingWimax, nm_setting_wimax, NM_TYPE_SETTING,
+ _nm_register_setting (WIMAX, 1))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_WIMAX)
+
+#define NM_SETTING_WIMAX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIMAX, NMSettingWimaxPrivate))
+
+typedef struct {
+ char *network_name;
+ char *mac_address;
+} NMSettingWimaxPrivate;
+
+enum {
+ PROP_0,
+ PROP_NETWORK_NAME,
+ PROP_MAC_ADDRESS,
+
+ LAST_PROP
+};
+
+/**
+ * nm_setting_wimax_new:
+ *
+ * Creates a new #NMSettingWimax object with default values.
+ *
+ * Returns: the new empty #NMSettingWimax object
+ **/
+NMSetting *
+nm_setting_wimax_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_WIMAX, NULL);
+}
+
+/**
+ * nm_setting_wimax_get_network_name:
+ * @setting: the #NMSettingWimax
+ *
+ * Returns the WiMAX NSP name (ex "Sprint" or "CLEAR") which identifies the
+ * specific WiMAX network this setting describes a connection to.
+ *
+ * Returns: the WiMAX NSP name
+ **/
+const char *
+nm_setting_wimax_get_network_name (NMSettingWimax *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIMAX (setting), NULL);
+
+ return NM_SETTING_WIMAX_GET_PRIVATE (setting)->network_name;
+}
+
+/**
+ * nm_setting_wimax_get_mac_address:
+ * @setting: the #NMSettingWimax
+ *
+ * Returns the MAC address of a WiMAX device which this connection is locked
+ * to.
+ *
+ * Returns: the MAC address
+ **/
+const char *
+nm_setting_wimax_get_mac_address (NMSettingWimax *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIMAX (setting), NULL);
+
+ return NM_SETTING_WIMAX_GET_PRIVATE (setting)->mac_address;
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ NMSettingWimaxPrivate *priv = NM_SETTING_WIMAX_GET_PRIVATE (setting);
+
+ if (!priv->network_name) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIMAX_SETTING_NAME, NM_SETTING_WIMAX_NETWORK_NAME);
+ return FALSE;
+ }
+
+ if (!strlen (priv->network_name)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIMAX_SETTING_NAME, NM_SETTING_WIMAX_NETWORK_NAME);
+ return FALSE;
+ }
+
+ if (priv->mac_address && !nm_utils_hwaddr_valid (priv->mac_address, ETH_ALEN)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIMAX_SETTING_NAME, NM_SETTING_WIMAX_MAC_ADDRESS);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+nm_setting_wimax_init (NMSettingWimax *setting)
+{
+}
+
+static void
+finalize (GObject *object)
+{
+ NMSettingWimaxPrivate *priv = NM_SETTING_WIMAX_GET_PRIVATE (object);
+
+ g_free (priv->network_name);
+ g_free (priv->mac_address);
+
+ G_OBJECT_CLASS (nm_setting_wimax_parent_class)->finalize (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingWimaxPrivate *priv = NM_SETTING_WIMAX_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_NETWORK_NAME:
+ g_free (priv->network_name);
+ priv->network_name = g_value_dup_string (value);
+ break;
+ case PROP_MAC_ADDRESS:
+ g_free (priv->mac_address);
+ priv->mac_address = _nm_utils_hwaddr_canonical_or_invalid (g_value_get_string (value),
+ ETH_ALEN);
+ 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)
+{
+ NMSettingWimax *setting = NM_SETTING_WIMAX (object);
+
+ switch (prop_id) {
+ case PROP_NETWORK_NAME:
+ g_value_set_string (value, nm_setting_wimax_get_network_name (setting));
+ break;
+ case PROP_MAC_ADDRESS:
+ g_value_set_string (value, nm_setting_wimax_get_mac_address (setting));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_setting_wimax_class_init (NMSettingWimaxClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+ NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+ g_type_class_add_private (setting_class, 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 */
+ /**
+ * NMSettingWimax:network-name:
+ *
+ * Network Service Provider (NSP) name of the WiMAX network this connection
+ * should use.
+ **/
+ g_object_class_install_property
+ (object_class, PROP_NETWORK_NAME,
+ g_param_spec_string (NM_SETTING_WIMAX_NETWORK_NAME, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWimax:mac-address:
+ *
+ * If specified, this connection will only apply to the WiMAX device whose
+ * MAC address matches. This property does not change the MAC address of the
+ * device (known as MAC spoofing).
+ **/
+ g_object_class_install_property
+ (object_class, PROP_MAC_ADDRESS,
+ g_param_spec_string (NM_SETTING_WIMAX_MAC_ADDRESS, "", "",
+ 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);
+}
diff --git a/libnm-core/nm-setting-wimax.h b/libnm-core/nm-setting-wimax.h
new file mode 100644
index 000000000..0a5850466
--- /dev/null
+++ b/libnm-core/nm-setting-wimax.h
@@ -0,0 +1,64 @@
+/* -*- 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 2009 Novell, Inc.
+ */
+
+#ifndef __NM_SETTING_WIMAX_H__
+#define __NM_SETTING_WIMAX_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_WIMAX (nm_setting_wimax_get_type ())
+#define NM_SETTING_WIMAX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_WIMAX, NMSettingWimax))
+#define NM_SETTING_WIMAX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_WIMAX, NMSettingWimaxClass))
+#define NM_IS_SETTING_WIMAX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_WIMAX))
+#define NM_IS_SETTING_WIMAX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_WIMAX))
+#define NM_SETTING_WIMAX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_WIMAX, NMSettingWimaxClass))
+
+#define NM_SETTING_WIMAX_SETTING_NAME "wimax"
+
+#define NM_SETTING_WIMAX_NETWORK_NAME "network-name"
+#define NM_SETTING_WIMAX_MAC_ADDRESS "mac-address"
+
+struct _NMSettingWimax {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingWimaxClass;
+
+GType nm_setting_wimax_get_type (void);
+
+NMSetting *nm_setting_wimax_new (void);
+const char *nm_setting_wimax_get_network_name (NMSettingWimax *setting);
+const char *nm_setting_wimax_get_mac_address (NMSettingWimax *setting);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_WIMAX_H__ */
diff --git a/libnm-core/nm-setting-wired.c b/libnm-core/nm-setting-wired.c
new file mode 100644
index 000000000..ac143e45d
--- /dev/null
+++ b/libnm-core/nm-setting-wired.c
@@ -0,0 +1,1103 @@
+/* -*- 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 2007 - 2014 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <net/ethernet.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-wired.h"
+#include "nm-utils.h"
+#include "nm-utils-private.h"
+#include "nm-setting-private.h"
+
+/**
+ * SECTION:nm-setting-wired
+ * @short_description: Describes connection properties for Ethernet-based networks
+ *
+ * The #NMSettingWired object is a #NMSetting subclass that describes properties
+ * necessary for connection to Ethernet networks.
+ **/
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingWired, nm_setting_wired, NM_TYPE_SETTING,
+ _nm_register_setting (WIRED, 1))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_WIRED)
+
+#define NM_SETTING_WIRED_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIRED, NMSettingWiredPrivate))
+
+typedef struct {
+ char *port;
+ guint32 speed;
+ char *duplex;
+ gboolean auto_negotiate;
+ char *device_mac_address;
+ char *cloned_mac_address;
+ GArray *mac_address_blacklist;
+ guint32 mtu;
+ char **s390_subchannels;
+ char *s390_nettype;
+ GHashTable *s390_options;
+} NMSettingWiredPrivate;
+
+enum {
+ PROP_0,
+ PROP_PORT,
+ PROP_SPEED,
+ PROP_DUPLEX,
+ PROP_AUTO_NEGOTIATE,
+ PROP_MAC_ADDRESS,
+ PROP_CLONED_MAC_ADDRESS,
+ PROP_MAC_ADDRESS_BLACKLIST,
+ PROP_MTU,
+ PROP_S390_SUBCHANNELS,
+ PROP_S390_NETTYPE,
+ PROP_S390_OPTIONS,
+
+ LAST_PROP
+};
+
+static const char *valid_s390_opts[] = {
+ "portno", "layer2", "portname", "protocol", "priority_queueing",
+ "buffer_count", "isolation", "total", "inter", "inter_jumbo", "route4",
+ "route6", "fake_broadcast", "broadcast_mode", "canonical_macaddr",
+ "checksumming", "sniffer", "large_send", "ipato_enable", "ipato_invert4",
+ "ipato_add4", "ipato_invert6", "ipato_add6", "vipa_add4", "vipa_add6",
+ "rxip_add4", "rxip_add6", "lancmd_timeout", "ctcprot",
+ NULL
+};
+
+/**
+ * nm_setting_wired_new:
+ *
+ * Creates a new #NMSettingWired object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingWired object
+ **/
+NMSetting *
+nm_setting_wired_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_WIRED, NULL);
+}
+
+/**
+ * nm_setting_wired_get_port:
+ * @setting: the #NMSettingWired
+ *
+ * Returns: the #NMSettingWired:port property of the setting
+ **/
+const char *
+nm_setting_wired_get_port (NMSettingWired *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL);
+
+ return NM_SETTING_WIRED_GET_PRIVATE (setting)->port;
+}
+
+/**
+ * nm_setting_wired_get_speed:
+ * @setting: the #NMSettingWired
+ *
+ * Returns: the #NMSettingWired:speed property of the setting
+ **/
+guint32
+nm_setting_wired_get_speed (NMSettingWired *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), 0);
+
+ return NM_SETTING_WIRED_GET_PRIVATE (setting)->speed;
+}
+
+/**
+ * nm_setting_wired_get_duplex:
+ * @setting: the #NMSettingWired
+ *
+ * Returns: the #NMSettingWired:duplex property of the setting
+ **/
+const char *
+nm_setting_wired_get_duplex (NMSettingWired *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL);
+
+ return NM_SETTING_WIRED_GET_PRIVATE (setting)->duplex;
+}
+
+/**
+ * nm_setting_wired_get_auto_negotiate:
+ * @setting: the #NMSettingWired
+ *
+ * Returns: the #NMSettingWired:auto-negotiate property of the setting
+ **/
+gboolean
+nm_setting_wired_get_auto_negotiate (NMSettingWired *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), FALSE);
+
+ return NM_SETTING_WIRED_GET_PRIVATE (setting)->auto_negotiate;
+}
+
+/**
+ * nm_setting_wired_get_mac_address:
+ * @setting: the #NMSettingWired
+ *
+ * Returns: the #NMSettingWired:mac-address property of the setting
+ **/
+const char *
+nm_setting_wired_get_mac_address (NMSettingWired *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL);
+
+ return NM_SETTING_WIRED_GET_PRIVATE (setting)->device_mac_address;
+}
+
+/**
+ * nm_setting_wired_get_cloned_mac_address:
+ * @setting: the #NMSettingWired
+ *
+ * Returns: the #NMSettingWired:cloned-mac-address property of the setting
+ **/
+const char *
+nm_setting_wired_get_cloned_mac_address (NMSettingWired *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL);
+
+ return NM_SETTING_WIRED_GET_PRIVATE (setting)->cloned_mac_address;
+}
+
+/**
+ * nm_setting_wired_get_mac_address_blacklist:
+ * @setting: the #NMSettingWired
+ *
+ * Returns: the #NMSettingWired:mac-address-blacklist property of the setting
+ **/
+const char * const *
+nm_setting_wired_get_mac_address_blacklist (NMSettingWired *setting)
+{
+ NMSettingWiredPrivate *priv;
+
+ g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL);
+
+ priv = NM_SETTING_WIRED_GET_PRIVATE (setting);
+ return (const char * const *) priv->mac_address_blacklist->data;
+}
+
+/**
+ * nm_setting_wired_get_num_mac_blacklist_items:
+ * @setting: the #NMSettingWired
+ *
+ * Returns: the number of blacklisted MAC addresses
+ **/
+guint32
+nm_setting_wired_get_num_mac_blacklist_items (NMSettingWired *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), 0);
+
+ return NM_SETTING_WIRED_GET_PRIVATE (setting)->mac_address_blacklist->len;
+}
+
+/**
+ * nm_setting_wired_get_mac_blacklist_item:
+ * @setting: the #NMSettingWired
+ * @idx: the zero-based index of the MAC address entry
+ *
+ * Returns: the blacklisted MAC address string (hex-digits-and-colons notation)
+ * at index @idx
+ **/
+const char *
+nm_setting_wired_get_mac_blacklist_item (NMSettingWired *setting, guint32 idx)
+{
+ NMSettingWiredPrivate *priv;
+
+ g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL);
+
+ priv = NM_SETTING_WIRED_GET_PRIVATE (setting);
+ g_return_val_if_fail (idx <= priv->mac_address_blacklist->len, NULL);
+
+ return g_array_index (priv->mac_address_blacklist, const char *, idx);
+}
+
+/**
+ * nm_setting_wired_add_mac_blacklist_item:
+ * @setting: the #NMSettingWired
+ * @mac: the MAC address string (hex-digits-and-colons notation) to blacklist
+ *
+ * Adds a new MAC address to the #NMSettingWired:mac-address-blacklist property.
+ *
+ * Returns: %TRUE if the MAC address was added; %FALSE if the MAC address
+ * is invalid or was already present
+ **/
+gboolean
+nm_setting_wired_add_mac_blacklist_item (NMSettingWired *setting, const char *mac)
+{
+ NMSettingWiredPrivate *priv;
+ const char *candidate;
+ int i;
+
+ g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), FALSE);
+ g_return_val_if_fail (mac != NULL, FALSE);
+
+ if (!nm_utils_hwaddr_valid (mac, ETH_ALEN))
+ return FALSE;
+
+ priv = NM_SETTING_WIRED_GET_PRIVATE (setting);
+ for (i = 0; i < priv->mac_address_blacklist->len; i++) {
+ candidate = g_array_index (priv->mac_address_blacklist, char *, i);
+ if (nm_utils_hwaddr_matches (mac, -1, candidate, -1))
+ return FALSE;
+ }
+
+ mac = nm_utils_hwaddr_canonical (mac, ETH_ALEN);
+ g_array_append_val (priv->mac_address_blacklist, mac);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST);
+ return TRUE;
+}
+
+/**
+ * nm_setting_wired_remove_mac_blacklist_item:
+ * @setting: the #NMSettingWired
+ * @idx: index number of the MAC address
+ *
+ * Removes the MAC address at index @idx from the blacklist.
+ **/
+void
+nm_setting_wired_remove_mac_blacklist_item (NMSettingWired *setting, guint32 idx)
+{
+ NMSettingWiredPrivate *priv;
+
+ g_return_if_fail (NM_IS_SETTING_WIRED (setting));
+
+ priv = NM_SETTING_WIRED_GET_PRIVATE (setting);
+ g_return_if_fail (idx < priv->mac_address_blacklist->len);
+
+ g_array_remove_index (priv->mac_address_blacklist, idx);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST);
+}
+
+/**
+ * nm_setting_wired_remove_mac_blacklist_item_by_value:
+ * @setting: the #NMSettingWired
+ * @mac: the MAC address string (hex-digits-and-colons notation) to remove from
+ * the blacklist
+ *
+ * Removes the MAC address @mac from the blacklist.
+ *
+ * Returns: %TRUE if the MAC address was found and removed; %FALSE if it was not.
+ **/
+gboolean
+nm_setting_wired_remove_mac_blacklist_item_by_value (NMSettingWired *setting, const char *mac)
+{
+ NMSettingWiredPrivate *priv;
+ const char *candidate;
+ int i;
+
+ g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), FALSE);
+ g_return_val_if_fail (mac != NULL, FALSE);
+
+ priv = NM_SETTING_WIRED_GET_PRIVATE (setting);
+ for (i = 0; i < priv->mac_address_blacklist->len; i++) {
+ candidate = g_array_index (priv->mac_address_blacklist, char *, i);
+ if (!nm_utils_hwaddr_matches (mac, -1, candidate, -1)) {
+ g_array_remove_index (priv->mac_address_blacklist, i);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * nm_setting_wired_clear_mac_blacklist_items:
+ * @setting: the #NMSettingWired
+ *
+ * Removes all blacklisted MAC addresses.
+ **/
+void
+nm_setting_wired_clear_mac_blacklist_items (NMSettingWired *setting)
+{
+ g_return_if_fail (NM_IS_SETTING_WIRED (setting));
+
+ g_array_set_size (NM_SETTING_WIRED_GET_PRIVATE (setting)->mac_address_blacklist, 0);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST);
+}
+
+/**
+ * nm_setting_wired_get_mtu:
+ * @setting: the #NMSettingWired
+ *
+ * Returns: the #NMSettingWired:mtu property of the setting
+ **/
+guint32
+nm_setting_wired_get_mtu (NMSettingWired *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), 0);
+
+ return NM_SETTING_WIRED_GET_PRIVATE (setting)->mtu;
+}
+
+/**
+ * nm_setting_wired_get_s390_subchannels:
+ * @setting: the #NMSettingWired
+ *
+ * Return the list of s390 subchannels that identify the device that this
+ * connection is applicable to. The connection should only be used in
+ * conjunction with that device.
+ *
+ * Returns: (transfer none) (element-type utf8): array of strings, each specifying
+ * one subchannel the s390 device uses to communicate to the host.
+ **/
+const char * const *
+nm_setting_wired_get_s390_subchannels (NMSettingWired *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL);
+
+ return (const char * const *) NM_SETTING_WIRED_GET_PRIVATE (setting)->s390_subchannels;
+}
+
+/**
+ * nm_setting_wired_get_s390_nettype:
+ * @setting: the #NMSettingWired
+ *
+ * Returns the s390 device type this connection should apply to. Will be one
+ * of 'qeth', 'lcs', or 'ctc'.
+ *
+ * Returns: the s390 device type
+ **/
+const char *
+nm_setting_wired_get_s390_nettype (NMSettingWired *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL);
+
+ return NM_SETTING_WIRED_GET_PRIVATE (setting)->s390_nettype;
+}
+
+/**
+ * nm_setting_wired_get_num_s390_options:
+ * @setting: the #NMSettingWired
+ *
+ * Returns the number of s390-specific options that should be set for this
+ * device when it is activated. This can be used to retrieve each s390
+ * option individually using nm_setting_wired_get_s390_option().
+ *
+ * Returns: the number of s390-specific device options
+ **/
+guint32
+nm_setting_wired_get_num_s390_options (NMSettingWired *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), 0);
+
+ return g_hash_table_size (NM_SETTING_WIRED_GET_PRIVATE (setting)->s390_options);
+}
+
+/**
+ * nm_setting_wired_get_s390_option:
+ * @setting: the #NMSettingWired
+ * @idx: index of the desired option, from 0 to
+ * nm_setting_wired_get_num_s390_options() - 1
+ * @out_key: (out) (transfer none): on return, the key name of the s390 specific
+ * option; this value is owned by the setting and should not be modified
+ * @out_value: (out) (transfer none): on return, the value of the key of the
+ * s390 specific option; this value is owned by the setting and should not be
+ * modified
+ *
+ * Given an index, return the value of the s390 option at that index. indexes
+ * are *not* guaranteed to be static across modifications to options done by
+ * nm_setting_wired_add_s390_option() and nm_setting_wired_remove_s390_option(),
+ * and should not be used to refer to options except for short periods of time
+ * such as during option iteration.
+ *
+ * Returns: %TRUE on success if the index was valid and an option was found,
+ * %FALSE if the index was invalid (ie, greater than the number of options
+ * currently held by the setting)
+ **/
+gboolean
+nm_setting_wired_get_s390_option (NMSettingWired *setting,
+ guint32 idx,
+ const char **out_key,
+ const char **out_value)
+{
+ NMSettingWiredPrivate *priv;
+ guint32 num_keys;
+ GList *keys;
+ const char *_key = NULL, *_value = NULL;
+
+ g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), FALSE);
+
+ priv = NM_SETTING_WIRED_GET_PRIVATE (setting);
+
+ num_keys = nm_setting_wired_get_num_s390_options (setting);
+ g_return_val_if_fail (idx < num_keys, FALSE);
+
+ keys = g_hash_table_get_keys (priv->s390_options);
+ _key = g_list_nth_data (keys, idx);
+ _value = g_hash_table_lookup (priv->s390_options, _key);
+
+ if (out_key)
+ *out_key = _key;
+ if (out_value)
+ *out_value = _value;
+ return TRUE;
+}
+
+/**
+ * nm_setting_wired_get_s390_option_by_key:
+ * @setting: the #NMSettingWired
+ * @key: the key for which to retrieve the value
+ *
+ * Returns the value associated with the s390-specific option specified by
+ * @key, if it exists.
+ *
+ * Returns: the value, or %NULL if the key/value pair was never added to the
+ * setting; the value is owned by the setting and must not be modified
+ **/
+const char *
+nm_setting_wired_get_s390_option_by_key (NMSettingWired *setting,
+ const char *key)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), NULL);
+ g_return_val_if_fail (key != NULL, NULL);
+ g_return_val_if_fail (strlen (key), NULL);
+
+ return g_hash_table_lookup (NM_SETTING_WIRED_GET_PRIVATE (setting)->s390_options, key);
+}
+
+/**
+ * nm_setting_wired_add_s390_option:
+ * @setting: the #NMSettingWired
+ * @key: key name for the option
+ * @value: value for the option
+ *
+ * Add an option to the table. The option is compared to an internal list
+ * of allowed options. Key names may contain only alphanumeric characters
+ * (ie [a-zA-Z0-9]). Adding a new key replaces any existing key/value pair that
+ * may already exist.
+ *
+ * Returns: %TRUE if the option was valid and was added to the internal option
+ * list, %FALSE if it was not.
+ **/
+gboolean
+nm_setting_wired_add_s390_option (NMSettingWired *setting,
+ const char *key,
+ const char *value)
+{
+ size_t value_len;
+
+ g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), FALSE);
+ g_return_val_if_fail (key != NULL, FALSE);
+ g_return_val_if_fail (strlen (key), FALSE);
+ g_return_val_if_fail (_nm_utils_string_in_list (key, valid_s390_opts), FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+
+ value_len = strlen (value);
+ g_return_val_if_fail (value_len > 0 && value_len < 200, FALSE);
+
+ g_hash_table_insert (NM_SETTING_WIRED_GET_PRIVATE (setting)->s390_options,
+ g_strdup (key),
+ g_strdup (value));
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRED_S390_OPTIONS);
+ return TRUE;
+}
+
+/**
+ * nm_setting_wired_remove_s390_option:
+ * @setting: the #NMSettingWired
+ * @key: key name for the option to remove
+ *
+ * Remove the s390-specific option referenced by @key from the internal option
+ * list.
+ *
+ * Returns: %TRUE if the option was found and removed from the internal option
+ * list, %FALSE if it was not.
+ **/
+gboolean
+nm_setting_wired_remove_s390_option (NMSettingWired *setting,
+ const char *key)
+{
+ gboolean found;
+
+ g_return_val_if_fail (NM_IS_SETTING_WIRED (setting), FALSE);
+ g_return_val_if_fail (key != NULL, FALSE);
+ g_return_val_if_fail (strlen (key), FALSE);
+
+ found = g_hash_table_remove (NM_SETTING_WIRED_GET_PRIVATE (setting)->s390_options, key);
+ if (found)
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRED_S390_OPTIONS);
+ return found;
+}
+
+/**
+ * nm_setting_wired_get_valid_s390_options:
+ * @setting: the #NMSettingWired
+ *
+ * Returns a list of valid s390 options.
+ *
+ * Returns: (transfer none): a %NULL-terminated array of strings of valid s390 options.
+ **/
+const char **
+nm_setting_wired_get_valid_s390_options (NMSettingWired *setting)
+{
+ return valid_s390_opts;
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE (setting);
+ const char *valid_ports[] = { "tp", "aui", "bnc", "mii", NULL };
+ const char *valid_duplex[] = { "half", "full", NULL };
+ const char *valid_nettype[] = { "qeth", "lcs", "ctc", NULL };
+ GHashTableIter iter;
+ const char *key, *value;
+ int i;
+
+ if (priv->port && !_nm_utils_string_in_list (priv->port, valid_ports)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid Ethernet port value"),
+ priv->port);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_PORT);
+ return FALSE;
+ }
+
+ if (priv->duplex && !_nm_utils_string_in_list (priv->duplex, valid_duplex)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid duplex value"),
+ priv->duplex);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_DUPLEX);
+ return FALSE;
+ }
+
+ if (priv->device_mac_address && !nm_utils_hwaddr_valid (priv->device_mac_address, ETH_ALEN)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("is not a valid MAC address"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_MAC_ADDRESS);
+ return FALSE;
+ }
+
+ for (i = 0; i < priv->mac_address_blacklist->len; i++) {
+ const char *mac = g_array_index (priv->mac_address_blacklist, const char *, i);
+
+ if (!nm_utils_hwaddr_valid (mac, ETH_ALEN)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid MAC address"),
+ mac);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST);
+ return FALSE;
+ }
+ }
+
+ if (priv->s390_subchannels) {
+ int len = g_strv_length (priv->s390_subchannels);
+
+ if (len != 2 && len != 3) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_S390_SUBCHANNELS);
+ return FALSE;
+ }
+ }
+
+ if (priv->s390_nettype && !_nm_utils_string_in_list (priv->s390_nettype, valid_nettype)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_S390_NETTYPE);
+ return FALSE;
+ }
+
+ g_hash_table_iter_init (&iter, priv->s390_options);
+ while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value)) {
+ if ( !_nm_utils_string_in_list (key, valid_s390_opts)
+ || !strlen (value)
+ || (strlen (value) > 200)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("invalid '%s' or its value '%s'"),
+ key, value);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_S390_OPTIONS);
+ return FALSE;
+ }
+ }
+
+ if (priv->cloned_mac_address && !nm_utils_hwaddr_valid (priv->cloned_mac_address, ETH_ALEN)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("is not a valid MAC address"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_CLONED_MAC_ADDRESS);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+clear_blacklist_item (char **item_p)
+{
+ g_free (*item_p);
+}
+
+static void
+nm_setting_wired_init (NMSettingWired *setting)
+{
+ NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE (setting);
+
+ priv->s390_options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ /* We use GArray rather than GPtrArray so it will automatically be NULL-terminated */
+ priv->mac_address_blacklist = g_array_new (TRUE, FALSE, sizeof (char *));
+ g_array_set_clear_func (priv->mac_address_blacklist, (GDestroyNotify) clear_blacklist_item);
+}
+
+static void
+finalize (GObject *object)
+{
+ NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE (object);
+
+ g_free (priv->port);
+ g_free (priv->duplex);
+ g_free (priv->s390_nettype);
+
+ g_hash_table_destroy (priv->s390_options);
+
+ g_free (priv->device_mac_address);
+ g_free (priv->cloned_mac_address);
+ g_array_unref (priv->mac_address_blacklist);
+
+ if (priv->s390_subchannels)
+ g_strfreev (priv->s390_subchannels);
+
+ G_OBJECT_CLASS (nm_setting_wired_parent_class)->finalize (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE (object);
+ const char * const *blacklist;
+ const char *mac;
+ int i;
+
+ switch (prop_id) {
+ case PROP_PORT:
+ g_free (priv->port);
+ priv->port = g_value_dup_string (value);
+ break;
+ case PROP_SPEED:
+ priv->speed = g_value_get_uint (value);
+ break;
+ case PROP_DUPLEX:
+ g_free (priv->duplex);
+ priv->duplex = g_value_dup_string (value);
+ break;
+ case PROP_AUTO_NEGOTIATE:
+ priv->auto_negotiate = g_value_get_boolean (value);
+ break;
+ case PROP_MAC_ADDRESS:
+ g_free (priv->device_mac_address);
+ priv->device_mac_address = _nm_utils_hwaddr_canonical_or_invalid (g_value_get_string (value),
+ ETH_ALEN);
+ break;
+ case PROP_CLONED_MAC_ADDRESS:
+ g_free (priv->cloned_mac_address);
+ priv->cloned_mac_address = _nm_utils_hwaddr_canonical_or_invalid (g_value_get_string (value),
+ ETH_ALEN);
+ break;
+ case PROP_MAC_ADDRESS_BLACKLIST:
+ blacklist = g_value_get_boxed (value);
+ g_array_set_size (priv->mac_address_blacklist, 0);
+ if (blacklist && *blacklist) {
+ for (i = 0; blacklist[i]; i++) {
+ mac = _nm_utils_hwaddr_canonical_or_invalid (blacklist[i], ETH_ALEN);
+ g_array_append_val (priv->mac_address_blacklist, mac);
+ }
+ }
+ break;
+ case PROP_MTU:
+ priv->mtu = g_value_get_uint (value);
+ break;
+ case PROP_S390_SUBCHANNELS:
+ if (priv->s390_subchannels)
+ g_strfreev (priv->s390_subchannels);
+ priv->s390_subchannels = g_value_dup_boxed (value);
+ break;
+ case PROP_S390_NETTYPE:
+ g_free (priv->s390_nettype);
+ priv->s390_nettype = g_value_dup_string (value);
+ break;
+ case PROP_S390_OPTIONS:
+ g_hash_table_unref (priv->s390_options);
+ priv->s390_options = _nm_utils_copy_strdict (g_value_get_boxed (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)
+{
+ NMSettingWired *setting = NM_SETTING_WIRED (object);
+ NMSettingWiredPrivate *priv = NM_SETTING_WIRED_GET_PRIVATE (setting);
+
+ switch (prop_id) {
+ case PROP_PORT:
+ g_value_set_string (value, nm_setting_wired_get_port (setting));
+ break;
+ case PROP_SPEED:
+ g_value_set_uint (value, nm_setting_wired_get_speed (setting));
+ break;
+ case PROP_DUPLEX:
+ g_value_set_string (value, nm_setting_wired_get_duplex (setting));
+ break;
+ case PROP_AUTO_NEGOTIATE:
+ g_value_set_boolean (value, nm_setting_wired_get_auto_negotiate (setting));
+ break;
+ case PROP_MAC_ADDRESS:
+ g_value_set_string (value, nm_setting_wired_get_mac_address (setting));
+ break;
+ case PROP_CLONED_MAC_ADDRESS:
+ g_value_set_string (value, nm_setting_wired_get_cloned_mac_address (setting));
+ break;
+ case PROP_MAC_ADDRESS_BLACKLIST:
+ g_value_set_boxed (value, (char **) priv->mac_address_blacklist->data);
+ break;
+ case PROP_MTU:
+ g_value_set_uint (value, nm_setting_wired_get_mtu (setting));
+ break;
+ case PROP_S390_SUBCHANNELS:
+ g_value_set_boxed (value, priv->s390_subchannels);
+ break;
+ case PROP_S390_NETTYPE:
+ g_value_set_string (value, nm_setting_wired_get_s390_nettype (setting));
+ break;
+ case PROP_S390_OPTIONS:
+ g_value_take_boxed (value, _nm_utils_copy_strdict (priv->s390_options));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_setting_wired_class_init (NMSettingWiredClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+ NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+ g_type_class_add_private (setting_class, sizeof (NMSettingWiredPrivate));
+
+ /* virtual methods */
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+ object_class->finalize = finalize;
+ parent_class->verify = verify;
+
+ /* Properties */
+ /**
+ * NMSettingWired:port:
+ *
+ * Specific port type to use if multiple the device supports multiple
+ * attachment methods. One of "tp" (Twisted Pair), "aui" (Attachment Unit
+ * Interface), "bnc" (Thin Ethernet) or "mii" (Media Independent Interface.
+ * If the device supports only one port type, this setting is ignored.
+ **/
+ /* ---ifcfg-rh---
+ * property: port
+ * variable: (none)
+ * description: The property is not saved by the plugin.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_PORT,
+ g_param_spec_string (NM_SETTING_WIRED_PORT, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWired:speed:
+ *
+ * If non-zero, request that the device use only the specified speed. In
+ * Mbit/s, ie 100 == 100Mbit/s.
+ **/
+ /* ---ifcfg-rh---
+ * property: speed
+ * variable: (none)
+ * description: The property is not saved by the plugin.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_SPEED,
+ g_param_spec_uint (NM_SETTING_WIRED_SPEED, "", "",
+ 0, G_MAXUINT32, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWired:duplex:
+ *
+ * If specified, request that the device only use the specified duplex mode.
+ * Either "half" or "full".
+ **/
+ /* ---ifcfg-rh---
+ * property: duplex
+ * variable: (none)
+ * description: The property is not saved by the plugin.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_DUPLEX,
+ g_param_spec_string (NM_SETTING_WIRED_DUPLEX, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWired:auto-negotiate:
+ *
+ * If %TRUE, allow auto-negotiation of port speed and duplex mode. If
+ * %FALSE, do not allow auto-negotiation, in which case the "speed" and
+ * "duplex" properties should be set.
+ **/
+ /* ---ifcfg-rh---
+ * property: auto-negotiate
+ * variable: (none)
+ * description: The property is not saved by the plugin.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_AUTO_NEGOTIATE,
+ g_param_spec_boolean (NM_SETTING_WIRED_AUTO_NEGOTIATE, "", "",
+ TRUE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWired:mac-address:
+ *
+ * If specified, this connection will only apply to the Ethernet device
+ * whose permanent MAC address matches. This property does not change the
+ * MAC address of the device (i.e. MAC spoofing).
+ **/
+ /* ---keyfile---
+ * property: mac-address
+ * format: ususal hex-digits-and-colons notation
+ * description: MAC address in traditional hex-digits-and-colons notation
+ * (e.g. 00:22:68:12:79:A2), or semicolon separated list of 6 bytes (obsolete)
+ * (e.g. 0;34;104;18;121;162)
+ * ---end---
+ * ---ifcfg-rh---
+ * property: mac-address
+ * variable: HWADDR
+ * description: Hardware address of the device in traditional hex-digits-and-colons
+ * notation (e.g. 00:22:68:14:5A:05).
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_MAC_ADDRESS,
+ g_param_spec_string (NM_SETTING_WIRED_MAC_ADDRESS, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+ _nm_setting_class_transform_property (parent_class, NM_SETTING_WIRED_MAC_ADDRESS,
+ G_VARIANT_TYPE_BYTESTRING,
+ _nm_utils_hwaddr_to_dbus,
+ _nm_utils_hwaddr_from_dbus);
+
+ /**
+ * NMSettingWired:cloned-mac-address:
+ *
+ * If specified, request that the device use this MAC address instead of its
+ * permanent MAC address. This is known as MAC cloning or spoofing.
+ **/
+ /* ---keyfile---
+ * property: cloned-mac-address
+ * format: ususal hex-digits-and-colons notation
+ * description: Cloned MAC address in traditional hex-digits-and-colons notation
+ * (e.g. 00:22:68:12:79:B2), or semicolon separated list of 6 bytes (obsolete)
+ * (e.g. 0;34;104;18;121;178).
+ * ---end---
+ * ---ifcfg-rh---
+ * property: cloned-mac-address
+ * variable: MACADDR
+ * description: Cloned (spoofed) MAC address in traditional hex-digits-and-colons
+ * notation (e.g. 00:22:68:14:5A:99).
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_CLONED_MAC_ADDRESS,
+ g_param_spec_string (NM_SETTING_WIRED_CLONED_MAC_ADDRESS, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+ _nm_setting_class_transform_property (parent_class, NM_SETTING_WIRED_CLONED_MAC_ADDRESS,
+ G_VARIANT_TYPE_BYTESTRING,
+ _nm_utils_hwaddr_to_dbus,
+ _nm_utils_hwaddr_from_dbus);
+
+ /**
+ * NMSettingWired:mac-address-blacklist:
+ *
+ * If specified, this connection will never apply to the Ethernet device
+ * whose permanent MAC address matches an address in the list. Each MAC
+ * address is in the standard hex-digits-and-colons notation
+ * (00:11:22:33:44:55).
+ **/
+ /* ---keyfile---
+ * property: mac-address-blacklist
+ * format: list of MACs (separated with semicolons)
+ * description: MAC address blacklist.
+ * example: mac-address-blacklist= 00:22:68:12:79:A6;00:22:68:12:79:78
+ * ---end---
+ * ---ifcfg-rh---
+ * property: mac-address-blacklist
+ * variable: HWADDR_BLACKLIST(+)
+ * description: It denies usage of the connection for any device whose address
+ * is listed.
+ * example: HWADDR_BLACKLIST="00:22:68:11:69:08 00:11:22:11:44:55"
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_MAC_ADDRESS_BLACKLIST,
+ g_param_spec_boxed (NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST, "", "",
+ G_TYPE_STRV,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWired:mtu:
+ *
+ * If non-zero, only transmit packets of the specified size or smaller,
+ * breaking larger packets up into multiple Ethernet frames.
+ **/
+ /* ---ifcfg-rh---
+ * property: mtu
+ * variable: MTU
+ * description: MTU of the interface.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_MTU,
+ g_param_spec_uint (NM_SETTING_WIRED_MTU, "", "",
+ 0, G_MAXUINT32, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWired:s390-subchannels:
+ *
+ * Identifies specific subchannels that this network device uses for
+ * communication with z/VM or s390 host. Like the
+ * #NMSettingWired:mac-address property for non-z/VM devices, this property
+ * can be used to ensure this connection only applies to the network device
+ * that uses these subchannels. The list should contain exactly 3 strings,
+ * and each string may only be composed of hexadecimal characters and the
+ * period (.) character.
+ **/
+ /* ---ifcfg-rh---
+ * property: s390-subchannels
+ * variable: SUBCHANNELS
+ * description: Subchannels for IBM S390 hosts.
+ * example: SUBCHANNELS=0.0.b00a,0.0.b00b,0.0.b00c
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_S390_SUBCHANNELS,
+ g_param_spec_boxed (NM_SETTING_WIRED_S390_SUBCHANNELS, "", "",
+ G_TYPE_STRV,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWired:s390-nettype:
+ *
+ * s390 network device type; one of "qeth", "lcs", or "ctc", representing
+ * the different types of virtual network devices available on s390 systems.
+ **/
+ /* ---ifcfg-rh---
+ * property: s390-nettype
+ * variable: NETTYPE
+ * values: "qeth", "lcs" or "ctc"
+ * description: Network type of the S390 host.
+ * example: NETTYPE=qeth
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_S390_NETTYPE,
+ g_param_spec_string (NM_SETTING_WIRED_S390_NETTYPE, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWired:s390-options:
+ *
+ * Dictionary of key/value pairs of s390-specific device options. Both keys
+ * and values must be strings. Allowed keys include "portno", "layer2",
+ * "portname", "protocol", among others. Key names must contain only
+ * alphanumeric characters (ie, [a-zA-Z0-9]).
+ *
+ * Type: GHashTable(utf8,utf8)
+ **/
+ /* ---ifcfg-rh---
+ * property: s390-options
+ * variable: OPTIONS and PORTNAME, CTCPROTO,
+ * description: S390 device options. All options go to OPTIONS, except for
+ * "portname" and "ctcprot" that have their own variables.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_S390_OPTIONS,
+ g_param_spec_boxed (NM_SETTING_WIRED_S390_OPTIONS, "", "",
+ G_TYPE_HASH_TABLE,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_INFERRABLE |
+ G_PARAM_STATIC_STRINGS));
+ _nm_setting_class_transform_property (parent_class, NM_SETTING_WIRED_S390_OPTIONS,
+ G_VARIANT_TYPE ("a{ss}"),
+ _nm_utils_strdict_to_dbus,
+ _nm_utils_strdict_from_dbus);
+}
diff --git a/libnm-core/nm-setting-wired.h b/libnm-core/nm-setting-wired.h
new file mode 100644
index 000000000..4189b6896
--- /dev/null
+++ b/libnm-core/nm-setting-wired.h
@@ -0,0 +1,109 @@
+/* -*- 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 2007 - 2014 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#ifndef __NM_SETTING_WIRED_H__
+#define __NM_SETTING_WIRED_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_WIRED (nm_setting_wired_get_type ())
+#define NM_SETTING_WIRED(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_WIRED, NMSettingWired))
+#define NM_SETTING_WIRED_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_WIRED, NMSettingWiredClass))
+#define NM_IS_SETTING_WIRED(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_WIRED))
+#define NM_IS_SETTING_WIRED_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_WIRED))
+#define NM_SETTING_WIRED_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_WIRED, NMSettingWiredClass))
+
+#define NM_SETTING_WIRED_SETTING_NAME "802-3-ethernet"
+
+#define NM_SETTING_WIRED_PORT "port"
+#define NM_SETTING_WIRED_SPEED "speed"
+#define NM_SETTING_WIRED_DUPLEX "duplex"
+#define NM_SETTING_WIRED_AUTO_NEGOTIATE "auto-negotiate"
+#define NM_SETTING_WIRED_MAC_ADDRESS "mac-address"
+#define NM_SETTING_WIRED_CLONED_MAC_ADDRESS "cloned-mac-address"
+#define NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST "mac-address-blacklist"
+#define NM_SETTING_WIRED_MTU "mtu"
+#define NM_SETTING_WIRED_S390_SUBCHANNELS "s390-subchannels"
+#define NM_SETTING_WIRED_S390_NETTYPE "s390-nettype"
+#define NM_SETTING_WIRED_S390_OPTIONS "s390-options"
+
+struct _NMSettingWired {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingWiredClass;
+
+GType nm_setting_wired_get_type (void);
+
+NMSetting * nm_setting_wired_new (void);
+const char * nm_setting_wired_get_port (NMSettingWired *setting);
+guint32 nm_setting_wired_get_speed (NMSettingWired *setting);
+const char * nm_setting_wired_get_duplex (NMSettingWired *setting);
+gboolean nm_setting_wired_get_auto_negotiate (NMSettingWired *setting);
+const char * nm_setting_wired_get_mac_address (NMSettingWired *setting);
+const char * nm_setting_wired_get_cloned_mac_address (NMSettingWired *setting);
+
+const char * const *nm_setting_wired_get_mac_address_blacklist (NMSettingWired *setting);
+guint32 nm_setting_wired_get_num_mac_blacklist_items (NMSettingWired *setting);
+const char * nm_setting_wired_get_mac_blacklist_item (NMSettingWired *setting,
+ guint32 idx);
+gboolean nm_setting_wired_add_mac_blacklist_item (NMSettingWired *setting,
+ const char *mac);
+void nm_setting_wired_remove_mac_blacklist_item (NMSettingWired *setting,
+ guint32 idx);
+gboolean nm_setting_wired_remove_mac_blacklist_item_by_value (NMSettingWired *setting,
+ const char *mac);
+void nm_setting_wired_clear_mac_blacklist_items (NMSettingWired *setting);
+
+guint32 nm_setting_wired_get_mtu (NMSettingWired *setting);
+
+const char * const *nm_setting_wired_get_s390_subchannels (NMSettingWired *setting);
+const char * nm_setting_wired_get_s390_nettype (NMSettingWired *setting);
+
+guint32 nm_setting_wired_get_num_s390_options (NMSettingWired *setting);
+gboolean nm_setting_wired_get_s390_option (NMSettingWired *setting,
+ guint32 idx,
+ const char **out_key,
+ const char **out_value);
+const char * nm_setting_wired_get_s390_option_by_key (NMSettingWired *setting,
+ const char *key);
+gboolean nm_setting_wired_add_s390_option (NMSettingWired *setting,
+ const char *key,
+ const char *value);
+gboolean nm_setting_wired_remove_s390_option (NMSettingWired *setting,
+ const char *key);
+const char ** nm_setting_wired_get_valid_s390_options (NMSettingWired *setting);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_WIRED_H__ */
diff --git a/libnm-core/nm-setting-wireless-security.c b/libnm-core/nm-setting-wireless-security.c
new file mode 100644
index 000000000..c95f92435
--- /dev/null
+++ b/libnm-core/nm-setting-wireless-security.c
@@ -0,0 +1,1704 @@
+/* -*- 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 2007 - 2014 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-wireless-security.h"
+#include "nm-setting-8021x.h"
+#include "nm-utils.h"
+#include "nm-utils-private.h"
+#include "nm-setting-private.h"
+#include "nm-setting-wireless.h"
+
+/**
+ * SECTION:nm-setting-wireless-security
+ * @short_description: Describes connection properties for Wi-Fi networks that
+ * use WEP, LEAP, WPA or WPA2/RSN security
+ *
+ * The #NMSettingWirelessSecurity object is a #NMSetting subclass that describes
+ * properties necessary for connection to encrypted Wi-Fi networks.
+ *
+ * It's a good idea to read up on wpa_supplicant configuration before using this
+ * setting extensively, since most of the options here correspond closely with
+ * the relevant wpa_supplicant configuration options. To get a better overview
+ * of how Wi-Fi security works, you may want to get copies of the following books.
+ *
+ * 802.11 Wireless Networks: The Definitive Guide, Second Edition
+ * Author: Matthew Gast
+ * ISBN: 978-0596100520
+ *
+ * Cisco Wireless LAN Security
+ * Authors: Krishna Sankar, Sri Sundaralingam, Darrin Miller, and Andrew Balinsky
+ * ISBN: 978-1587051548
+ **/
+
+G_DEFINE_TYPE_WITH_CODE (NMSettingWirelessSecurity, nm_setting_wireless_security, NM_TYPE_SETTING,
+ _nm_register_setting (WIRELESS_SECURITY, 2))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_WIRELESS_SECURITY)
+
+#define NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIRELESS_SECURITY, NMSettingWirelessSecurityPrivate))
+
+typedef struct {
+ char *key_mgmt;
+ char *auth_alg;
+ GSList *proto; /* GSList of strings */
+ GSList *pairwise; /* GSList of strings */
+ GSList *group; /* GSList of strings */
+
+ /* LEAP */
+ char *leap_username;
+ char *leap_password;
+ NMSettingSecretFlags leap_password_flags;
+
+ /* WEP */
+ char *wep_key0;
+ char *wep_key1;
+ char *wep_key2;
+ char *wep_key3;
+ NMSettingSecretFlags wep_key_flags;
+ NMWepKeyType wep_key_type;
+ guint32 wep_tx_keyidx;
+
+ /* WPA-PSK */
+ char *psk;
+ NMSettingSecretFlags psk_flags;
+} NMSettingWirelessSecurityPrivate;
+
+enum {
+ PROP_0,
+ PROP_KEY_MGMT,
+ PROP_WEP_TX_KEYIDX,
+ PROP_AUTH_ALG,
+ PROP_PROTO,
+ PROP_PAIRWISE,
+ PROP_GROUP,
+ PROP_LEAP_USERNAME,
+ PROP_WEP_KEY0,
+ PROP_WEP_KEY1,
+ PROP_WEP_KEY2,
+ PROP_WEP_KEY3,
+ PROP_WEP_KEY_FLAGS,
+ PROP_WEP_KEY_TYPE,
+ PROP_PSK,
+ PROP_PSK_FLAGS,
+ PROP_LEAP_PASSWORD,
+ PROP_LEAP_PASSWORD_FLAGS,
+
+ LAST_PROP
+};
+
+/**
+ * nm_setting_wireless_security_new:
+ *
+ * Creates a new #NMSettingWirelessSecurity object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingWirelessSecurity object
+ **/
+NMSetting *
+nm_setting_wireless_security_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_WIRELESS_SECURITY, NULL);
+}
+
+/**
+ * nm_setting_wireless_security_get_key_mgmt:
+ * @setting: the #NMSettingWirelessSecurity
+ *
+ * Returns: the #NMSettingWirelessSecurity:key-mgmt property of the setting
+ **/
+const char *
+nm_setting_wireless_security_get_key_mgmt (NMSettingWirelessSecurity *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), NULL);
+
+ return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->key_mgmt;
+}
+
+/**
+ * nm_setting_wireless_security_get_num_protos:
+ * @setting: the #NMSettingWirelessSecurity
+ *
+ * Returns: the number of security protocols this connection allows when
+ * connecting to secure Wi-Fi networks
+ **/
+guint32
+nm_setting_wireless_security_get_num_protos (NMSettingWirelessSecurity *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), 0);
+
+ return g_slist_length (NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->proto);
+}
+
+/**
+ * nm_setting_wireless_security_get_proto:
+ * @setting: the #NMSettingWirelessSecurity
+ * @i: an index into the protocol list
+ *
+ * Returns: the protocol at index @i
+ **/
+const char *
+nm_setting_wireless_security_get_proto (NMSettingWirelessSecurity *setting, guint32 i)
+{
+ NMSettingWirelessSecurityPrivate *priv;
+
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), NULL);
+
+ priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
+ g_return_val_if_fail (i <= g_slist_length (priv->proto), NULL);
+
+ return (const char *) g_slist_nth_data (priv->proto, i);
+}
+
+/**
+ * nm_setting_wireless_security_add_proto:
+ * @setting: the #NMSettingWirelessSecurity
+ * @proto: the protocol to add, one of "wpa" or "rsn"
+ *
+ * Adds a Wi-Fi security protocol (one of "wpa" or "rsn") to the allowed list;
+ * only protocols in this list will be used when finding and connecting to
+ * the Wi-Fi network specified by this connection. For example, if the
+ * protocol list contains only "wpa" but the access point for the SSID specified
+ * by this connection only supports WPA2/RSN, the connection cannot be used
+ * with the access point.
+ *
+ * Returns: %TRUE if the protocol was new and and was added to the allowed
+ * protocol list, or %FALSE if it was already in the list
+ **/
+gboolean
+nm_setting_wireless_security_add_proto (NMSettingWirelessSecurity *setting, const char *proto)
+{
+ NMSettingWirelessSecurityPrivate *priv;
+ GSList *iter;
+
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), FALSE);
+ g_return_val_if_fail (proto != NULL, FALSE);
+
+ priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
+ for (iter = priv->proto; iter; iter = g_slist_next (iter)) {
+ if (strcasecmp (proto, (char *) iter->data) == 0)
+ return FALSE;
+ }
+
+ priv->proto = g_slist_append (priv->proto, g_ascii_strdown (proto, -1));
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_PROTO);
+ return TRUE;
+}
+
+/**
+ * nm_setting_wireless_security_remove_proto:
+ * @setting: the #NMSettingWirelessSecurity
+ * @i: index of the protocol to remove
+ *
+ * Removes a protocol from the allowed protocol list.
+ **/
+void
+nm_setting_wireless_security_remove_proto (NMSettingWirelessSecurity *setting, guint32 i)
+{
+ NMSettingWirelessSecurityPrivate *priv;
+ GSList *elt;
+
+ g_return_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting));
+
+ priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
+ elt = g_slist_nth (priv->proto, i);
+ g_return_if_fail (elt != NULL);
+
+ g_free (elt->data);
+ priv->proto = g_slist_delete_link (priv->proto, elt);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_PROTO);
+}
+
+/**
+ * nm_setting_wireless_security_remove_proto_by_value:
+ * @setting: the #NMSettingWirelessSecurity
+ * @proto: the protocol to remove, one of "wpa" or "rsn"
+ *
+ * Removes a protocol from the allowed protocol list.
+ *
+ * Returns: %TRUE if the protocol was found and removed; %FALSE it it was not.
+ **/
+gboolean
+nm_setting_wireless_security_remove_proto_by_value (NMSettingWirelessSecurity *setting,
+ const char *proto)
+{
+ NMSettingWirelessSecurityPrivate *priv;
+ GSList *iter;
+
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), FALSE);
+ g_return_val_if_fail (proto != NULL, FALSE);
+
+ priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
+ for (iter = priv->proto; iter; iter = g_slist_next (iter)) {
+ if (strcasecmp (proto, (char *) iter->data) == 0) {
+ priv->proto = g_slist_delete_link (priv->proto, iter);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_PROTO);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * nm_setting_wireless_security_clear_protos:
+ * @setting: the #NMSettingWirelessSecurity
+ *
+ * Removes all protocols from the allowed list. If there are no protocols
+ * specified then all protocols are allowed.
+ **/
+void
+nm_setting_wireless_security_clear_protos (NMSettingWirelessSecurity *setting)
+{
+ NMSettingWirelessSecurityPrivate *priv;
+
+ g_return_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting));
+
+ priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
+ g_slist_free_full (priv->proto, g_free);
+ priv->proto = NULL;
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_PROTO);
+}
+
+/**
+ * nm_setting_wireless_security_get_num_pairwise:
+ * @setting: the #NMSettingWirelessSecurity
+ *
+ * Returns: the number of pairwise encryption algorithms in the allowed list
+ **/
+guint32
+nm_setting_wireless_security_get_num_pairwise (NMSettingWirelessSecurity *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), 0);
+
+ return g_slist_length (NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->pairwise);
+}
+
+/**
+ * nm_setting_wireless_security_get_pairwise:
+ * @setting: the #NMSettingWirelessSecurity
+ * @i: index of an item in the allowed pairwise encryption algorithm list
+ *
+ * Returns the allowed pairwise encryption algorithm from allowed algorithm
+ * list.
+ *
+ * Returns: the pairwise encryption algorithm at index @i
+ **/
+const char *
+nm_setting_wireless_security_get_pairwise (NMSettingWirelessSecurity *setting, guint32 i)
+{
+ NMSettingWirelessSecurityPrivate *priv;
+
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), NULL);
+
+ priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
+ g_return_val_if_fail (i <= g_slist_length (priv->pairwise), NULL);
+
+ return (const char *) g_slist_nth_data (priv->pairwise, i);
+}
+
+/**
+ * nm_setting_wireless_security_add_pairwise:
+ * @setting: the #NMSettingWirelessSecurity
+ * @pairwise: the encryption algorithm to add, one of "tkip" or "ccmp"
+ *
+ * Adds an encryption algorithm to the list of allowed pairwise encryption
+ * algorithms. If the list is not empty, then only access points that support
+ * one or more of the encryption algorithms in the list will be considered
+ * compatible with this connection.
+ *
+ * Returns: %TRUE if the algorithm was added to the list, %FALSE if it was
+ * already in the list
+ **/
+gboolean
+nm_setting_wireless_security_add_pairwise (NMSettingWirelessSecurity *setting, const char *pairwise)
+{
+ NMSettingWirelessSecurityPrivate *priv;
+ GSList *iter;
+
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), FALSE);
+ g_return_val_if_fail (pairwise != NULL, FALSE);
+
+ priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
+ for (iter = priv->pairwise; iter; iter = g_slist_next (iter)) {
+ if (strcasecmp (pairwise, (char *) iter->data) == 0)
+ return FALSE;
+ }
+
+ priv->pairwise = g_slist_append (priv->pairwise, g_ascii_strdown (pairwise, -1));
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_PAIRWISE);
+ return TRUE;
+}
+
+/**
+ * nm_setting_wireless_security_remove_pairwise:
+ * @setting: the #NMSettingWirelessSecurity
+ * @i: the index of an item in the allowed pairwise encryption algorithm list
+ *
+ * Removes an encryption algorithm from the allowed pairwise encryption
+ * algorithm list.
+ **/
+void
+nm_setting_wireless_security_remove_pairwise (NMSettingWirelessSecurity *setting, guint32 i)
+{
+ NMSettingWirelessSecurityPrivate *priv;
+ GSList *elt;
+
+ g_return_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting));
+
+ priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
+ elt = g_slist_nth (priv->pairwise, i);
+ g_return_if_fail (elt != NULL);
+
+ g_free (elt->data);
+ priv->pairwise = g_slist_delete_link (priv->pairwise, elt);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_PAIRWISE);
+}
+
+/**
+ * nm_setting_wireless_security_remove_pairwise_by_value:
+ * @setting: the #NMSettingWirelessSecurity
+ * @pairwise: the encryption algorithm to remove, one of "tkip" or "ccmp"
+ *
+ * Removes an encryption algorithm from the allowed pairwise encryption
+ * algorithm list.
+ *
+ * Returns: %TRUE if the encryption algorith was found and removed; %FALSE it it was not.
+ **/
+gboolean
+nm_setting_wireless_security_remove_pairwise_by_value (NMSettingWirelessSecurity *setting,
+ const char *pairwise)
+{
+ NMSettingWirelessSecurityPrivate *priv;
+ GSList *iter;
+
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), FALSE);
+ g_return_val_if_fail (pairwise != NULL, FALSE);
+
+ priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
+ for (iter = priv->pairwise; iter; iter = g_slist_next (iter)) {
+ if (strcasecmp (pairwise, (char *) iter->data) == 0) {
+ priv->pairwise = g_slist_delete_link (priv->pairwise, iter);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_PAIRWISE);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * nm_setting_wireless_security_clear_pairwise:
+ * @setting: the #NMSettingWirelessSecurity
+ *
+ * Removes all algorithms from the allowed list. If there are no algorithms
+ * specified then all pairwise encryption algorithms are allowed.
+ **/
+void
+nm_setting_wireless_security_clear_pairwise (NMSettingWirelessSecurity *setting)
+{
+ NMSettingWirelessSecurityPrivate *priv;
+
+ g_return_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting));
+
+ priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
+ g_slist_free_full (priv->pairwise, g_free);
+ priv->pairwise = NULL;
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_PAIRWISE);
+}
+
+/**
+ * nm_setting_wireless_security_get_num_groups:
+ * @setting: the #NMSettingWirelessSecurity
+ *
+ * Returns: the number of groupwise encryption algorithms in the allowed list
+ **/
+guint32
+nm_setting_wireless_security_get_num_groups (NMSettingWirelessSecurity *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), 0);
+
+ return g_slist_length (NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->group);
+}
+
+/**
+ * nm_setting_wireless_security_get_group:
+ * @setting: the #NMSettingWirelessSecurity
+ * @i: index of an item in the allowed groupwise encryption algorithm list
+ *
+ * Returns the allowed groupwise encryption algorithm from allowed algorithm
+ * list.
+ *
+ * Returns: the groupwise encryption algorithm at index @i
+ **/
+const char *
+nm_setting_wireless_security_get_group (NMSettingWirelessSecurity *setting, guint32 i)
+{
+ NMSettingWirelessSecurityPrivate *priv;
+
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), NULL);
+
+ priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
+ g_return_val_if_fail (i <= g_slist_length (priv->group), NULL);
+
+ return (const char *) g_slist_nth_data (priv->group, i);
+}
+
+/**
+ * nm_setting_wireless_security_add_group:
+ * @setting: the #NMSettingWirelessSecurity
+ * @group: the encryption algorithm to add, one of "wep40", "wep104",
+ * "tkip", or "ccmp"
+ *
+ * Adds an encryption algorithm to the list of allowed groupwise encryption
+ * algorithms. If the list is not empty, then only access points that support
+ * one or more of the encryption algorithms in the list will be considered
+ * compatible with this connection.
+ *
+ * Returns: %TRUE if the algorithm was added to the list, %FALSE if it was
+ * already in the list
+ **/
+gboolean
+nm_setting_wireless_security_add_group (NMSettingWirelessSecurity *setting, const char *group)
+{
+ NMSettingWirelessSecurityPrivate *priv;
+ GSList *iter;
+
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), FALSE);
+ g_return_val_if_fail (group != NULL, FALSE);
+
+ priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
+ for (iter = priv->group; iter; iter = g_slist_next (iter)) {
+ if (strcasecmp (group, (char *) iter->data) == 0)
+ return FALSE;
+ }
+
+ priv->group = g_slist_append (priv->group, g_ascii_strdown (group, -1));
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_GROUP);
+ return TRUE;
+}
+
+/**
+ * nm_setting_wireless_security_remove_group:
+ * @setting: the #NMSettingWirelessSecurity
+ * @i: the index of an item in the allowed groupwise encryption algorithm list
+ *
+ * Removes an encryption algorithm from the allowed groupwise encryption
+ * algorithm list.
+ **/
+void
+nm_setting_wireless_security_remove_group (NMSettingWirelessSecurity *setting, guint32 i)
+{
+ NMSettingWirelessSecurityPrivate *priv;
+ GSList *elt;
+
+ g_return_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting));
+
+ priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
+ elt = g_slist_nth (priv->group, i);
+ g_return_if_fail (elt != NULL);
+
+ g_free (elt->data);
+ priv->group = g_slist_delete_link (priv->group, elt);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_GROUP);
+}
+
+/**
+ * nm_setting_wireless_security_remove_group_by_value:
+ * @setting: the #NMSettingWirelessSecurity
+ * @group: the encryption algorithm to remove, one of "wep40", "wep104",
+ * "tkip", or "ccmp"
+ *
+ * Removes an encryption algorithm from the allowed groupwise encryption
+ * algorithm list.
+ *
+ * Returns: %TRUE if the algorithm was found and removed; %FALSE it it was not.
+ **/
+gboolean
+nm_setting_wireless_security_remove_group_by_value (NMSettingWirelessSecurity *setting,
+ const char *group)
+{
+ NMSettingWirelessSecurityPrivate *priv;
+ GSList *iter;
+
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), FALSE);
+ g_return_val_if_fail (group != NULL, FALSE);
+
+ priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
+ for (iter = priv->group; iter; iter = g_slist_next (iter)) {
+ if (strcasecmp (group, (char *) iter->data) == 0) {
+ priv->group = g_slist_delete_link (priv->group, iter);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_GROUP);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * nm_setting_wireless_security_clear_groups:
+ * @setting: the #NMSettingWirelessSecurity
+ *
+ * Removes all algorithms from the allowed list. If there are no algorithms
+ * specified then all groupwise encryption algorithms are allowed.
+ **/
+void
+nm_setting_wireless_security_clear_groups (NMSettingWirelessSecurity *setting)
+{
+ NMSettingWirelessSecurityPrivate *priv;
+
+ g_return_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting));
+
+ priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
+ g_slist_free_full (priv->group, g_free);
+ priv->group = NULL;
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_GROUP);
+}
+
+/**
+ * nm_setting_wireless_security_get_psk:
+ * @setting: the #NMSettingWirelessSecurity
+ *
+ * Returns: the #NMSettingWirelessSecurity:psk property of the setting
+ **/
+const char *
+nm_setting_wireless_security_get_psk (NMSettingWirelessSecurity *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), NULL);
+
+ return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->psk;
+}
+
+/**
+ * nm_setting_wireless_security_get_psk_flags:
+ * @setting: the #NMSettingWirelessSecurity
+ *
+ * Returns: the #NMSettingSecretFlags pertaining to the
+ * #NMSettingWirelessSecurity:psk
+ **/
+NMSettingSecretFlags
+nm_setting_wireless_security_get_psk_flags (NMSettingWirelessSecurity *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), NM_SETTING_SECRET_FLAG_NONE);
+
+ return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->psk_flags;
+}
+
+/**
+ * nm_setting_wireless_security_get_leap_username:
+ * @setting: the #NMSettingWirelessSecurity
+ *
+ * Returns: the #NMSettingWirelessSecurity:leap-username property of the setting
+ **/
+const char *
+nm_setting_wireless_security_get_leap_username (NMSettingWirelessSecurity *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), NULL);
+
+ return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->leap_username;
+}
+
+/**
+ * nm_setting_wireless_security_get_leap_password:
+ * @setting: the #NMSettingWirelessSecurity
+ *
+ * Returns: the #NMSettingWirelessSecurity:leap-password property of the setting
+ **/
+const char *
+nm_setting_wireless_security_get_leap_password (NMSettingWirelessSecurity *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), NULL);
+
+ return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->leap_password;
+}
+
+/**
+ * nm_setting_wireless_security_get_leap_password_flags:
+ * @setting: the #NMSettingWirelessSecurity
+ *
+ * Returns: the #NMSettingSecretFlags pertaining to the
+ * #NMSettingWirelessSecurity:leap-password
+ **/
+NMSettingSecretFlags
+nm_setting_wireless_security_get_leap_password_flags (NMSettingWirelessSecurity *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), NM_SETTING_SECRET_FLAG_NONE);
+
+ return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->leap_password_flags;
+}
+
+/**
+ * nm_setting_wireless_security_get_wep_key:
+ * @setting: the #NMSettingWirelessSecurity
+ * @idx: the WEP key index (0..3 inclusive)
+ *
+ * Returns: the WEP key at the given index
+ **/
+const char *
+nm_setting_wireless_security_get_wep_key (NMSettingWirelessSecurity *setting, guint32 idx)
+{
+ NMSettingWirelessSecurityPrivate *priv;
+
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), NULL);
+ g_return_val_if_fail (idx < 4, NULL);
+
+ priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
+ if (idx == 0)
+ return priv->wep_key0;
+ else if (idx == 1)
+ return priv->wep_key1;
+ else if (idx == 2)
+ return priv->wep_key2;
+ else if (idx == 3)
+ return priv->wep_key3;
+
+ g_assert_not_reached ();
+ return NULL;
+}
+
+/**
+ * nm_setting_wireless_security_set_wep_key:
+ * @setting: the #NMSettingWirelessSecurity
+ * @idx: the index of the key (0..3 inclusive)
+ * @key: the WEP key as a string, in either hexadecimal, ASCII, or passphrase
+ * form as determiend by the value of the #NMSettingWirelessSecurity:wep-key-type
+ * property.
+ *
+ * Sets a WEP key in the given index.
+ **/
+void
+nm_setting_wireless_security_set_wep_key (NMSettingWirelessSecurity *setting, guint32 idx, const char *key)
+{
+ NMSettingWirelessSecurityPrivate *priv;
+
+ g_return_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting));
+ g_return_if_fail (idx < 4);
+
+ priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
+ switch (idx) {
+ case 0:
+ g_free (priv->wep_key0);
+ priv->wep_key0 = g_strdup (key);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
+ break;
+ case 1:
+ g_free (priv->wep_key1);
+ priv->wep_key1 = g_strdup (key);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_WEP_KEY1);
+ break;
+ case 2:
+ g_free (priv->wep_key2);
+ priv->wep_key2 = g_strdup (key);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_WEP_KEY2);
+ break;
+ case 3:
+ g_free (priv->wep_key3);
+ priv->wep_key3 = g_strdup (key);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SECURITY_WEP_KEY3);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+/**
+ * nm_setting_wireless_security_get_wep_tx_keyidx:
+ * @setting: the #NMSettingWirelessSecurity
+ *
+ * Returns: the #NMSettingWirelessSecurity:wep-tx-keyidx property of the setting
+ **/
+guint32
+nm_setting_wireless_security_get_wep_tx_keyidx (NMSettingWirelessSecurity *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), 0);
+
+ return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->wep_tx_keyidx;
+}
+
+/**
+ * nm_setting_wireless_security_get_auth_alg:
+ * @setting: the #NMSettingWirelessSecurity
+ *
+ * Returns: the #NMSettingWirelessSecurity:auth-alg property of the setting
+ **/
+const char *
+nm_setting_wireless_security_get_auth_alg (NMSettingWirelessSecurity *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), NULL);
+
+ return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->auth_alg;
+}
+
+/**
+ * nm_setting_wireless_security_get_wep_key_flags:
+ * @setting: the #NMSettingWirelessSecurity
+ *
+ * Returns: the #NMSettingSecretFlags pertaining to the all WEP keys
+ **/
+NMSettingSecretFlags
+nm_setting_wireless_security_get_wep_key_flags (NMSettingWirelessSecurity *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), NM_SETTING_SECRET_FLAG_NONE);
+
+ return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->wep_key_flags;
+}
+
+/**
+ * nm_setting_wireless_security_get_wep_key_type:
+ * @setting: the #NMSettingWirelessSecurity
+ *
+ * Returns: the #NMSettingWirelessSecurity:wep-key-type property of the setting
+ **/
+NMWepKeyType
+nm_setting_wireless_security_get_wep_key_type (NMSettingWirelessSecurity *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS_SECURITY (setting), 0);
+
+ return NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting)->wep_key_type;
+}
+
+static GPtrArray *
+need_secrets (NMSetting *setting)
+{
+ NMSettingWirelessSecurity *self = NM_SETTING_WIRELESS_SECURITY (setting);
+ NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (self);
+ GPtrArray *secrets;
+
+ secrets = g_ptr_array_sized_new (4);
+
+ g_assert (priv->key_mgmt);
+
+ /* Static WEP */
+ if (strcmp (priv->key_mgmt, "none") == 0) {
+ if ((priv->wep_tx_keyidx == 0) && !nm_utils_wep_key_valid (priv->wep_key0, priv->wep_key_type)) {
+ g_ptr_array_add (secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
+ return secrets;
+ }
+ if ((priv->wep_tx_keyidx == 1) && !nm_utils_wep_key_valid (priv->wep_key1, priv->wep_key_type)) {
+ g_ptr_array_add (secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY1);
+ return secrets;
+ }
+ if ((priv->wep_tx_keyidx == 2) && !nm_utils_wep_key_valid (priv->wep_key2, priv->wep_key_type)) {
+ g_ptr_array_add (secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY2);
+ return secrets;
+ }
+ if ((priv->wep_tx_keyidx == 3) && !nm_utils_wep_key_valid (priv->wep_key3, priv->wep_key_type)) {
+ g_ptr_array_add (secrets, NM_SETTING_WIRELESS_SECURITY_WEP_KEY3);
+ return secrets;
+ }
+ goto no_secrets;
+ }
+
+ /* WPA-PSK infrastructure and adhoc */
+ if ( (strcmp (priv->key_mgmt, "wpa-none") == 0)
+ || (strcmp (priv->key_mgmt, "wpa-psk") == 0)) {
+ if (!nm_utils_wpa_psk_valid (priv->psk)) {
+ g_ptr_array_add (secrets, NM_SETTING_WIRELESS_SECURITY_PSK);
+ return secrets;
+ }
+ goto no_secrets;
+ }
+
+ /* LEAP */
+ if ( priv->auth_alg
+ && !strcmp (priv->auth_alg, "leap")
+ && !strcmp (priv->key_mgmt, "ieee8021x")) {
+ if (!priv->leap_password || !strlen (priv->leap_password)) {
+ g_ptr_array_add (secrets, NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD);
+ return secrets;
+ }
+ goto no_secrets;
+ }
+
+ if ( (strcmp (priv->key_mgmt, "ieee8021x") == 0)
+ || (strcmp (priv->key_mgmt, "wpa-eap") == 0)) {
+ /* Let caller check the 802.1x setting for secrets */
+ goto no_secrets;
+ }
+
+ g_assert_not_reached ();
+ return secrets;
+
+no_secrets:
+ if (secrets)
+ g_ptr_array_free (secrets, TRUE);
+ return NULL;
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ NMSettingWirelessSecurity *self = NM_SETTING_WIRELESS_SECURITY (setting);
+ NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (self);
+ const char *valid_key_mgmt[] = { "none", "ieee8021x", "wpa-none", "wpa-psk", "wpa-eap", NULL };
+ const char *valid_auth_algs[] = { "open", "shared", "leap", NULL };
+ const char *valid_protos[] = { "wpa", "rsn", NULL };
+ const char *valid_pairwise[] = { "tkip", "ccmp", NULL };
+ const char *valid_groups[] = { "wep40", "wep104", "tkip", "ccmp", NULL };
+
+ if (!priv->key_mgmt) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
+ return FALSE;
+ }
+
+ if (!_nm_utils_string_in_list (priv->key_mgmt, valid_key_mgmt)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid value for the property"),
+ priv->key_mgmt);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
+ return FALSE;
+ }
+
+ if (priv->auth_alg && !strcmp (priv->auth_alg, "leap")) {
+ /* LEAP must use ieee8021x key management */
+ if (strcmp (priv->key_mgmt, "ieee8021x")) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' security requires '%s=%s'"),
+ "leap", NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x");
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_AUTH_ALG);
+ return FALSE;
+ }
+ if (!priv->leap_username) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME);
+ return FALSE;
+ }
+ if (priv->leap_password && !strlen (priv->leap_password)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD);
+ return FALSE;
+ }
+ } else {
+ if ( (strcmp (priv->key_mgmt, "ieee8021x") == 0)
+ || (strcmp (priv->key_mgmt, "wpa-eap") == 0)) {
+ /* Need an 802.1x setting too */
+ if (connection && !nm_connection_get_setting_802_1x (connection)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_SETTING,
+ _("'%s' security requires '%s' setting presence"),
+ priv->key_mgmt, NM_SETTING_802_1X_SETTING_NAME);
+ g_prefix_error (error, "%s: ", NM_SETTING_802_1X_SETTING_NAME);
+ return FALSE;
+ }
+ }
+ }
+
+ if (priv->leap_username && !strlen (priv->leap_username)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is empty"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME);
+ return FALSE;
+ }
+
+ if (priv->wep_tx_keyidx > 3) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%d' value is out of range <0-3>"),
+ priv->wep_tx_keyidx);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX);
+ return FALSE;
+ }
+
+ if (priv->wep_key_type > NM_WEP_KEY_TYPE_LAST) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE);
+ return FALSE;
+ }
+
+ if (priv->wep_key0 && !nm_utils_wep_key_valid (priv->wep_key0, priv->wep_key_type)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
+ return FALSE;
+ }
+ if (priv->wep_key1 && !nm_utils_wep_key_valid (priv->wep_key1, priv->wep_key_type)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_WEP_KEY1);
+ return FALSE;
+ }
+ if (priv->wep_key2 && !nm_utils_wep_key_valid (priv->wep_key2, priv->wep_key_type)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_WEP_KEY2);
+ return FALSE;
+ }
+ if (priv->wep_key3 && !nm_utils_wep_key_valid (priv->wep_key3, priv->wep_key_type)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_WEP_KEY3);
+ return FALSE;
+ }
+
+ if (priv->auth_alg && !_nm_utils_string_in_list (priv->auth_alg, valid_auth_algs)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_AUTH_ALG);
+ return FALSE;
+ }
+
+ if (priv->psk && !nm_utils_wpa_psk_valid (priv->psk)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_PSK);
+ return FALSE;
+ }
+
+ if (priv->proto && !_nm_utils_string_slist_validate (priv->proto, valid_protos)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_PROTO);
+ return FALSE;
+ }
+
+ if (priv->pairwise) {
+ const char *wpa_none[] = { "wpa-none", NULL };
+
+ /* For ad-hoc connections, pairwise must be "none" */
+ if (_nm_utils_string_in_list (priv->key_mgmt, wpa_none)) {
+ GSList *iter;
+ gboolean found = FALSE;
+
+ for (iter = priv->pairwise; iter; iter = g_slist_next (iter)) {
+ if (!strcmp ((char *) iter->data, "none")) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ /* pairwise cipher list didn't contain "none", which is invalid
+ * for WPA adhoc connections.
+ */
+ if (!found) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' connections require '%s' in this property"),
+ NM_SETTING_WIRELESS_MODE_ADHOC, "none");
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_PAIRWISE);
+ return FALSE;
+ }
+ } else if (!_nm_utils_string_slist_validate (priv->pairwise, valid_pairwise)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_PAIRWISE);
+ return FALSE;
+ }
+ }
+
+ if (priv->group && !_nm_utils_string_slist_validate (priv->group, valid_groups)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_GROUP);
+ return FALSE;
+ }
+
+ /* Shared Key auth can only be used with WEP */
+ if (priv->auth_alg && !strcmp (priv->auth_alg, "shared")) {
+ if (priv->key_mgmt && strcmp (priv->key_mgmt, "none")) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' can only be used with '%s=%s' (WEP)"),
+ "shared", NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none");
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, NM_SETTING_WIRELESS_SECURITY_AUTH_ALG);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static gboolean
+get_secret_flags (NMSetting *setting,
+ const char *secret_name,
+ gboolean verify_secret,
+ NMSettingSecretFlags *out_flags,
+ GError **error)
+{
+ NMSettingClass *setting_class;
+ gboolean verify_override = verify_secret;
+
+ /* There's only one 'flags' property for WEP keys, so alias all the WEP key
+ * property names to that flags property.
+ */
+ if ( !g_strcmp0 (secret_name, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0)
+ || !g_strcmp0 (secret_name, NM_SETTING_WIRELESS_SECURITY_WEP_KEY1)
+ || !g_strcmp0 (secret_name, NM_SETTING_WIRELESS_SECURITY_WEP_KEY2)
+ || !g_strcmp0 (secret_name, NM_SETTING_WIRELESS_SECURITY_WEP_KEY3)) {
+ secret_name = "wep-key";
+ verify_override = FALSE; /* Already know it's a secret */
+ }
+
+ /* Chain up to superclass with modified key name */
+ setting_class = NM_SETTING_CLASS (nm_setting_wireless_security_parent_class);
+ return setting_class->get_secret_flags (setting, secret_name, verify_override, out_flags, error);
+}
+
+static gboolean
+set_secret_flags (NMSetting *setting,
+ const char *secret_name,
+ gboolean verify_secret,
+ NMSettingSecretFlags flags,
+ GError **error)
+{
+ NMSettingClass *setting_class;
+ gboolean verify_override = verify_secret;
+
+ /* There's only one 'flags' property for WEP keys, so alias all the WEP key
+ * property names to that flags property.
+ */
+ if ( !g_strcmp0 (secret_name, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0)
+ || !g_strcmp0 (secret_name, NM_SETTING_WIRELESS_SECURITY_WEP_KEY1)
+ || !g_strcmp0 (secret_name, NM_SETTING_WIRELESS_SECURITY_WEP_KEY2)
+ || !g_strcmp0 (secret_name, NM_SETTING_WIRELESS_SECURITY_WEP_KEY3)) {
+ secret_name = "wep-key";
+ verify_override = FALSE; /* Already know it's a secret */
+ }
+
+ /* Chain up to superclass with modified key name */
+ setting_class = NM_SETTING_CLASS (nm_setting_wireless_security_parent_class);
+ return setting_class->set_secret_flags (setting, secret_name, verify_override, flags, error);
+}
+
+static void
+nm_setting_wireless_security_init (NMSettingWirelessSecurity *setting)
+{
+}
+
+static void
+finalize (GObject *object)
+{
+ NMSettingWirelessSecurity *self = NM_SETTING_WIRELESS_SECURITY (object);
+ NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (self);
+
+ /* Strings first. g_free() already checks for NULLs so we don't have to */
+
+ g_free (priv->key_mgmt);
+ g_free (priv->auth_alg);
+ g_free (priv->leap_username);
+ g_free (priv->wep_key0);
+ g_free (priv->wep_key1);
+ g_free (priv->wep_key2);
+ g_free (priv->wep_key3);
+ g_free (priv->psk);
+ g_free (priv->leap_password);
+
+ g_slist_free_full (priv->proto, g_free);
+ g_slist_free_full (priv->pairwise, g_free);
+ g_slist_free_full (priv->group, g_free);
+
+ G_OBJECT_CLASS (nm_setting_wireless_security_parent_class)->finalize (object);
+}
+
+/* NMSettingWirelessSecurity:wep-key-type is an enum, but needs to be marshalled
+ * as 'u', not 'i', for backward-compatibility.
+ */
+static GVariant *
+wep_key_type_to_dbus (const GValue *from)
+{
+ return g_variant_new_uint32 (g_value_get_enum (from));
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingWirelessSecurity *setting = NM_SETTING_WIRELESS_SECURITY (object);
+ NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
+ const char *str;
+
+ switch (prop_id) {
+ case PROP_KEY_MGMT:
+ g_free (priv->key_mgmt);
+ str = g_value_get_string (value);
+ priv->key_mgmt = str ? g_ascii_strdown (str, -1) : NULL;
+ break;
+ case PROP_WEP_TX_KEYIDX:
+ priv->wep_tx_keyidx = g_value_get_uint (value);
+ break;
+ case PROP_AUTH_ALG:
+ g_free (priv->auth_alg);
+ str = g_value_get_string (value);
+ priv->auth_alg = str ? g_ascii_strdown (str, -1) : NULL;
+ break;
+ case PROP_PROTO:
+ g_slist_free_full (priv->proto, g_free);
+ priv->proto = _nm_utils_strv_to_slist (g_value_get_boxed (value));
+ break;
+ case PROP_PAIRWISE:
+ g_slist_free_full (priv->pairwise, g_free);
+ priv->pairwise = _nm_utils_strv_to_slist (g_value_get_boxed (value));
+ break;
+ case PROP_GROUP:
+ g_slist_free_full (priv->group, g_free);
+ priv->group = _nm_utils_strv_to_slist (g_value_get_boxed (value));
+ break;
+ case PROP_LEAP_USERNAME:
+ g_free (priv->leap_username);
+ priv->leap_username = g_value_dup_string (value);
+ break;
+ case PROP_WEP_KEY0:
+ g_free (priv->wep_key0);
+ priv->wep_key0 = g_value_dup_string (value);
+ break;
+ case PROP_WEP_KEY1:
+ g_free (priv->wep_key1);
+ priv->wep_key1 = g_value_dup_string (value);
+ break;
+ case PROP_WEP_KEY2:
+ g_free (priv->wep_key2);
+ priv->wep_key2 = g_value_dup_string (value);
+ break;
+ case PROP_WEP_KEY3:
+ g_free (priv->wep_key3);
+ priv->wep_key3 = g_value_dup_string (value);
+ break;
+ case PROP_WEP_KEY_FLAGS:
+ priv->wep_key_flags = g_value_get_flags (value);
+ break;
+ case PROP_PSK:
+ g_free (priv->psk);
+ priv->psk = g_value_dup_string (value);
+ break;
+ case PROP_PSK_FLAGS:
+ priv->psk_flags = g_value_get_flags (value);
+ break;
+ case PROP_LEAP_PASSWORD:
+ g_free (priv->leap_password);
+ priv->leap_password = g_value_dup_string (value);
+ break;
+ case PROP_LEAP_PASSWORD_FLAGS:
+ priv->leap_password_flags = g_value_get_flags (value);
+ break;
+ case PROP_WEP_KEY_TYPE:
+ priv->wep_key_type = 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)
+{
+ NMSettingWirelessSecurity *setting = NM_SETTING_WIRELESS_SECURITY (object);
+ NMSettingWirelessSecurityPrivate *priv = NM_SETTING_WIRELESS_SECURITY_GET_PRIVATE (setting);
+
+ switch (prop_id) {
+ case PROP_KEY_MGMT:
+ g_value_set_string (value, priv->key_mgmt);
+ break;
+ case PROP_WEP_TX_KEYIDX:
+ g_value_set_uint (value, priv->wep_tx_keyidx);
+ break;
+ case PROP_AUTH_ALG:
+ g_value_set_string (value, priv->auth_alg);
+ break;
+ case PROP_PROTO:
+ g_value_take_boxed (value, _nm_utils_slist_to_strv (priv->proto));
+ break;
+ case PROP_PAIRWISE:
+ g_value_take_boxed (value, _nm_utils_slist_to_strv (priv->pairwise));
+ break;
+ case PROP_GROUP:
+ g_value_take_boxed (value, _nm_utils_slist_to_strv (priv->group));
+ break;
+ case PROP_LEAP_USERNAME:
+ g_value_set_string (value, priv->leap_username);
+ break;
+ case PROP_WEP_KEY0:
+ g_value_set_string (value, priv->wep_key0);
+ break;
+ case PROP_WEP_KEY1:
+ g_value_set_string (value, priv->wep_key1);
+ break;
+ case PROP_WEP_KEY2:
+ g_value_set_string (value, priv->wep_key2);
+ break;
+ case PROP_WEP_KEY3:
+ g_value_set_string (value, priv->wep_key3);
+ break;
+ case PROP_WEP_KEY_FLAGS:
+ g_value_set_flags (value, priv->wep_key_flags);
+ break;
+ case PROP_PSK:
+ g_value_set_string (value, priv->psk);
+ break;
+ case PROP_PSK_FLAGS:
+ g_value_set_flags (value, priv->psk_flags);
+ break;
+ case PROP_LEAP_PASSWORD:
+ g_value_set_string (value, priv->leap_password);
+ break;
+ case PROP_LEAP_PASSWORD_FLAGS:
+ g_value_set_flags (value, priv->leap_password_flags);
+ break;
+ case PROP_WEP_KEY_TYPE:
+ g_value_set_enum (value, priv->wep_key_type);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_setting_wireless_security_class_init (NMSettingWirelessSecurityClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+ NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+ g_type_class_add_private (setting_class, 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->need_secrets = need_secrets;
+ parent_class->get_secret_flags = get_secret_flags;
+ parent_class->set_secret_flags = set_secret_flags;
+
+ /* Properties */
+ /**
+ * NMSettingWirelessSecurity:key-mgmt:
+ *
+ * Key management used for the connection. One of "none" (WEP), "ieee8021x"
+ * (Dynamic WEP), "wpa-none" (Ad-Hoc WPA-PSK), "wpa-psk" (infrastructure
+ * WPA-PSK), or "wpa-eap" (WPA-Enterprise). This property must be set for
+ * any Wi-Fi connection that uses security.
+ **/
+ /* ---ifcfg-rh---
+ * property: key-mgmt
+ * variable: KEY_MGMT(+)
+ * values: IEEE8021X, WPA-PSK, WPA-EAP
+ * description: Key management menthod.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_KEY_MGMT,
+ g_param_spec_string (NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_REQUIRED |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWirelessSecurity:wep-tx-keyidx:
+ *
+ * When static WEP is used (ie, key-mgmt = "none") and a non-default WEP key
+ * index is used by the AP, put that WEP key index here. Valid values are 0
+ * (default key) through 3. Note that some consumer access points (like the
+ * Linksys WRT54G) number the keys 1 - 4.
+ **/
+ /* ---ifcfg-rh---
+ * property: wep-tx-keyidx
+ * variable: DEFAULTKEY
+ * values: 1, 2, 3, 4
+ * default: 1
+ * description: Index of active WEP key.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_WEP_TX_KEYIDX,
+ g_param_spec_uint (NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, "", "",
+ 0, 3, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWirelessSecurity:auth-alg:
+ *
+ * When WEP is used (ie, key-mgmt = "none" or "ieee8021x") indicate the
+ * 802.11 authentication algorithm required by the AP here. One of "open"
+ * for Open System, "shared" for Shared Key, or "leap" for Cisco LEAP. When
+ * using Cisco LEAP (ie, key-mgmt = "ieee8021x" and auth-alg = "leap") the
+ * "leap-username" and "leap-password" properties must be specified.
+ **/
+ /* ---ifcfg-rh---
+ * property: auth-alg
+ * variable: SECURITYMODE(+)
+ * values: restricted, open, leap
+ * description: Authentication algorithm for WEP.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_AUTH_ALG,
+ g_param_spec_string (NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWirelessSecurity:proto:
+ *
+ * List of strings specifying the allowed WPA protocol versions to use.
+ * Each element may be one "wpa" (allow WPA) or "rsn" (allow WPA2/RSN). If
+ * not specified, both WPA and RSN connections are allowed.
+ **/
+ /* ---ifcfg-rh---
+ * property: proto
+ * variable: WPA_ALLOW_WPA(+), WPA_ALLOW_WPA2(+)
+ * values: yes, no
+ * default: no
+ * description: Allowed WPA protocols, WPA and WPA2 (RSN).
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_PROTO,
+ g_param_spec_boxed (NM_SETTING_WIRELESS_SECURITY_PROTO, "", "",
+ G_TYPE_STRV,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWirelessSecurity:pairwise:
+ *
+ * A list of pairwise encryption algorithms which prevents connections to
+ * Wi-Fi networks that do not utilize one of the algorithms in the list.
+ * For maximum compatibility leave this property empty. Each list element
+ * may be one of "tkip" or "ccmp".
+ **/
+ /* ---ifcfg-rh---
+ * property: pairwise
+ * variable: CIPHER_PAIRWISE(+)
+ * values: CCMP, TKIP
+ * description: Restrict pairwise encryption algorithms, specified as a space
+ * separated list.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_PAIRWISE,
+ g_param_spec_boxed (NM_SETTING_WIRELESS_SECURITY_PAIRWISE, "", "",
+ G_TYPE_STRV,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWirelessSecurity:group:
+ *
+ * A list of group/broadcast encryption algorithms which prevents
+ * connections to Wi-Fi networks that do not utilize one of the algorithms
+ * in the list. For maximum compatibility leave this property empty. Each
+ * list element may be one of "wep40", "wep104", "tkip", or "ccmp".
+ **/
+ /* ---ifcfg-rh---
+ * property: group
+ * variable: CIPHER_GROUP(+)
+ * values: CCMP, TKIP, WEP40, WEP104
+ * description: Restrict group/broadcast encryption algorithms, specified as a space
+ * separated list.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_GROUP,
+ g_param_spec_boxed (NM_SETTING_WIRELESS_SECURITY_GROUP, "", "",
+ G_TYPE_STRV,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWirelessSecurity:leap-username:
+ *
+ * The login username for legacy LEAP connections (ie, key-mgmt =
+ * "ieee8021x" and auth-alg = "leap").
+ **/
+ /* ---ifcfg-rh---
+ * property: leap-username
+ * variable: IEEE_8021X_IDENTITY(+)
+ * description: Login name for LEAP.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_LEAP_USERNAME,
+ g_param_spec_string (NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWirelessSecurity:wep-key0:
+ *
+ * Index 0 WEP key. This is the WEP key used in most networks. See the
+ * "wep-key-type" property for a description of how this key is interpreted.
+ **/
+ /* ---ifcfg-rh---
+ * property: wep-key0
+ * variable: KEY1, KEY_PASSPHRASE1(+)
+ * description: The first WEP key (used in most networks). See also DEFAULTKEY for key index.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_WEP_KEY0,
+ g_param_spec_string (NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_SECRET |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWirelessSecurity:wep-key1:
+ *
+ * Index 1 WEP key. This WEP index is not used by most networks. See the
+ * "wep-key-type" property for a description of how this key is interpreted.
+ **/
+ /* ---ifcfg-rh---
+ * property: wep-key1
+ * variable: KEY2, KEY_PASSPHRASE2(+)
+ * description: WEP key with index 1. See also DEFAULTKEY for key index.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_WEP_KEY1,
+ g_param_spec_string (NM_SETTING_WIRELESS_SECURITY_WEP_KEY1, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_SECRET |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWirelessSecurity:wep-key2:
+ *
+ * Index 2 WEP key. This WEP index is not used by most networks. See the
+ * "wep-key-type" property for a description of how this key is interpreted.
+ **/
+ /* ---ifcfg-rh---
+ * property: wep-key2
+ * variable: KEY3, KEY_PASSPHRASE3(+)
+ * description: WEP key with index 2. See also DEFAULTKEY for key index.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_WEP_KEY2,
+ g_param_spec_string (NM_SETTING_WIRELESS_SECURITY_WEP_KEY2, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_SECRET |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWirelessSecurity:wep-key3:
+ *
+ * Index 3 WEP key. This WEP index is not used by most networks. See the
+ * "wep-key-type" property for a description of how this key is interpreted.
+ **/
+ /* ---ifcfg-rh---
+ * property: wep-key3
+ * variable: KEY4, KEY_PASSPHRASE4(+)
+ * description: WEP key with index 3. See also DEFAULTKEY for key index.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_WEP_KEY3,
+ g_param_spec_string (NM_SETTING_WIRELESS_SECURITY_WEP_KEY3, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_SECRET |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWirelessSecurity:wep-key-flags:
+ *
+ * Flags indicating how to handle the #NMSettingWirelessSecurity:wep-key0,
+ * #NMSettingWirelessSecurity:wep-key1, #NMSettingWirelessSecurity:wep-key2,
+ * and #NMSettingWirelessSecurity:wep-key3 properties.
+ **/
+ /* ---ifcfg-rh---
+ * property: wep-key-flags
+ * variable: WEP_KEY_FLAGS(+)
+ * format: NMSettingSecretFlags
+ * description: Password flags for KEY<i>, KEY_PASSPHRASE<i> password.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_WEP_KEY_FLAGS,
+ g_param_spec_flags (NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, "", "",
+ NM_TYPE_SETTING_SECRET_FLAGS,
+ NM_SETTING_SECRET_FLAG_NONE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWirelessSecurity:psk:
+ *
+ * Pre-Shared-Key for WPA networks. If the key is 64-characters long, it
+ * must contain only hexadecimal characters and is interpreted as a
+ * hexadecimal WPA key. Otherwise, the key must be between 8 and 63 ASCII
+ * characters (as specified in the 802.11i standard) and is interpreted as a
+ * WPA passphrase, and is hashed to derive the actual WPA-PSK used when
+ * connecting to the Wi-Fi network.
+ **/
+ /* ---ifcfg-rh---
+ * property: psk
+ * variable: WPA_PSK
+ * description: Pre-Shared-Key for WPA networks.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_PSK,
+ g_param_spec_string (NM_SETTING_WIRELESS_SECURITY_PSK, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_SECRET |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWirelessSecurity:psk-flags:
+ *
+ * Flags indicating how to handle the #NMSettingWirelessSecurity:psk
+ * property.
+ **/
+ /* ---ifcfg-rh---
+ * property: psk-flags
+ * variable: WPA_PSK_FLAGS(+)
+ * format: NMSettingSecretFlags
+ * description: Password flags for WPA_PSK_FLAGS.
+ * example: WPA_PSK_FLAGS=user
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_PSK_FLAGS,
+ g_param_spec_flags (NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS, "", "",
+ NM_TYPE_SETTING_SECRET_FLAGS,
+ NM_SETTING_SECRET_FLAG_NONE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWirelessSecurity:leap-password:
+ *
+ * The login password for legacy LEAP connections (ie, key-mgmt =
+ * "ieee8021x" and auth-alg = "leap").
+ **/
+ /* ---ifcfg-rh---
+ * property: leap-password
+ * variable: IEEE_8021X_PASSWORD(+)
+ * description: Password for LEAP. It can also go to "key-"
+ * lookaside file, or it can be owned by a secret agent.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_LEAP_PASSWORD,
+ g_param_spec_string (NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_SECRET |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWirelessSecurity:leap-password-flags:
+ *
+ * Flags indicating how to handle the
+ * #NMSettingWirelessSecurity:leap-password property.
+ **/
+ /* ---ifcfg-rh---
+ * property: leap-password-flags
+ * variable: IEEE_8021X_PASSWORD_FLAGS(+)
+ * format: NMSettingSecretFlags
+ * description: Password flags for IEEE_8021X_PASSWORD_FLAGS.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_LEAP_PASSWORD_FLAGS,
+ g_param_spec_flags (NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS, "", "",
+ NM_TYPE_SETTING_SECRET_FLAGS,
+ NM_SETTING_SECRET_FLAG_NONE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWirelessSecurity:wep-key-type:
+ *
+ * Controls the interpretation of WEP keys. Allowed values are
+ * %NM_WEP_KEY_TYPE_KEY, in which case the key is either a 10- or
+ * 26-character hexadecimal string, or a 5- or 13-character ASCII password;
+ * or %NM_WEP_KEY_TYPE_PASSPHRASE, in which case the passphrase is provided
+ * as a string and will be hashed using the de-facto MD5 method to derive
+ * the actual WEP key.
+ **/
+ /* ---ifcfg-rh---
+ * property: wep-key-type
+ * variable: KEY<i> or KEY_PASSPHRASE<i>(+)
+ * description: KEY is used for "key" type (10 or 26 hexadecimal characters,
+ * or 5 or 13 character string prefixed with "s:"). KEY_PASSPHRASE is used
+ * for WEP passphrases.
+ * example: KEY1=s:ahoj, KEY1=0a1c45bc02, KEY_PASSPHRASE1=mysupersecretkey
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_WEP_KEY_TYPE,
+ g_param_spec_enum (NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, "", "",
+ NM_TYPE_WEP_KEY_TYPE,
+ NM_WEP_KEY_TYPE_UNKNOWN,
+ 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);
+}
diff --git a/libnm-core/nm-setting-wireless-security.h b/libnm-core/nm-setting-wireless-security.h
new file mode 100644
index 000000000..8c4e1f038
--- /dev/null
+++ b/libnm-core/nm-setting-wireless-security.h
@@ -0,0 +1,147 @@
+/* -*- 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 2007 - 2014 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#ifndef __NM_SETTING_WIRELESS_SECURITY_H__
+#define __NM_SETTING_WIRELESS_SECURITY_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_WIRELESS_SECURITY (nm_setting_wireless_security_get_type ())
+#define NM_SETTING_WIRELESS_SECURITY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_WIRELESS_SECURITY, NMSettingWirelessSecurity))
+#define NM_SETTING_WIRELESS_SECURITY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_WIRELESS_SECURITY, NMSettingWirelessSecurityClass))
+#define NM_IS_SETTING_WIRELESS_SECURITY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_WIRELESS_SECURITY))
+#define NM_IS_SETTING_WIRELESS_SECURITY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_WIRELESS_SECURITY))
+#define NM_SETTING_WIRELESS_SECURITY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_WIRELESS_SECURITY, NMSettingWirelessSecurityClass))
+
+#define NM_SETTING_WIRELESS_SECURITY_SETTING_NAME "802-11-wireless-security"
+
+/**
+ * NMWepKeyType:
+ * @NM_WEP_KEY_TYPE_UNKNOWN: unknown WEP key type
+ * @NM_WEP_KEY_TYPE_KEY: indicates a hexadecimal or ASCII formatted WEP key.
+ * Hex keys are either 10 or 26 hexadecimal characters (ie "5f782f2f5f" or
+ * "732f2d712e4a394a375d366931"), while ASCII keys are either 5 or 13 ASCII
+ * characters (ie "abcde" or "blahblah99$*1").
+ * @NM_WEP_KEY_TYPE_PASSPHRASE: indicates a WEP passphrase (ex "I bought a duck
+ * on my way back from the market 235Q&^%^*%") instead of a hexadecimal or ASCII
+ * key. Passphrases are between 8 and 64 characters inclusive and are hashed
+ * the actual WEP key using the MD5 hash algorithm.
+ * @NM_WEP_KEY_TYPE_LAST: placeholder value for bounds-checking
+ *
+ * The #NMWepKeyType values specify how any WEP keys present in the setting
+ * are intepreted. There are no standards governing how to hash the various WEP
+ * key/passphrase formats into the actual WEP key. Unfortunately some WEP keys
+ * can be interpreted in multiple ways, requring the setting to specify how to
+ * interpret the any WEP keys. For example, the key "732f2d712e4a394a375d366931"
+ * is both a valid Hexadecimal WEP key and a WEP passphrase. Further, many
+ * ASCII keys are also valid WEP passphrases, but since passphrases and ASCII
+ * keys are hashed differently to determine the actual WEP key the type must be
+ * specified.
+ */
+typedef enum {
+ NM_WEP_KEY_TYPE_UNKNOWN = 0,
+ NM_WEP_KEY_TYPE_KEY = 1, /* Hex or ASCII */
+ NM_WEP_KEY_TYPE_PASSPHRASE = 2, /* 104/128-bit Passphrase */
+
+ NM_WEP_KEY_TYPE_LAST = NM_WEP_KEY_TYPE_PASSPHRASE
+} NMWepKeyType;
+
+#define NM_SETTING_WIRELESS_SECURITY_KEY_MGMT "key-mgmt"
+#define NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX "wep-tx-keyidx"
+#define NM_SETTING_WIRELESS_SECURITY_AUTH_ALG "auth-alg"
+#define NM_SETTING_WIRELESS_SECURITY_PROTO "proto"
+#define NM_SETTING_WIRELESS_SECURITY_PAIRWISE "pairwise"
+#define NM_SETTING_WIRELESS_SECURITY_GROUP "group"
+#define NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME "leap-username"
+#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY0 "wep-key0"
+#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY1 "wep-key1"
+#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY2 "wep-key2"
+#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY3 "wep-key3"
+#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS "wep-key-flags"
+#define NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE "wep-key-type"
+#define NM_SETTING_WIRELESS_SECURITY_PSK "psk"
+#define NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS "psk-flags"
+#define NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD "leap-password"
+#define NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS "leap-password-flags"
+
+struct _NMSettingWirelessSecurity {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingWirelessSecurityClass;
+
+GType nm_setting_wireless_security_get_type (void);
+
+NMSetting * nm_setting_wireless_security_new (void);
+
+const char *nm_setting_wireless_security_get_key_mgmt (NMSettingWirelessSecurity *setting);
+
+guint32 nm_setting_wireless_security_get_num_protos (NMSettingWirelessSecurity *setting);
+const char *nm_setting_wireless_security_get_proto (NMSettingWirelessSecurity *setting, guint32 i);
+gboolean nm_setting_wireless_security_add_proto (NMSettingWirelessSecurity *setting, const char *proto);
+void nm_setting_wireless_security_remove_proto (NMSettingWirelessSecurity *setting, guint32 i);
+gboolean nm_setting_wireless_security_remove_proto_by_value (NMSettingWirelessSecurity *setting, const char *proto);
+void nm_setting_wireless_security_clear_protos (NMSettingWirelessSecurity *setting);
+
+guint32 nm_setting_wireless_security_get_num_pairwise (NMSettingWirelessSecurity *setting);
+const char *nm_setting_wireless_security_get_pairwise (NMSettingWirelessSecurity *setting, guint32 i);
+gboolean nm_setting_wireless_security_add_pairwise (NMSettingWirelessSecurity *setting, const char *pairwise);
+void nm_setting_wireless_security_remove_pairwise (NMSettingWirelessSecurity *setting, guint32 i);
+gboolean nm_setting_wireless_security_remove_pairwise_by_value (NMSettingWirelessSecurity *setting, const char *pairwise);
+void nm_setting_wireless_security_clear_pairwise (NMSettingWirelessSecurity *setting);
+
+guint32 nm_setting_wireless_security_get_num_groups (NMSettingWirelessSecurity *setting);
+const char *nm_setting_wireless_security_get_group (NMSettingWirelessSecurity *setting, guint32 i);
+gboolean nm_setting_wireless_security_add_group (NMSettingWirelessSecurity *setting, const char *group);
+void nm_setting_wireless_security_remove_group (NMSettingWirelessSecurity *setting, guint32 i);
+gboolean nm_setting_wireless_security_remove_group_by_value (NMSettingWirelessSecurity *setting, const char *group);
+void nm_setting_wireless_security_clear_groups (NMSettingWirelessSecurity *setting);
+
+const char *nm_setting_wireless_security_get_psk (NMSettingWirelessSecurity *setting);
+NMSettingSecretFlags nm_setting_wireless_security_get_psk_flags (NMSettingWirelessSecurity *setting);
+
+const char *nm_setting_wireless_security_get_leap_username (NMSettingWirelessSecurity *setting);
+const char *nm_setting_wireless_security_get_leap_password (NMSettingWirelessSecurity *setting);
+NMSettingSecretFlags nm_setting_wireless_security_get_leap_password_flags (NMSettingWirelessSecurity *setting);
+
+const char *nm_setting_wireless_security_get_wep_key (NMSettingWirelessSecurity *setting, guint32 idx);
+void nm_setting_wireless_security_set_wep_key (NMSettingWirelessSecurity *setting, guint32 idx, const char *key);
+guint32 nm_setting_wireless_security_get_wep_tx_keyidx (NMSettingWirelessSecurity *setting);
+const char *nm_setting_wireless_security_get_auth_alg (NMSettingWirelessSecurity *setting);
+
+NMSettingSecretFlags nm_setting_wireless_security_get_wep_key_flags (NMSettingWirelessSecurity *setting);
+NMWepKeyType nm_setting_wireless_security_get_wep_key_type (NMSettingWirelessSecurity *setting);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_WIRELESS_SECURITY_H__ */
diff --git a/libnm-core/nm-setting-wireless.c b/libnm-core/nm-setting-wireless.c
new file mode 100644
index 000000000..f8d22c2d0
--- /dev/null
+++ b/libnm-core/nm-setting-wireless.c
@@ -0,0 +1,1335 @@
+/* -*- 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 2007 - 2014 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <net/ethernet.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-setting-wireless.h"
+#include "nm-dbus-interface.h"
+#include "nm-utils.h"
+#include "nm-utils-private.h"
+#include "nm-setting-private.h"
+
+/**
+ * SECTION:nm-setting-wireless
+ * @short_description: Describes connection properties for 802.11 Wi-Fi networks
+ *
+ * The #NMSettingWireless object is a #NMSetting subclass that describes properties
+ * 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, 1))
+NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_WIRELESS)
+
+#define NM_SETTING_WIRELESS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING_WIRELESS, NMSettingWirelessPrivate))
+
+typedef struct {
+ GBytes *ssid;
+ char *mode;
+ char *band;
+ guint32 channel;
+ char *bssid;
+ guint32 rate;
+ guint32 tx_power;
+ char *device_mac_address;
+ char *cloned_mac_address;
+ GArray *mac_address_blacklist;
+ guint32 mtu;
+ GSList *seen_bssids;
+ gboolean hidden;
+} NMSettingWirelessPrivate;
+
+enum {
+ PROP_0,
+ PROP_SSID,
+ PROP_MODE,
+ PROP_BAND,
+ PROP_CHANNEL,
+ PROP_BSSID,
+ PROP_RATE,
+ PROP_TX_POWER,
+ PROP_MAC_ADDRESS,
+ PROP_CLONED_MAC_ADDRESS,
+ PROP_MAC_ADDRESS_BLACKLIST,
+ PROP_MTU,
+ PROP_SEEN_BSSIDS,
+ PROP_HIDDEN,
+
+ LAST_PROP
+};
+
+static gboolean
+match_cipher (const char *cipher,
+ const char *expected,
+ guint32 wpa_flags,
+ guint32 rsn_flags,
+ guint32 flag)
+{
+ if (strcmp (cipher, expected) != 0)
+ return FALSE;
+
+ if (!(wpa_flags & flag) && !(rsn_flags & flag))
+ return FALSE;
+
+ return TRUE;
+}
+
+/**
+ * nm_setting_wireless_ap_security_compatible:
+ * @s_wireless: a #NMSettingWireless
+ * @s_wireless_sec: a #NMSettingWirelessSecurity or %NULL
+ * @ap_flags: the %NM80211ApFlags of the given access point
+ * @ap_wpa: the %NM80211ApSecurityFlags of the given access point's WPA
+ * capabilities
+ * @ap_rsn: the %NM80211ApSecurityFlags of the given access point's WPA2/RSN
+ * capabilities
+ * @ap_mode: the 802.11 mode of the AP, either Ad-Hoc or Infrastructure
+ *
+ * Given a #NMSettingWireless and an optional #NMSettingWirelessSecurity,
+ * determine if the configuration given by the settings is compatible with
+ * the security of an access point using that access point's capability flags
+ * and mode. Useful for clients that wish to filter a set of connections
+ * against a set of access points and determine which connections are
+ * compatible with which access points.
+ *
+ * Returns: %TRUE if the given settings are compatible with the access point's
+ * security flags and mode, %FALSE if they are not.
+ */
+gboolean
+nm_setting_wireless_ap_security_compatible (NMSettingWireless *s_wireless,
+ NMSettingWirelessSecurity *s_wireless_sec,
+ NM80211ApFlags ap_flags,
+ NM80211ApSecurityFlags ap_wpa,
+ NM80211ApSecurityFlags ap_rsn,
+ NM80211Mode ap_mode)
+{
+ const char *key_mgmt = NULL, *cipher;
+ guint32 num, i;
+ gboolean found = FALSE;
+
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS (s_wireless), FALSE);
+
+ if (!s_wireless_sec) {
+ if ( (ap_flags & NM_802_11_AP_FLAGS_PRIVACY)
+ || (ap_wpa != NM_802_11_AP_SEC_NONE)
+ || (ap_rsn != NM_802_11_AP_SEC_NONE))
+ return FALSE;
+ return TRUE;
+ }
+
+ key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wireless_sec);
+ if (!key_mgmt)
+ return FALSE;
+
+ /* Static WEP */
+ if (!strcmp (key_mgmt, "none")) {
+ if ( !(ap_flags & NM_802_11_AP_FLAGS_PRIVACY)
+ || (ap_wpa != NM_802_11_AP_SEC_NONE)
+ || (ap_rsn != NM_802_11_AP_SEC_NONE))
+ return FALSE;
+ return TRUE;
+ }
+
+ /* Adhoc WPA */
+ if (!strcmp (key_mgmt, "wpa-none")) {
+ if (ap_mode != NM_802_11_MODE_ADHOC)
+ return FALSE;
+ /* FIXME: validate ciphers if they're in the beacon */
+ return TRUE;
+ }
+
+ /* Adhoc WPA2 (ie, RSN IBSS) */
+ if (ap_mode == NM_802_11_MODE_ADHOC) {
+ if (strcmp (key_mgmt, "wpa-psk"))
+ return FALSE;
+
+ /* Ensure the AP has RSN PSK capability */
+ if (!(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_PSK))
+ return FALSE;
+
+ /* Fall through and check ciphers in generic WPA-PSK code */
+ }
+
+ /* Dynamic WEP or LEAP */
+ if (!strcmp (key_mgmt, "ieee8021x")) {
+ if (!(ap_flags & NM_802_11_AP_FLAGS_PRIVACY))
+ return FALSE;
+
+ /* If the AP is advertising a WPA IE, make sure it supports WEP ciphers */
+ if (ap_wpa != NM_802_11_AP_SEC_NONE) {
+ if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X))
+ return FALSE;
+
+ /* quick check; can't use AP if it doesn't support at least one
+ * WEP cipher in both pairwise and group suites.
+ */
+ if ( !(ap_wpa & (NM_802_11_AP_SEC_PAIR_WEP40 | NM_802_11_AP_SEC_PAIR_WEP104))
+ || !(ap_wpa & (NM_802_11_AP_SEC_GROUP_WEP40 | NM_802_11_AP_SEC_GROUP_WEP104)))
+ return FALSE;
+
+ /* Match at least one pairwise cipher with AP's capability if the
+ * wireless-security setting explicitly lists pairwise ciphers
+ */
+ num = nm_setting_wireless_security_get_num_pairwise (s_wireless_sec);
+ for (i = 0, found = FALSE; i < num; i++) {
+ cipher = nm_setting_wireless_security_get_pairwise (s_wireless_sec, i);
+ if ((found = match_cipher (cipher, "wep40", ap_wpa, ap_wpa, NM_802_11_AP_SEC_PAIR_WEP40)))
+ break;
+ if ((found = match_cipher (cipher, "wep104", ap_wpa, ap_wpa, NM_802_11_AP_SEC_PAIR_WEP104)))
+ break;
+ }
+ if (!found && num)
+ return FALSE;
+
+ /* Match at least one group cipher with AP's capability if the
+ * wireless-security setting explicitly lists group ciphers
+ */
+ num = nm_setting_wireless_security_get_num_groups (s_wireless_sec);
+ for (i = 0, found = FALSE; i < num; i++) {
+ cipher = nm_setting_wireless_security_get_group (s_wireless_sec, i);
+ if ((found = match_cipher (cipher, "wep40", ap_wpa, ap_wpa, NM_802_11_AP_SEC_GROUP_WEP40)))
+ break;
+ if ((found = match_cipher (cipher, "wep104", ap_wpa, ap_wpa, NM_802_11_AP_SEC_GROUP_WEP104)))
+ break;
+ }
+ if (!found && num)
+ return FALSE;
+ }
+ return TRUE;
+ }
+
+ /* WPA[2]-PSK and WPA[2] Enterprise */
+ if ( !strcmp (key_mgmt, "wpa-psk")
+ || !strcmp (key_mgmt, "wpa-eap")) {
+
+ if (!strcmp (key_mgmt, "wpa-psk")) {
+ if ( !(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_PSK)
+ && !(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_PSK))
+ return FALSE;
+ } else if (!strcmp (key_mgmt, "wpa-eap")) {
+ if ( !(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X)
+ && !(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_802_1X))
+ return FALSE;
+ }
+
+ // FIXME: should handle WPA and RSN separately here to ensure that
+ // if the Connection only uses WPA we don't match a cipher against
+ // the AP's RSN IE instead
+
+ /* Match at least one pairwise cipher with AP's capability if the
+ * wireless-security setting explicitly lists pairwise ciphers
+ */
+ num = nm_setting_wireless_security_get_num_pairwise (s_wireless_sec);
+ for (i = 0, found = FALSE; i < num; i++) {
+ cipher = nm_setting_wireless_security_get_pairwise (s_wireless_sec, i);
+ if ((found = match_cipher (cipher, "tkip", ap_wpa, ap_rsn, NM_802_11_AP_SEC_PAIR_TKIP)))
+ break;
+ if ((found = match_cipher (cipher, "ccmp", ap_wpa, ap_rsn, NM_802_11_AP_SEC_PAIR_CCMP)))
+ break;
+ }
+ if (!found && num)
+ return FALSE;
+
+ /* Match at least one group cipher with AP's capability if the
+ * wireless-security setting explicitly lists group ciphers
+ */
+ num = nm_setting_wireless_security_get_num_groups (s_wireless_sec);
+ for (i = 0, found = FALSE; i < num; i++) {
+ cipher = nm_setting_wireless_security_get_group (s_wireless_sec, i);
+
+ if ((found = match_cipher (cipher, "wep40", ap_wpa, ap_rsn, NM_802_11_AP_SEC_GROUP_WEP40)))
+ break;
+ if ((found = match_cipher (cipher, "wep104", ap_wpa, ap_rsn, NM_802_11_AP_SEC_GROUP_WEP104)))
+ break;
+ if ((found = match_cipher (cipher, "tkip", ap_wpa, ap_rsn, NM_802_11_AP_SEC_GROUP_TKIP)))
+ break;
+ if ((found = match_cipher (cipher, "ccmp", ap_wpa, ap_rsn, NM_802_11_AP_SEC_GROUP_CCMP)))
+ break;
+ }
+ if (!found && num)
+ return FALSE;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * nm_setting_wireless_new:
+ *
+ * Creates a new #NMSettingWireless object with default values.
+ *
+ * Returns: (transfer full): the new empty #NMSettingWireless object
+ **/
+NMSetting *
+nm_setting_wireless_new (void)
+{
+ return (NMSetting *) g_object_new (NM_TYPE_SETTING_WIRELESS, NULL);
+}
+
+/**
+ * nm_setting_wireless_get_ssid:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: (transfer none): the #NMSettingWireless:ssid property of the setting
+ **/
+GBytes *
+nm_setting_wireless_get_ssid (NMSettingWireless *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL);
+
+ return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->ssid;
+}
+
+/**
+ * nm_setting_wireless_get_mode:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:mode property of the setting
+ **/
+const char *
+nm_setting_wireless_get_mode (NMSettingWireless *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL);
+
+ return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->mode;
+}
+
+/**
+ * nm_setting_wireless_get_band:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:band property of the setting
+ **/
+const char *
+nm_setting_wireless_get_band (NMSettingWireless *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL);
+
+ return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->band;
+}
+
+/**
+ * nm_setting_wireless_get_channel:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:channel property of the setting
+ **/
+guint32
+nm_setting_wireless_get_channel (NMSettingWireless *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), 0);
+
+ return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->channel;
+}
+
+/**
+ * nm_setting_wireless_get_bssid:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:bssid property of the setting
+ **/
+const char *
+nm_setting_wireless_get_bssid (NMSettingWireless *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL);
+
+ return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->bssid;
+}
+
+/**
+ * nm_setting_wireless_get_rate:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:rate property of the setting
+ **/
+guint32
+nm_setting_wireless_get_rate (NMSettingWireless *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), 0);
+
+ return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->rate;
+}
+
+/**
+ * nm_setting_wireless_get_tx_power:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:tx-power property of the setting
+ **/
+guint32
+nm_setting_wireless_get_tx_power (NMSettingWireless *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), 0);
+
+ return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->tx_power;
+}
+
+/**
+ * nm_setting_wireless_get_mac_address:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:mac-address property of the setting
+ **/
+const char *
+nm_setting_wireless_get_mac_address (NMSettingWireless *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL);
+
+ return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->device_mac_address;
+}
+
+/**
+ * nm_setting_wireless_get_cloned_mac_address:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:cloned-mac-address property of the setting
+ **/
+const char *
+nm_setting_wireless_get_cloned_mac_address (NMSettingWireless *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL);
+
+ return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->cloned_mac_address;
+}
+
+/**
+ * nm_setting_wireless_get_mac_address_blacklist:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:mac-address-blacklist property of the setting
+ **/
+const char * const *
+nm_setting_wireless_get_mac_address_blacklist (NMSettingWireless *setting)
+{
+ NMSettingWirelessPrivate *priv;
+
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL);
+
+ priv = NM_SETTING_WIRELESS_GET_PRIVATE (setting);
+ return (const char * const *) priv->mac_address_blacklist->data;
+}
+
+/**
+ * nm_setting_wireless_get_num_mac_blacklist_items:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the number of blacklisted MAC addresses
+ **/
+guint32
+nm_setting_wireless_get_num_mac_blacklist_items (NMSettingWireless *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), 0);
+
+ return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->mac_address_blacklist->len;
+}
+
+/**
+ * nm_setting_wireless_get_mac_blacklist_item:
+ * @setting: the #NMSettingWireless
+ * @idx: the zero-based index of the MAC address entry
+ *
+ * Returns: the blacklisted MAC address string (hex-digits-and-colons notation)
+ * at index @idx
+ **/
+const char *
+nm_setting_wireless_get_mac_blacklist_item (NMSettingWireless *setting, guint32 idx)
+{
+ NMSettingWirelessPrivate *priv;
+
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL);
+
+ priv = NM_SETTING_WIRELESS_GET_PRIVATE (setting);
+ g_return_val_if_fail (idx <= priv->mac_address_blacklist->len, NULL);
+
+ return g_array_index (priv->mac_address_blacklist, const char *, idx);
+}
+
+/**
+ * nm_setting_wireless_add_mac_blacklist_item:
+ * @setting: the #NMSettingWireless
+ * @mac: the MAC address string (hex-digits-and-colons notation) to blacklist
+ *
+ * Adds a new MAC address to the #NMSettingWireless:mac-address-blacklist property.
+ *
+ * Returns: %TRUE if the MAC address was added; %FALSE if the MAC address
+ * is invalid or was already present
+ **/
+gboolean
+nm_setting_wireless_add_mac_blacklist_item (NMSettingWireless *setting, const char *mac)
+{
+ NMSettingWirelessPrivate *priv;
+ const char *candidate;
+ int i;
+
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), FALSE);
+ g_return_val_if_fail (mac != NULL, FALSE);
+
+ if (!nm_utils_hwaddr_valid (mac, ETH_ALEN))
+ return FALSE;
+
+ priv = NM_SETTING_WIRELESS_GET_PRIVATE (setting);
+ for (i = 0; i < priv->mac_address_blacklist->len; i++) {
+ candidate = g_array_index (priv->mac_address_blacklist, char *, i);
+ if (nm_utils_hwaddr_matches (mac, -1, candidate, -1))
+ return FALSE;
+ }
+
+ mac = nm_utils_hwaddr_canonical (mac, ETH_ALEN);
+ g_array_append_val (priv->mac_address_blacklist, mac);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST);
+ return TRUE;
+}
+
+/**
+ * nm_setting_wireless_remove_mac_blacklist_item:
+ * @setting: the #NMSettingWireless
+ * @idx: index number of the MAC address
+ *
+ * Removes the MAC address at index @idx from the blacklist.
+ **/
+void
+nm_setting_wireless_remove_mac_blacklist_item (NMSettingWireless *setting, guint32 idx)
+{
+ NMSettingWirelessPrivate *priv;
+
+ g_return_if_fail (NM_IS_SETTING_WIRELESS (setting));
+
+ priv = NM_SETTING_WIRELESS_GET_PRIVATE (setting);
+ g_return_if_fail (idx < priv->mac_address_blacklist->len);
+
+ g_array_remove_index (priv->mac_address_blacklist, idx);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST);
+}
+
+/**
+ * nm_setting_wireless_remove_mac_blacklist_item_by_value:
+ * @setting: the #NMSettingWireless
+ * @mac: the MAC address string (hex-digits-and-colons notation) to remove from
+ * the blacklist
+ *
+ * Removes the MAC address @mac from the blacklist.
+ *
+ * Returns: %TRUE if the MAC address was found and removed; %FALSE if it was not.
+ **/
+gboolean
+nm_setting_wireless_remove_mac_blacklist_item_by_value (NMSettingWireless *setting, const char *mac)
+{
+ NMSettingWirelessPrivate *priv;
+ const char *candidate;
+ int i;
+
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), FALSE);
+ g_return_val_if_fail (mac != NULL, FALSE);
+
+ priv = NM_SETTING_WIRELESS_GET_PRIVATE (setting);
+ for (i = 0; i < priv->mac_address_blacklist->len; i++) {
+ candidate = g_array_index (priv->mac_address_blacklist, char *, i);
+ if (!nm_utils_hwaddr_matches (mac, -1, candidate, -1)) {
+ g_array_remove_index (priv->mac_address_blacklist, i);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * nm_setting_wireless_clear_mac_blacklist_items:
+ * @setting: the #NMSettingWireless
+ *
+ * Removes all blacklisted MAC addresses.
+ **/
+void
+nm_setting_wireless_clear_mac_blacklist_items (NMSettingWireless *setting)
+{
+ g_return_if_fail (NM_IS_SETTING_WIRELESS (setting));
+
+ g_array_set_size (NM_SETTING_WIRELESS_GET_PRIVATE (setting)->mac_address_blacklist, 0);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST);
+}
+
+/**
+ * nm_setting_wireless_get_mtu:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:mtu property of the setting
+ **/
+guint32
+nm_setting_wireless_get_mtu (NMSettingWireless *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), 0);
+
+ return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->mtu;
+}
+
+/**
+ * nm_setting_wireless_get_hidden:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the #NMSettingWireless:hidden property of the setting
+ **/
+gboolean
+nm_setting_wireless_get_hidden (NMSettingWireless *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), FALSE);
+
+ return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->hidden;
+}
+
+/**
+ * nm_setting_wireless_add_seen_bssid:
+ * @setting: the #NMSettingWireless
+ * @bssid: the new BSSID to add to the list
+ *
+ * Adds a new Wi-Fi AP's BSSID to the previously seen BSSID list of the setting.
+ * NetworkManager now tracks previously seen BSSIDs internally so this function
+ * no longer has much use. Actually, changes you make using this function will
+ * not be preserved.
+ *
+ * Returns: %TRUE if @bssid was already known, %FALSE if not
+ **/
+gboolean
+nm_setting_wireless_add_seen_bssid (NMSettingWireless *setting,
+ const char *bssid)
+{
+ NMSettingWirelessPrivate *priv;
+ char *lower_bssid;
+ GSList *iter;
+ gboolean found = FALSE;
+
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), FALSE);
+ g_return_val_if_fail (bssid != NULL, FALSE);
+
+ lower_bssid = g_ascii_strdown (bssid, -1);
+ if (!lower_bssid)
+ return FALSE;
+
+ priv = NM_SETTING_WIRELESS_GET_PRIVATE (setting);
+
+ for (iter = priv->seen_bssids; iter; iter = iter->next) {
+ if (!strcmp ((char *) iter->data, lower_bssid)) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found) {
+ priv->seen_bssids = g_slist_prepend (priv->seen_bssids, lower_bssid);
+ g_object_notify (G_OBJECT (setting), NM_SETTING_WIRELESS_SEEN_BSSIDS);
+ } else
+ g_free (lower_bssid);
+
+ return !found;
+}
+
+/**
+ * nm_setting_wireless_get_num_seen_bssids:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns: the number of BSSIDs in the previously seen BSSID list
+ **/
+guint32
+nm_setting_wireless_get_num_seen_bssids (NMSettingWireless *setting)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), 0);
+
+ return g_slist_length (NM_SETTING_WIRELESS_GET_PRIVATE (setting)->seen_bssids);
+}
+
+/**
+ * nm_setting_wireless_get_seen_bssid:
+ * @setting: the #NMSettingWireless
+ * @i: index of a BSSID in the previously seen BSSID list
+ *
+ * Returns: the BSSID at index @i
+ **/
+const char *
+nm_setting_wireless_get_seen_bssid (NMSettingWireless *setting,
+ guint32 i)
+{
+ g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NULL);
+
+ return (const char *) g_slist_nth_data (NM_SETTING_WIRELESS_GET_PRIVATE (setting)->seen_bssids, i);
+}
+
+static gboolean
+verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ NMSettingWirelessPrivate *priv = NM_SETTING_WIRELESS_GET_PRIVATE (setting);
+ const char *valid_modes[] = { NM_SETTING_WIRELESS_MODE_INFRA, NM_SETTING_WIRELESS_MODE_ADHOC, NM_SETTING_WIRELESS_MODE_AP, NULL };
+ const char *valid_bands[] = { "a", "bg", NULL };
+ GSList *iter;
+ int i;
+ gsize length;
+
+ if (!priv->ssid) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("property is missing"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_SSID);
+ return FALSE;
+ }
+
+ length = g_bytes_get_size (priv->ssid);
+ if (length == 0 || length > 32) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("SSID length is out of range <1-32> bytes"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_SSID);
+ return FALSE;
+ }
+
+ if (priv->mode && !_nm_utils_string_in_list (priv->mode, valid_modes)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid Wi-Fi mode"),
+ priv->mode);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_MODE);
+ return FALSE;
+ }
+
+ if (priv->band && !_nm_utils_string_in_list (priv->band, valid_bands)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid band"),
+ priv->band);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_BAND);
+ return FALSE;
+ }
+
+ if (priv->channel && !priv->band) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_MISSING_PROPERTY,
+ _("'%s' requires setting '%s' property"),
+ NM_SETTING_WIRELESS_CHANNEL, NM_SETTING_WIRELESS_BAND);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_BAND);
+ return FALSE;
+ }
+
+ if (priv->channel) {
+ if (!nm_utils_wifi_is_channel_valid (priv->channel, priv->band)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%d' is not a valid channel"),
+ priv->channel);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_CHANNEL);
+ return FALSE;
+ }
+ }
+
+ if (priv->bssid && !nm_utils_hwaddr_valid (priv->bssid, ETH_ALEN)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_BSSID);
+ return FALSE;
+ }
+
+ if (priv->device_mac_address && !nm_utils_hwaddr_valid (priv->device_mac_address, ETH_ALEN)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_MAC_ADDRESS);
+ return FALSE;
+ }
+
+ if (priv->cloned_mac_address && !nm_utils_hwaddr_valid (priv->cloned_mac_address, ETH_ALEN)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("property is invalid"));
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS);
+ return FALSE;
+ }
+
+ for (i = 0; i < priv->mac_address_blacklist->len; i++) {
+ const char *mac = g_array_index (priv->mac_address_blacklist, const char *, i);
+
+ if (!nm_utils_hwaddr_valid (mac, ETH_ALEN)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid MAC address"),
+ mac);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST);
+ return FALSE;
+ }
+ }
+
+ for (iter = priv->seen_bssids; iter; iter = iter->next) {
+ if (!nm_utils_hwaddr_valid (iter->data, ETH_ALEN)) {
+ g_set_error (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("'%s' is not a valid MAC address"),
+ (const char *) iter->data);
+ g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_SEEN_BSSIDS);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static GVariant *
+nm_setting_wireless_get_security (NMSetting *setting,
+ NMConnection *connection,
+ const char *property_name)
+{
+ if (nm_connection_get_setting_wireless_security (connection))
+ return g_variant_new_string (NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
+ else
+ return NULL;
+}
+
+static void
+clear_blacklist_item (char **item_p)
+{
+ g_free (*item_p);
+}
+
+static void
+nm_setting_wireless_init (NMSettingWireless *setting)
+{
+ NMSettingWirelessPrivate *priv = NM_SETTING_WIRELESS_GET_PRIVATE (setting);
+
+ /* We use GArray rather than GPtrArray so it will automatically be NULL-terminated */
+ priv->mac_address_blacklist = g_array_new (TRUE, FALSE, sizeof (char *));
+ g_array_set_clear_func (priv->mac_address_blacklist, (GDestroyNotify) clear_blacklist_item);
+}
+
+static void
+finalize (GObject *object)
+{
+ NMSettingWirelessPrivate *priv = NM_SETTING_WIRELESS_GET_PRIVATE (object);
+
+ g_free (priv->mode);
+ g_free (priv->band);
+
+ if (priv->ssid)
+ g_bytes_unref (priv->ssid);
+ g_free (priv->bssid);
+ g_free (priv->device_mac_address);
+ g_free (priv->cloned_mac_address);
+ g_array_unref (priv->mac_address_blacklist);
+ g_slist_free_full (priv->seen_bssids, g_free);
+
+ G_OBJECT_CLASS (nm_setting_wireless_parent_class)->finalize (object);
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ NMSettingWirelessPrivate *priv = NM_SETTING_WIRELESS_GET_PRIVATE (object);
+ const char * const *blacklist;
+ const char *mac;
+ int i;
+
+ switch (prop_id) {
+ case PROP_SSID:
+ if (priv->ssid)
+ g_bytes_unref (priv->ssid);
+ priv->ssid = g_value_dup_boxed (value);
+ break;
+ case PROP_MODE:
+ g_free (priv->mode);
+ priv->mode = g_value_dup_string (value);
+ break;
+ case PROP_BAND:
+ g_free (priv->band);
+ priv->band = g_value_dup_string (value);
+ break;
+ case PROP_CHANNEL:
+ priv->channel = g_value_get_uint (value);
+ break;
+ case PROP_BSSID:
+ g_free (priv->bssid);
+ priv->bssid = g_value_dup_string (value);
+ break;
+ case PROP_RATE:
+ priv->rate = g_value_get_uint (value);
+ break;
+ case PROP_TX_POWER:
+ priv->tx_power = g_value_get_uint (value);
+ break;
+ case PROP_MAC_ADDRESS:
+ g_free (priv->device_mac_address);
+ priv->device_mac_address = _nm_utils_hwaddr_canonical_or_invalid (g_value_get_string (value),
+ ETH_ALEN);
+ break;
+ case PROP_CLONED_MAC_ADDRESS:
+ g_free (priv->cloned_mac_address);
+ priv->cloned_mac_address = _nm_utils_hwaddr_canonical_or_invalid (g_value_get_string (value),
+ ETH_ALEN);
+ break;
+ case PROP_MAC_ADDRESS_BLACKLIST:
+ blacklist = g_value_get_boxed (value);
+ g_array_set_size (priv->mac_address_blacklist, 0);
+ if (blacklist && *blacklist) {
+ for (i = 0; blacklist[i]; i++) {
+ mac = _nm_utils_hwaddr_canonical_or_invalid (blacklist[i], ETH_ALEN);
+ g_array_append_val (priv->mac_address_blacklist, mac);
+ }
+ }
+ break;
+ case PROP_MTU:
+ priv->mtu = g_value_get_uint (value);
+ break;
+ case PROP_SEEN_BSSIDS:
+ g_slist_free_full (priv->seen_bssids, g_free);
+ priv->seen_bssids = _nm_utils_strv_to_slist (g_value_get_boxed (value));
+ break;
+ case PROP_HIDDEN:
+ priv->hidden = g_value_get_boolean (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)
+{
+ NMSettingWireless *setting = NM_SETTING_WIRELESS (object);
+ NMSettingWirelessPrivate *priv = NM_SETTING_WIRELESS_GET_PRIVATE (object);
+
+ switch (prop_id) {
+ case PROP_SSID:
+ g_value_set_boxed (value, nm_setting_wireless_get_ssid (setting));
+ break;
+ case PROP_MODE:
+ g_value_set_string (value, nm_setting_wireless_get_mode (setting));
+ break;
+ case PROP_BAND:
+ g_value_set_string (value, nm_setting_wireless_get_band (setting));
+ break;
+ case PROP_CHANNEL:
+ g_value_set_uint (value, nm_setting_wireless_get_channel (setting));
+ break;
+ case PROP_BSSID:
+ g_value_set_string (value, nm_setting_wireless_get_bssid (setting));
+ break;
+ case PROP_RATE:
+ g_value_set_uint (value, nm_setting_wireless_get_rate (setting));
+ break;
+ case PROP_TX_POWER:
+ g_value_set_uint (value, nm_setting_wireless_get_tx_power (setting));
+ break;
+ case PROP_MAC_ADDRESS:
+ g_value_set_string (value, nm_setting_wireless_get_mac_address (setting));
+ break;
+ case PROP_CLONED_MAC_ADDRESS:
+ g_value_set_string (value, nm_setting_wireless_get_cloned_mac_address (setting));
+ break;
+ case PROP_MAC_ADDRESS_BLACKLIST:
+ g_value_set_boxed (value, (char **) priv->mac_address_blacklist->data);
+ break;
+ case PROP_MTU:
+ g_value_set_uint (value, nm_setting_wireless_get_mtu (setting));
+ break;
+ case PROP_SEEN_BSSIDS:
+ g_value_take_boxed (value, _nm_utils_slist_to_strv (priv->seen_bssids));
+ break;
+ case PROP_HIDDEN:
+ g_value_set_boolean (value, nm_setting_wireless_get_hidden (setting));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_setting_wireless_class_init (NMSettingWirelessClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+ NMSettingClass *parent_class = NM_SETTING_CLASS (setting_class);
+
+ g_type_class_add_private (setting_class, sizeof (NMSettingWirelessPrivate));
+
+ /* virtual methods */
+ object_class->set_property = set_property;
+ object_class->get_property = get_property;
+ object_class->finalize = finalize;
+ parent_class->verify = verify;
+
+ /* Properties */
+ /**
+ * NMSettingWireless:ssid:
+ *
+ * SSID of the Wi-Fi network. Must be specified.
+ **/
+ /* ---keyfile---
+ * property: ssid
+ * format: string (or decimal-byte list - obsolete)
+ * description: SSID of Wi-Fi network.
+ * example: ssid=Quick Net
+ * ---end---
+ * ---ifcfg-rh---
+ * property: ssid
+ * variable: ESSID
+ * description: SSID of Wi-Fi network.
+ * example: ESSID="Quick Net"
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_SSID,
+ g_param_spec_boxed (NM_SETTING_WIRELESS_SSID, "", "",
+ G_TYPE_BYTES,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWireless:mode:
+ *
+ * Wi-Fi network mode; one of "infrastructure", "adhoc" or "ap". If blank,
+ * infrastructure is assumed.
+ **/
+ /* ---ifcfg-rh---
+ * property: mode
+ * variable: MODE
+ * values: Ad-Hoc, Managed (Auto) [case insensitive]
+ * description: Wi-Fi network mode.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_MODE,
+ g_param_spec_string (NM_SETTING_WIRELESS_MODE, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWireless:band:
+ *
+ * 802.11 frequency band of the network. One of "a" for 5GHz 802.11a or
+ * "bg" for 2.4GHz 802.11. This will lock associations to the Wi-Fi network
+ * to the specific band, i.e. if "a" is specified, the device will not
+ * associate with the same network in the 2.4GHz band even if the network's
+ * settings are compatible. This setting depends on specific driver
+ * capability and may not work with all drivers.
+ **/
+ /* ---ifcfg-rh---
+ * property: band
+ * variable: BAND(+)
+ * values: a, bg
+ * description: BAND alone is honored, but CHANNEL overrides BAND since it
+ * implies a band.
+ * example: BAND=bg
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_BAND,
+ g_param_spec_string (NM_SETTING_WIRELESS_BAND, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWireless:channel:
+ *
+ * Wireless channel to use for the Wi-Fi connection. The device will only
+ * join (or create for Ad-Hoc networks) a Wi-Fi network on the specified
+ * channel. Because channel numbers overlap between bands, this property
+ * also requires the "band" property to be set.
+ **/
+ /* ---ifcfg-rh---
+ * property: channel
+ * variable: CHANNEL
+ * description: Channel used for the Wi-Fi communication.
+ * Channels greater than 14 mean "a" band, otherwise the
+ * band is "bg".
+ * example: CHANNEL=6
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_CHANNEL,
+ g_param_spec_uint (NM_SETTING_WIRELESS_CHANNEL, "", "",
+ 0, G_MAXUINT32, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWireless:bssid:
+ *
+ * If specified, directs the device to only associate with the given access
+ * point. This capability is highly driver dependent and not supported by
+ * all devices. Note: this property does not control the BSSID used when
+ * creating an Ad-Hoc network and is unlikely to in the future.
+ **/
+ /* ---ifcfg-rh---
+ * property: bssid
+ * variable: BSSID(+)
+ * description: Restricts association only to a single AP.
+ * example: BSSID=00:1E:BD:64:83:21
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_BSSID,
+ g_param_spec_string (NM_SETTING_WIRELESS_BSSID, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+ _nm_setting_class_transform_property (parent_class, NM_SETTING_WIRELESS_BSSID,
+ G_VARIANT_TYPE_BYTESTRING,
+ _nm_utils_hwaddr_to_dbus,
+ _nm_utils_hwaddr_from_dbus);
+
+ /**
+ * NMSettingWireless:rate:
+ *
+ * If non-zero, directs the device to only use the specified bitrate for
+ * communication with the access point. Units are in Kb/s, ie 5500 = 5.5
+ * Mbit/s. This property is highly driver dependent and not all devices
+ * support setting a static bitrate.
+ **/
+ /* ---ifcfg-rh---
+ * property: rate
+ * variable: (none)
+ * description: This property is not handled by ifcfg-rh plugin.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_RATE,
+ g_param_spec_uint (NM_SETTING_WIRELESS_RATE, "", "",
+ 0, G_MAXUINT32, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWireless:tx-power:
+ *
+ * If non-zero, directs the device to use the specified transmit power.
+ * Units are dBm. This property is highly driver dependent and not all
+ * devices support setting a static transmit power.
+ **/
+ /* ---ifcfg-rh---
+ * property: tx-power
+ * variable: (none)
+ * description: This property is not handled by ifcfg-rh plugin.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_TX_POWER,
+ g_param_spec_uint (NM_SETTING_WIRELESS_TX_POWER, "", "",
+ 0, G_MAXUINT32, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWireless:mac-address:
+ *
+ * If specified, this connection will only apply to the Wi-Fi device whose
+ * permanent MAC address matches. This property does not change the MAC
+ * address of the device (i.e. MAC spoofing).
+ **/
+ /* ---keyfile---
+ * property: mac-address
+ * format: ususal hex-digits-and-colons notation
+ * description: MAC address in traditional hex-digits-and-colons notation
+ * (e.g. 00:22:68:12:79:A2), or semicolon separated list of 6 bytes (obsolete)
+ * (e.g. 0;34;104;18;121;162).
+ * ---end---
+ * ---ifcfg-rh---
+ * property: mac-address
+ * variable: HWADDR
+ * description: Hardware address of the device in traditional hex-digits-and-colons
+ * notation (e.g. 00:22:68:14:5A:05).
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_MAC_ADDRESS,
+ g_param_spec_string (NM_SETTING_WIRELESS_MAC_ADDRESS, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+ _nm_setting_class_transform_property (parent_class, NM_SETTING_WIRELESS_MAC_ADDRESS,
+ G_VARIANT_TYPE_BYTESTRING,
+ _nm_utils_hwaddr_to_dbus,
+ _nm_utils_hwaddr_from_dbus);
+
+ /**
+ * NMSettingWireless:cloned-mac-address:
+ *
+ * If specified, request that the Wi-Fi device use this MAC address instead
+ * of its permanent MAC address. This is known as MAC cloning or spoofing.
+ **/
+ /* ---keyfile---
+ * property: cloned-mac-address
+ * format: ususal hex-digits-and-colons notation
+ * description: Cloned MAC address in traditional hex-digits-and-colons notation
+ * (e.g. 00:22:68:12:79:B2), or semicolon separated list of 6 bytes (obsolete)
+ * (e.g. 0;34;104;18;121;178).
+ * ---end---
+ * ---ifcfg-rh---
+ * property: cloned-mac-address
+ * variable: MACADDR
+ * description: Cloned (spoofed) MAC address in traditional hex-digits-and-colons
+ * notation (e.g. 00:22:68:14:5A:99).
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_CLONED_MAC_ADDRESS,
+ g_param_spec_string (NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, "", "",
+ NULL,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+ _nm_setting_class_transform_property (parent_class, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS,
+ G_VARIANT_TYPE_BYTESTRING,
+ _nm_utils_hwaddr_to_dbus,
+ _nm_utils_hwaddr_from_dbus);
+
+ /**
+ * NMSettingWireless:mac-address-blacklist:
+ *
+ * A list of permanent MAC addresses of Wi-Fi devices to which this
+ * connection should never apply. Each MAC address should be given in the
+ * standard hex-digits-and-colons notation (eg "00:11:22:33:44:55").
+ **/
+ /* ---keyfile---
+ * property: mac-address-blacklist
+ * format: list of MACs (separated with semicolons)
+ * description: MAC address blacklist.
+ * example: mac-address-blacklist= 00:22:68:12:79:A6;00:22:68:12:79:78
+ * ---end---
+ * ---ifcfg-rh---
+ * property: mac-address-blacklist
+ * variable: HWADDR_BLACKLIST(+)
+ * description: It denies usage of the connection for any device whose address
+ * is listed.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_MAC_ADDRESS_BLACKLIST,
+ g_param_spec_boxed (NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST, "", "",
+ G_TYPE_STRV,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWireless:seen-bssids:
+ *
+ * A list of BSSIDs (each BSSID formatted as a MAC address like
+ * "00:11:22:33:44:55") that have been detected as part of the Wi-Fi
+ * network. NetworkManager internally tracks previously seen BSSIDs. The
+ * property is only meant for reading and reflects the BSSID list of
+ * NetworkManager. The changes you make to this property will not be
+ * preserved.
+ **/
+ /* ---ifcfg-rh---
+ * property: seen-bssids
+ * variable: (none)
+ * description: This property is not handled by ifcfg-rh plugin.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_SEEN_BSSIDS,
+ g_param_spec_boxed (NM_SETTING_WIRELESS_SEEN_BSSIDS, "", "",
+ G_TYPE_STRV,
+ G_PARAM_READWRITE |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWireless:mtu:
+ *
+ * If non-zero, only transmit packets of the specified size or smaller,
+ * breaking larger packets up into multiple Ethernet frames.
+ **/
+ /* ---ifcfg-rh---
+ * property: mtu
+ * variable: MTU
+ * description: MTU of the wireless interface.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_MTU,
+ g_param_spec_uint (NM_SETTING_WIRELESS_MTU, "", "",
+ 0, G_MAXUINT32, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT |
+ NM_SETTING_PARAM_FUZZY_IGNORE |
+ G_PARAM_STATIC_STRINGS));
+
+ /**
+ * NMSettingWireless:hidden:
+ *
+ * If %TRUE, indicates this network is a non-broadcasting network that hides
+ * its SSID. In this case various workarounds may take place, such as
+ * probe-scanning the SSID for more reliable network discovery. However,
+ * these workarounds expose inherent insecurities with hidden SSID networks,
+ * and thus hidden SSID networks should be used with caution.
+ **/
+ /* ---ifcfg-rh---
+ * property: hidden
+ * variable: SSID_HIDDEN(+)
+ * description: Whether the network hides the SSID.
+ * ---end---
+ */
+ g_object_class_install_property
+ (object_class, PROP_HIDDEN,
+ g_param_spec_boolean (NM_SETTING_WIRELESS_HIDDEN, "", "",
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
+ /* Compatibility for deprecated property */
+ /* ---ifcfg-rh---
+ * property: security
+ * variable: (none)
+ * description: This property is deprecated and not handled by ifcfg-rh-plugin.
+ * ---end---
+ * ---dbus---
+ * property: security
+ * description: This property is deprecated, but can be set to the value
+ * '802-11-wireless-security' when a wireless security setting is also
+ * present in the connection dictionary, for compatibility with very old
+ * NetworkManager daemons.
+ * ---end---
+ */
+ _nm_setting_class_add_dbus_only_property (parent_class, "security",
+ G_VARIANT_TYPE_STRING,
+ nm_setting_wireless_get_security, NULL);
+}
diff --git a/libnm-core/nm-setting-wireless.h b/libnm-core/nm-setting-wireless.h
new file mode 100644
index 000000000..98fa98dc6
--- /dev/null
+++ b/libnm-core/nm-setting-wireless.h
@@ -0,0 +1,138 @@
+/* -*- 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 2007 - 2014 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#ifndef __NM_SETTING_WIRELESS_H__
+#define __NM_SETTING_WIRELESS_H__
+
+#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
+#error "Only <NetworkManager.h> can be included directly."
+#endif
+
+#include <nm-setting.h>
+#include <nm-setting-wireless-security.h>
+#include <nm-dbus-interface.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_SETTING_WIRELESS (nm_setting_wireless_get_type ())
+#define NM_SETTING_WIRELESS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING_WIRELESS, NMSettingWireless))
+#define NM_SETTING_WIRELESS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING_WIRELESS, NMSettingWirelessClass))
+#define NM_IS_SETTING_WIRELESS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING_WIRELESS))
+#define NM_IS_SETTING_WIRELESS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING_WIRELESS))
+#define NM_SETTING_WIRELESS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING_WIRELESS, NMSettingWirelessClass))
+
+#define NM_SETTING_WIRELESS_SETTING_NAME "802-11-wireless"
+
+#define NM_SETTING_WIRELESS_SSID "ssid"
+#define NM_SETTING_WIRELESS_MODE "mode"
+#define NM_SETTING_WIRELESS_BAND "band"
+#define NM_SETTING_WIRELESS_CHANNEL "channel"
+#define NM_SETTING_WIRELESS_BSSID "bssid"
+#define NM_SETTING_WIRELESS_RATE "rate"
+#define NM_SETTING_WIRELESS_TX_POWER "tx-power"
+#define NM_SETTING_WIRELESS_MAC_ADDRESS "mac-address"
+#define NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS "cloned-mac-address"
+#define NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST "mac-address-blacklist"
+#define NM_SETTING_WIRELESS_MTU "mtu"
+#define NM_SETTING_WIRELESS_SEEN_BSSIDS "seen-bssids"
+#define NM_SETTING_WIRELESS_HIDDEN "hidden"
+
+/**
+ * NM_SETTING_WIRELESS_MODE_ADHOC:
+ *
+ * Indicates Ad-Hoc mode where no access point is expected to be present.
+ */
+#define NM_SETTING_WIRELESS_MODE_ADHOC "adhoc"
+
+/**
+ * NM_SETTING_WIRELESS_MODE_AP:
+ *
+ * Indicates AP/master mode where the wireless device is started as an access
+ * point/hotspot.
+ */
+#define NM_SETTING_WIRELESS_MODE_AP "ap"
+
+/**
+ * NM_SETTING_WIRELESS_MODE_INFRA:
+ *
+ * Indicates infrastructure mode where an access point is expected to be present
+ * for this connection.
+ */
+#define NM_SETTING_WIRELESS_MODE_INFRA "infrastructure"
+
+struct _NMSettingWireless {
+ NMSetting parent;
+};
+
+typedef struct {
+ NMSettingClass parent;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSettingWirelessClass;
+
+GType nm_setting_wireless_get_type (void);
+
+NMSetting *nm_setting_wireless_new (void);
+
+GBytes *nm_setting_wireless_get_ssid (NMSettingWireless *setting);
+const char *nm_setting_wireless_get_mode (NMSettingWireless *setting);
+const char *nm_setting_wireless_get_band (NMSettingWireless *setting);
+guint32 nm_setting_wireless_get_channel (NMSettingWireless *setting);
+const char *nm_setting_wireless_get_bssid (NMSettingWireless *setting);
+guint32 nm_setting_wireless_get_rate (NMSettingWireless *setting);
+guint32 nm_setting_wireless_get_tx_power (NMSettingWireless *setting);
+const char *nm_setting_wireless_get_mac_address (NMSettingWireless *setting);
+const char *nm_setting_wireless_get_cloned_mac_address (NMSettingWireless *setting);
+
+const char * const *nm_setting_wireless_get_mac_address_blacklist (NMSettingWireless *setting);
+guint32 nm_setting_wireless_get_num_mac_blacklist_items (NMSettingWireless *setting);
+const char * nm_setting_wireless_get_mac_blacklist_item (NMSettingWireless *setting,
+ guint32 idx);
+gboolean nm_setting_wireless_add_mac_blacklist_item (NMSettingWireless *setting,
+ const char *mac);
+void nm_setting_wireless_remove_mac_blacklist_item (NMSettingWireless *setting,
+ guint32 idx);
+gboolean nm_setting_wireless_remove_mac_blacklist_item_by_value (NMSettingWireless *setting,
+ const char *mac);
+void nm_setting_wireless_clear_mac_blacklist_items (NMSettingWireless *setting);
+
+guint32 nm_setting_wireless_get_mtu (NMSettingWireless *setting);
+gboolean nm_setting_wireless_get_hidden (NMSettingWireless *setting);
+
+gboolean nm_setting_wireless_add_seen_bssid (NMSettingWireless *setting,
+ const char *bssid);
+
+guint32 nm_setting_wireless_get_num_seen_bssids (NMSettingWireless *setting);
+const char *nm_setting_wireless_get_seen_bssid (NMSettingWireless *setting,
+ guint32 i);
+
+gboolean nm_setting_wireless_ap_security_compatible (NMSettingWireless *s_wireless,
+ NMSettingWirelessSecurity *s_wireless_sec,
+ NM80211ApFlags ap_flags,
+ NM80211ApSecurityFlags ap_wpa,
+ NM80211ApSecurityFlags ap_rsn,
+ NM80211Mode ap_mode);
+
+G_END_DECLS
+
+#endif /* __NM_SETTING_WIRELESS_H__ */
diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c
new file mode 100644
index 000000000..037baa6b5
--- /dev/null
+++ b/libnm-core/nm-setting.c
@@ -0,0 +1,1818 @@
+/* -*- 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 2007 - 2011 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib/gi18n-lib.h>
+#include <gio/gio.h>
+
+#include "nm-setting.h"
+#include "nm-setting-private.h"
+#include "nm-utils.h"
+#include "nm-core-internal.h"
+#include "nm-utils-private.h"
+#include "nm-property-compare.h"
+
+#include "nm-setting-connection.h"
+#include "nm-setting-bond.h"
+#include "nm-setting-bridge.h"
+#include "nm-setting-bridge-port.h"
+#include "nm-setting-pppoe.h"
+#include "nm-setting-team.h"
+#include "nm-setting-team-port.h"
+#include "nm-setting-vpn.h"
+
+/**
+ * SECTION:nm-setting
+ * @short_description: Describes related configuration information
+ *
+ * Each #NMSetting contains properties that describe configuration that applies
+ * to a specific network layer (like IPv4 or IPv6 configuration) or device type
+ * (like Ethernet, or Wi-Fi). A collection of individual settings together
+ * make up an #NMConnection. Each property is strongly typed and usually has
+ * a number of allowed values. See each #NMSetting subclass for a description
+ * 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 {
+ const char *name;
+ GType type;
+ guint32 priority;
+} SettingInfo;
+
+typedef struct {
+ const SettingInfo *info;
+} NMSettingPrivate;
+
+enum {
+ PROP_0,
+ PROP_NAME,
+
+ 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 __attribute__((constructor))
+_ensure_registered (void)
+{
+ if (G_UNLIKELY (registered_settings == NULL)) {
+#if !GLIB_CHECK_VERSION (2, 35, 0)
+ g_type_init ();
+#endif
+ registered_settings = g_hash_table_new (g_str_hash, g_str_equal);
+ registered_settings_by_type = g_hash_table_new (_nm_gtype_hash, _nm_gtype_equal);
+ }
+}
+
+#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
+
+/*************************************************************/
+
+/*
+ * _nm_register_setting:
+ * @name: the name of the #NMSetting object to register
+ * @type: the #GType of the #NMSetting
+ * @priority: the sort priority of the setting, see below
+ *
+ * INTERNAL ONLY: registers a setting's internal properties with libnm.
+ *
+ * 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 the Connection setting
+ *
+ * 1: 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.
+ *
+ * 2: hardware-related auxiliary settings that require a base setting to be
+ * successful first, like Wi-Fi security, 802.1x, etc.
+ *
+ * 3: hardware-independent settings that are required before IP connectivity
+ * can be established, like PPP, PPPoE, etc.
+ *
+ * 4: IP-level stuff
+ */
+void
+(_nm_register_setting) (const char *name,
+ const GType type,
+ const guint32 priority)
+{
+ SettingInfo *info;
+
+ g_return_if_fail (name != NULL && *name);
+ g_return_if_fail (type != G_TYPE_INVALID);
+ g_return_if_fail (type != G_TYPE_NONE);
+ g_return_if_fail (priority <= 4);
+
+ _ensure_registered ();
+
+ if (G_LIKELY ((info = g_hash_table_lookup (registered_settings, name)))) {
+ g_return_if_fail (info->type == type);
+ g_return_if_fail (info->priority == priority);
+ g_return_if_fail (g_strcmp0 (info->name, name) == 0);
+ return;
+ }
+ g_return_if_fail (g_hash_table_lookup (registered_settings_by_type, &type) == NULL);
+
+ if (priority == 0)
+ g_assert_cmpstr (name, ==, NM_SETTING_CONNECTION_SETTING_NAME);
+
+ 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 guint32
+_get_setting_type_priority (GType type)
+{
+ const SettingInfo *info;
+
+ g_return_val_if_fail (g_type_is_a (type, NM_TYPE_SETTING), G_MAXUINT32);
+
+ info = _nm_setting_lookup_setting_by_type (type);
+ return info->priority;
+}
+
+guint32
+_nm_setting_get_setting_priority (NMSetting *setting)
+{
+ NMSettingPrivate *priv;
+
+ 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;
+}
+
+gboolean
+_nm_setting_type_is_base_type (GType type)
+{
+ /* 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.
+ */
+ return _get_setting_type_priority (type) == 1 || (type == NM_TYPE_SETTING_PPPOE);
+}
+
+gboolean
+_nm_setting_is_base_type (NMSetting *setting)
+{
+ return _nm_setting_type_is_base_type (G_OBJECT_TYPE (setting));
+}
+
+/**
+ * nm_setting_lookup_type:
+ * @name: a setting name
+ *
+ * Returns the #GType of the setting's class for a given setting name.
+ *
+ * Returns: the #GType of the setting's class, or %G_TYPE_INVALID if
+ * @name is not recognized.
+ **/
+GType
+nm_setting_lookup_type (const char *name)
+{
+ SettingInfo *info;
+
+ g_return_val_if_fail (name != NULL, G_TYPE_INVALID);
+
+ _ensure_registered ();
+
+ info = g_hash_table_lookup (registered_settings, name);
+ return info ? info->type : G_TYPE_INVALID;
+}
+
+gint
+_nm_setting_compare_priority (gconstpointer a, gconstpointer b)
+{
+ guint32 prio_a, prio_b;
+
+ prio_a = _nm_setting_get_setting_priority ((NMSetting *) a);
+ prio_b = _nm_setting_get_setting_priority ((NMSetting *) b);
+
+ if (prio_a < prio_b)
+ return -1;
+ else if (prio_a == prio_b)
+ return 0;
+ return 1;
+}
+
+/*************************************************************/
+
+gboolean
+_nm_setting_slave_type_is_valid (const char *slave_type, const char **out_port_type)
+{
+ const char *port_type = NULL;
+ gboolean found = TRUE;
+
+ if (!slave_type)
+ found = FALSE;
+ else if (!strcmp (slave_type, NM_SETTING_BOND_SETTING_NAME))
+ ;
+ else if (!strcmp (slave_type, NM_SETTING_BRIDGE_SETTING_NAME))
+ port_type = NM_SETTING_BRIDGE_PORT_SETTING_NAME;
+ else if (!strcmp (slave_type, NM_SETTING_TEAM_SETTING_NAME))
+ port_type = NM_SETTING_TEAM_PORT_SETTING_NAME;
+ else
+ found = FALSE;
+
+ if (out_port_type)
+ *out_port_type = port_type;
+ return found;
+}
+
+/*************************************************************/
+
+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 GQuark setting_property_overrides_quark;
+static GQuark setting_properties_quark;
+
+static NMSettingProperty *
+find_property (GArray *properties, const char *name)
+{
+ NMSettingProperty *property;
+ int i;
+
+ if (!properties)
+ return NULL;
+
+ for (i = 0; i < properties->len; i++) {
+ property = &g_array_index (properties, NMSettingProperty, i);
+ if (strcmp (name, property->name) == 0)
+ return property;
+ }
+
+ 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)
+{
+ 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);
+ }
+ 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
+ * @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
+ * a #GObject property.
+ *
+ * When serializing a setting to D-Bus, @synth_func will be called to synthesize
+ * a value for the property. (If it returns %NULL, no value will be added to the
+ * serialization. If @synth_func is %NULL, the property will always be omitted
+ * in the serialization.)
+ *
+ * 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 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)
+{
+ 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);
+}
+
+/**
+ * _nm_setting_class_override_property:
+ * @setting_class: the setting class
+ * @property_name: 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.
+ *
+ * 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
+ * property will be added to the hash, and if it returns %NULL, the property
+ * will be omitted. (If @get_func is %NULL, the property will be read normally
+ * 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().)
+ *
+ * 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
+ * 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)
+{
+ 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_setting_class_transform_property:
+ * @setting_class: the setting class
+ * @property: the name 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
+ *
+ * Indicates that @property on @setting_class does not have the same format as
+ * its corresponding D-Bus representation, and so must be transformed when
+ * serializing/deserializing.
+ *
+ * The transformation will also be used by nm_setting_compare(), meaning that
+ * the underlying object property does not need to be of a type that
+ * 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)
+{
+ GParamSpec *param_spec;
+
+ param_spec = g_object_class_find_property (G_OBJECT_CLASS (setting_class), property);
+ g_return_if_fail (param_spec != NULL);
+
+ add_property_override (setting_class,
+ property, param_spec, dbus_type,
+ NULL, NULL, NULL, NULL,
+ to_dbus, from_dbus);
+}
+
+gboolean
+_nm_setting_use_legacy_property (NMSetting *setting,
+ GVariant *connection_dict,
+ const char *legacy_property,
+ const char *new_property)
+{
+ GVariant *setting_dict, *value;
+
+ setting_dict = g_variant_lookup_value (connection_dict, nm_setting_get_name (NM_SETTING (setting)), NM_VARIANT_TYPE_SETTING);
+ g_return_val_if_fail (setting_dict != NULL, FALSE);
+
+ /* If the new property isn't set, we have to use the legacy property. */
+ value = g_variant_lookup_value (setting_dict, new_property, NULL);
+ if (!value) {
+ g_variant_unref (setting_dict);
+ return TRUE;
+ }
+ g_variant_unref (value);
+
+ /* Otherwise, clients always prefer new properties sent from the daemon. */
+ if (!_nm_utils_is_manager_process) {
+ g_variant_unref (setting_dict);
+ return FALSE;
+ }
+
+ /* The daemon prefers the legacy property if it exists. */
+ value = g_variant_lookup_value (setting_dict, legacy_property, NULL);
+ g_variant_unref (setting_dict);
+
+ if (value) {
+ g_variant_unref (value);
+ return TRUE;
+ } else
+ 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 *
+variant_type_for_gtype (GType type)
+{
+ if (type == G_TYPE_BOOLEAN)
+ return G_VARIANT_TYPE_BOOLEAN;
+ else if (type == G_TYPE_UCHAR)
+ return G_VARIANT_TYPE_BYTE;
+ else if (type == G_TYPE_INT)
+ return G_VARIANT_TYPE_INT32;
+ else if (type == G_TYPE_UINT)
+ return G_VARIANT_TYPE_UINT32;
+ else if (type == G_TYPE_INT64)
+ return G_VARIANT_TYPE_INT64;
+ else if (type == G_TYPE_UINT64)
+ return G_VARIANT_TYPE_UINT64;
+ else if (type == G_TYPE_STRING)
+ return G_VARIANT_TYPE_STRING;
+ else if (type == G_TYPE_DOUBLE)
+ return G_VARIANT_TYPE_DOUBLE;
+ else if (type == G_TYPE_STRV)
+ return G_VARIANT_TYPE_STRING_ARRAY;
+ else if (type == G_TYPE_BYTES)
+ return G_VARIANT_TYPE_BYTESTRING;
+ else if (g_type_is_a (type, G_TYPE_ENUM))
+ return G_VARIANT_TYPE_INT32;
+ else if (g_type_is_a (type, G_TYPE_FLAGS))
+ return G_VARIANT_TYPE_UINT32;
+ else
+ g_assert_not_reached ();
+}
+
+static GVariant *
+get_property_for_dbus (NMSetting *setting,
+ const NMSettingProperty *property,
+ gboolean ignore_default)
+{
+ GValue prop_value = { 0, };
+ GVariant *dbus_value;
+
+ if (property->get_func)
+ return property->get_func (setting, property->name);
+ else
+ g_return_val_if_fail (property->param_spec != NULL, NULL);
+
+ g_value_init (&prop_value, property->param_spec->value_type);
+ g_object_get_property (G_OBJECT (setting), property->param_spec->name, &prop_value);
+
+ if (ignore_default && g_param_value_defaults (property->param_spec, &prop_value)) {
+ g_value_unset (&prop_value);
+ return NULL;
+ }
+
+ if (property->to_dbus)
+ dbus_value = property->to_dbus (&prop_value);
+ else if (property->dbus_type)
+ dbus_value = g_dbus_gvalue_to_gvariant (&prop_value, property->dbus_type);
+ else if (g_type_is_a (prop_value.g_type, G_TYPE_ENUM))
+ dbus_value = g_variant_new_int32 (g_value_get_enum (&prop_value));
+ 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);
+ else
+ dbus_value = g_dbus_gvalue_to_gvariant (&prop_value, variant_type_for_gtype (prop_value.g_type));
+ g_value_unset (&prop_value);
+
+ return dbus_value;
+}
+
+static void
+set_property_from_dbus (const NMSettingProperty *property, GVariant *src_value, GValue *dst_value)
+{
+ g_return_if_fail (property->param_spec != NULL);
+
+ if (property->from_dbus)
+ property->from_dbus (src_value, dst_value);
+ else if (dst_value->g_type == G_TYPE_BYTES)
+ _nm_utils_bytes_from_dbus (src_value, dst_value);
+ else
+ g_dbus_gvariant_to_gvalue (src_value, dst_value);
+}
+
+
+/**
+ * _nm_setting_to_dbus:
+ * @setting: the #NMSetting
+ * @connection: the #NMConnection containing @setting
+ * @flags: hash flags, e.g. %NM_CONNECTION_SERIALIZE_ALL
+ *
+ * Converts the #NMSetting into a #GVariant of type #NM_VARIANT_TYPE_SETTING
+ * mapping each setting property name to a value describing that property,
+ * suitable for marshalling over D-Bus or serializing.
+ *
+ * Returns: (transfer none): a new floating #GVariant describing the setting's
+ * properties
+ **/
+GVariant *
+_nm_setting_to_dbus (NMSetting *setting, NMConnection *connection, NMConnectionSerializationFlags flags)
+{
+ GVariantBuilder builder;
+ GVariant *dbus_value;
+ const NMSettingProperty *properties;
+ guint n_properties, i;
+
+ g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
+
+ properties = nm_setting_class_get_properties (NM_SETTING_GET_CLASS (setting), &n_properties);
+
+ g_variant_builder_init (&builder, NM_VARIANT_TYPE_SETTING);
+
+ for (i = 0; i < n_properties; i++) {
+ const NMSettingProperty *property = &properties[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 && !(prop_spec->flags & G_PARAM_WRITABLE))
+ continue;
+
+ if ( prop_spec && (prop_spec->flags & NM_SETTING_PARAM_LEGACY)
+ && !_nm_utils_is_manager_process)
+ continue;
+
+ if ( (flags & NM_CONNECTION_SERIALIZE_NO_SECRETS)
+ && (prop_spec && (prop_spec->flags & NM_SETTING_PARAM_SECRET)))
+ continue;
+
+ if ( (flags & NM_CONNECTION_SERIALIZE_ONLY_SECRETS)
+ && !(prop_spec && (prop_spec->flags & NM_SETTING_PARAM_SECRET)))
+ continue;
+
+ if (property->synth_func)
+ dbus_value = property->synth_func (setting, connection, property->name);
+ else
+ dbus_value = get_property_for_dbus (setting, property, TRUE);
+ if (dbus_value) {
+ /* Allow dbus_value to be either floating or not. */
+ g_variant_take_ref (dbus_value);
+
+ g_variant_builder_add (&builder, "{sv}", property->name, dbus_value);
+ g_variant_unref (dbus_value);
+ }
+ }
+
+ return g_variant_builder_end (&builder);
+}
+
+/**
+ * _nm_setting_new_from_dbus:
+ * @setting_type: the #NMSetting type which the hash contains properties for
+ * @setting_dict: the #GVariant containing an %NM_VARIANT_TYPE_SETTING dictionary
+ * mapping property names to values
+ * @connection_dict: the #GVariant containing an %NM_VARIANT_TYPE_CONNECTION
+ * dictionary mapping setting names to dictionaries.
+ * @error: location to store error, or %NULL
+ *
+ * Creates a new #NMSetting object and populates that object with the properties
+ * contained in @setting_dict, using each key as the property to set, and each
+ * value as the value to set that property to. Setting properties are strongly
+ * typed, thus the #GVariantType of the dict value must be correct. See the
+ * documentation on each #NMSetting object subclass for the correct property
+ * names and value types.
+ *
+ * Returns: a new #NMSetting object populated with the properties from the
+ * hash table, or %NULL if @setting_hash could not be deserialized.
+ **/
+NMSetting *
+_nm_setting_new_from_dbus (GType setting_type,
+ GVariant *setting_dict,
+ GVariant *connection_dict,
+ GError **error)
+{
+ NMSettingClass *class;
+ NMSetting *setting;
+ const NMSettingProperty *properties;
+ guint n_properties;
+ 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);
+
+ /* connection_dict is not technically optional, but some tests in test-general
+ * don't bother with it in cases where they know it's not needed.
+ */
+ if (connection_dict)
+ g_return_val_if_fail (g_variant_is_of_type (connection_dict, NM_VARIANT_TYPE_CONNECTION), NULL);
+
+ /* g_type_class_ref() ensures the setting class is created if it hasn't
+ * already been used.
+ */
+ class = g_type_class_ref (setting_type);
+
+ /* Build the setting object from the properties we know about; we assume
+ * that any propreties in @setting_dict that we don't know about can
+ * either be ignored or else has a backward-compatibility equivalent
+ * that we do know about.
+ */
+ setting = (NMSetting *) g_object_new (setting_type, NULL);
+
+ properties = nm_setting_class_get_properties (class, &n_properties);
+ for (i = 0; i < n_properties; i++) {
+ const NMSettingProperty *property = &properties[i];
+ GVariant *value = g_variant_lookup_value (setting_dict, property->name, NULL);
+
+ if (value && property->set_func) {
+ property->set_func (setting,
+ connection_dict,
+ property->name,
+ value);
+ } else if (!value && property->not_set_func) {
+ property->not_set_func (setting,
+ connection_dict,
+ property->name);
+ } else if (value && property->param_spec) {
+ GValue object_value = { 0, };
+
+ if (!(property->param_spec->flags & G_PARAM_WRITABLE))
+ continue;
+
+ g_value_init (&object_value, property->param_spec->value_type);
+ set_property_from_dbus (property, value, &object_value);
+ g_object_set_property (G_OBJECT (setting), property->param_spec->name, &object_value);
+ g_value_unset (&object_value);
+ }
+
+ if (value)
+ g_variant_unref (value);
+ }
+
+ g_type_class_unref (class);
+
+ return setting;
+}
+
+/**
+ * nm_setting_get_dbus_property_type:
+ * @setting: an #NMSetting
+ * @property_name: the property of @setting to get the type of
+ *
+ * Gets the D-Bus marshalling type of a property. @property_name is a D-Bus
+ * property name, which may not necessarily be a #GObject property.
+ *
+ * Returns: the D-Bus marshalling type of @property on @setting.
+ */
+const GVariantType *
+nm_setting_get_dbus_property_type (NMSetting *setting,
+ const char *property_name)
+{
+ const NMSettingProperty *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);
+ g_return_val_if_fail (property != NULL, NULL);
+
+ if (property->dbus_type)
+ return property->dbus_type;
+ else
+ return variant_type_for_gtype (property->param_spec->value_type);
+}
+
+gboolean
+_nm_setting_get_property (NMSetting *setting, const char *property_name, GValue *value)
+{
+ 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);
+
+ if (!prop_spec) {
+ g_value_unset (value);
+ return FALSE;
+ }
+
+ g_value_init (value, prop_spec->value_type);
+ g_object_get_property (G_OBJECT (setting), property_name, value);
+ return TRUE;
+}
+
+static void
+duplicate_setting (NMSetting *setting,
+ const char *name,
+ const GValue *value,
+ GParamFlags flags,
+ gpointer user_data)
+{
+ if ((flags & (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)) == G_PARAM_WRITABLE)
+ g_object_set_property (G_OBJECT (user_data), name, value);
+}
+
+/**
+ * nm_setting_duplicate:
+ * @setting: the #NMSetting to duplicate
+ *
+ * Duplicates a #NMSetting.
+ *
+ * Returns: (transfer full): a new #NMSetting containing the same properties and values as the
+ * source #NMSetting
+ **/
+NMSetting *
+nm_setting_duplicate (NMSetting *setting)
+{
+ 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);
+
+ return NM_SETTING (dup);
+}
+
+/**
+ * nm_setting_get_name:
+ * @setting: the #NMSetting
+ *
+ * Returns the type name of the #NMSetting object
+ *
+ * Returns: a string containing the type name of the #NMSetting object,
+ * like 'ppp' or 'wireless' or 'wired'.
+ **/
+const char *
+nm_setting_get_name (NMSetting *setting)
+{
+ NMSettingPrivate *priv;
+
+ 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;
+}
+
+/**
+ * nm_setting_verify:
+ * @setting: the #NMSetting to verify
+ * @connection: (allow-none): the #NMConnection that @setting came from, or
+ * %NULL if @setting is being verified in isolation.
+ * @error: location to store error, or %NULL
+ *
+ * Validates the setting. Each setting's properties have allowed values, and
+ * some are dependent on other values (hence the need for @connection). The
+ * returned #GError contains information about which property of the setting
+ * failed validation, and in what way that property failed validation.
+ *
+ * Returns: %TRUE if the setting is valid, %FALSE if it is not
+ **/
+gboolean
+nm_setting_verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ NMSettingVerifyResult result = _nm_setting_verify (setting, connection, error);
+
+ if (result == NM_SETTING_VERIFY_NORMALIZABLE)
+ g_clear_error (error);
+
+ return result == NM_SETTING_VERIFY_SUCCESS || result == NM_SETTING_VERIFY_NORMALIZABLE;
+}
+
+NMSettingVerifyResult
+_nm_setting_verify (NMSetting *setting, NMConnection *connection, GError **error)
+{
+ g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_VERIFY_ERROR);
+ g_return_val_if_fail (!connection || NM_IS_CONNECTION (connection), NM_SETTING_VERIFY_ERROR);
+ g_return_val_if_fail (!error || *error == NULL, NM_SETTING_VERIFY_ERROR);
+
+ if (NM_SETTING_GET_CLASS (setting)->verify)
+ return NM_SETTING_GET_CLASS (setting)->verify (setting, connection, error);
+
+ return NM_SETTING_VERIFY_SUCCESS;
+}
+
+static gboolean
+compare_property (NMSetting *setting,
+ NMSetting *other,
+ const GParamSpec *prop_spec,
+ NMSettingCompareFlags flags)
+{
+ const NMSettingProperty *property;
+ GVariant *value1, *value2;
+ int cmp;
+
+ /* Handle compare flags */
+ if (prop_spec->flags & NM_SETTING_PARAM_SECRET) {
+ NMSettingSecretFlags a_secret_flags = NM_SETTING_SECRET_FLAG_NONE;
+ NMSettingSecretFlags b_secret_flags = NM_SETTING_SECRET_FLAG_NONE;
+
+ g_return_val_if_fail (!NM_IS_SETTING_VPN (setting), FALSE);
+
+ if (!nm_setting_get_secret_flags (setting, prop_spec->name, &a_secret_flags, NULL))
+ g_return_val_if_reached (FALSE);
+ if (!nm_setting_get_secret_flags (other, prop_spec->name, &b_secret_flags, NULL))
+ g_return_val_if_reached (FALSE);
+
+ /* If the secret flags aren't the same the settings aren't the same */
+ if (a_secret_flags != b_secret_flags)
+ return FALSE;
+
+ /* Check for various secret flags that might cause us to ignore comparing
+ * this property.
+ */
+ if ( (flags & NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS)
+ && (a_secret_flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED))
+ return TRUE;
+
+ if ( (flags & NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)
+ && (a_secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED))
+ return TRUE;
+ }
+
+ property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), prop_spec->name);
+ g_return_val_if_fail (property != NULL, FALSE);
+
+ value1 = get_property_for_dbus (setting, property, FALSE);
+ value2 = get_property_for_dbus (other, property, FALSE);
+
+ cmp = nm_property_compare (value1, value2);
+
+ g_variant_unref (value1);
+ g_variant_unref (value2);
+
+ return cmp == 0;
+}
+
+/**
+ * nm_setting_compare:
+ * @a: a #NMSetting
+ * @b: a second #NMSetting to compare with the first
+ * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT
+ *
+ * Compares two #NMSetting objects for similarity, with comparison behavior
+ * modified by a set of flags. See the documentation for #NMSettingCompareFlags
+ * for a description of each flag's behavior.
+ *
+ * Returns: %TRUE if the comparison succeeds, %FALSE if it does not
+ **/
+gboolean
+nm_setting_compare (NMSetting *a,
+ NMSetting *b,
+ NMSettingCompareFlags flags)
+{
+ GParamSpec **property_specs;
+ guint n_property_specs;
+ gint same = TRUE;
+ guint i;
+
+ g_return_val_if_fail (NM_IS_SETTING (a), FALSE);
+ g_return_val_if_fail (NM_IS_SETTING (b), FALSE);
+
+ /* First check that both have the same type */
+ if (G_OBJECT_TYPE (a) != G_OBJECT_TYPE (b))
+ return FALSE;
+
+ /* 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++) {
+ GParamSpec *prop_spec = property_specs[i];
+
+ /* Fuzzy compare ignores secrets and properties defined with the FUZZY_IGNORE flag */
+ if ( (flags & NM_SETTING_COMPARE_FLAG_FUZZY)
+ && (prop_spec->flags & (NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET)))
+ continue;
+
+ if ((flags & NM_SETTING_COMPARE_FLAG_INFERRABLE) && !(prop_spec->flags & NM_SETTING_PARAM_INFERRABLE))
+ continue;
+
+ if ( (flags & NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS)
+ && (prop_spec->flags & NM_SETTING_PARAM_SECRET))
+ continue;
+
+ same = NM_SETTING_GET_CLASS (a)->compare_property (a, b, prop_spec, flags);
+ }
+ g_free (property_specs);
+
+ return same;
+}
+
+static inline gboolean
+should_compare_prop (NMSetting *setting,
+ const char *prop_name,
+ NMSettingCompareFlags comp_flags,
+ GParamFlags prop_flags)
+{
+ /* Fuzzy compare ignores secrets and properties defined with the FUZZY_IGNORE flag */
+ if ( (comp_flags & NM_SETTING_COMPARE_FLAG_FUZZY)
+ && (prop_flags & (NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET)))
+ return FALSE;
+
+ if ((comp_flags & NM_SETTING_COMPARE_FLAG_INFERRABLE) && !(prop_flags & NM_SETTING_PARAM_INFERRABLE))
+ return FALSE;
+
+ if (prop_flags & NM_SETTING_PARAM_SECRET) {
+ NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
+
+ if (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS)
+ return FALSE;
+
+ if ( NM_IS_SETTING_VPN (setting)
+ && g_strcmp0 (prop_name, NM_SETTING_VPN_SECRETS) == 0) {
+ /* FIXME: NMSettingVPN:NM_SETTING_VPN_SECRETS has NM_SETTING_PARAM_SECRET.
+ * nm_setting_get_secret_flags() quite possibly fails, but it might succeed if the
+ * setting accidently uses a key "secrets". */
+ return TRUE;
+ }
+
+ if (!nm_setting_get_secret_flags (setting, prop_name, &secret_flags, NULL))
+ g_return_val_if_reached (FALSE);
+
+ if ( (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS)
+ && (secret_flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED))
+ return FALSE;
+
+ if ( (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)
+ && (secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED))
+ return FALSE;
+ }
+
+ if ( (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_ID)
+ && NM_IS_SETTING_CONNECTION (setting)
+ && !strcmp (prop_name, NM_SETTING_CONNECTION_ID))
+ return FALSE;
+
+ if ( (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP)
+ && NM_IS_SETTING_CONNECTION (setting)
+ && !strcmp (prop_name, NM_SETTING_CONNECTION_TIMESTAMP))
+ return FALSE;
+
+ return TRUE;
+}
+
+/**
+ * nm_setting_diff:
+ * @a: a #NMSetting
+ * @b: a second #NMSetting to compare with the first
+ * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT
+ * @invert_results: this parameter is used internally by libnm and should
+ * be set to %FALSE. If %TRUE inverts the meaning of the #NMSettingDiffResult.
+ * @results: (inout) (transfer full) (element-type utf8 guint32): if the
+ * settings differ, on return a hash table mapping the differing keys to one or
+ * more %NMSettingDiffResult values OR-ed together. If the settings do not
+ * differ, any hash table passed in is unmodified. If no hash table is passed
+ * in and the settings differ, a new one is created and returned.
+ *
+ * Compares two #NMSetting objects for similarity, with comparison behavior
+ * modified by a set of flags. See the documentation for #NMSettingCompareFlags
+ * for a description of each flag's behavior. If the settings differ, the keys
+ * of each setting that differ from the other are added to @results, mapped to
+ * one or more #NMSettingDiffResult values.
+ *
+ * Returns: %TRUE if the settings contain the same values, %FALSE if they do not
+ **/
+gboolean
+nm_setting_diff (NMSetting *a,
+ NMSetting *b,
+ NMSettingCompareFlags flags,
+ gboolean invert_results,
+ GHashTable **results)
+{
+ GParamSpec **property_specs;
+ guint n_property_specs;
+ guint i;
+ NMSettingDiffResult a_result = NM_SETTING_DIFF_RESULT_IN_A;
+ NMSettingDiffResult b_result = NM_SETTING_DIFF_RESULT_IN_B;
+ NMSettingDiffResult a_result_default = NM_SETTING_DIFF_RESULT_IN_A_DEFAULT;
+ NMSettingDiffResult b_result_default = NM_SETTING_DIFF_RESULT_IN_B_DEFAULT;
+ gboolean results_created = FALSE;
+
+ g_return_val_if_fail (results != NULL, FALSE);
+ g_return_val_if_fail (NM_IS_SETTING (a), FALSE);
+ if (b) {
+ g_return_val_if_fail (NM_IS_SETTING (b), FALSE);
+ g_return_val_if_fail (G_OBJECT_TYPE (a) == G_OBJECT_TYPE (b), FALSE);
+ }
+
+ if ((flags & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) ==
+ (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) {
+ /* conflicting flags: default to WITH_DEFAULT (clearing NO_DEFAULT). */
+ flags &= ~NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT;
+ }
+
+ /* If the caller is calling this function in a pattern like this to get
+ * complete diffs:
+ *
+ * nm_setting_diff (A, B, FALSE, &results);
+ * nm_setting_diff (B, A, TRUE, &results);
+ *
+ * and wants us to invert the results so that the second invocation comes
+ * out correctly, do that here.
+ */
+ if (invert_results) {
+ a_result = NM_SETTING_DIFF_RESULT_IN_B;
+ b_result = NM_SETTING_DIFF_RESULT_IN_A;
+ a_result_default = NM_SETTING_DIFF_RESULT_IN_B_DEFAULT;
+ b_result_default = NM_SETTING_DIFF_RESULT_IN_A_DEFAULT;
+ }
+
+ if (*results == NULL) {
+ *results = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ results_created = TRUE;
+ }
+
+ /* 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; 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;
+
+ 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);
+ 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;
+
+ 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));
+ }
+ }
+ g_free (property_specs);
+
+ /* Don't return an empty hash table */
+ if (results_created && !g_hash_table_size (*results)) {
+ g_hash_table_destroy (*results);
+ *results = NULL;
+ }
+
+ return !(*results);
+}
+
+/**
+ * nm_setting_enumerate_values:
+ * @setting: the #NMSetting
+ * @func: (scope call): user-supplied function called for each property of the setting
+ * @user_data: user data passed to @func at each invocation
+ *
+ * Iterates over each property of the #NMSetting object, calling the supplied
+ * user function for each property.
+ **/
+void
+nm_setting_enumerate_values (NMSetting *setting,
+ NMSettingValueIterFn func,
+ gpointer user_data)
+{
+ GParamSpec **property_specs;
+ guint n_property_specs;
+ int i;
+
+ 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);
+ for (i = 0; i < n_property_specs; i++) {
+ GParamSpec *prop_spec = property_specs[i];
+ GValue value = G_VALUE_INIT;
+
+ g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (prop_spec));
+ g_object_get_property (G_OBJECT (setting), prop_spec->name, &value);
+ func (setting, prop_spec->name, &value, prop_spec->flags, user_data);
+ g_value_unset (&value);
+ }
+
+ g_free (property_specs);
+}
+
+/**
+ * _nm_setting_clear_secrets:
+ * @setting: the #NMSetting
+ *
+ * Resets and clears any secrets in the setting. Secrets should be added to the
+ * setting only when needed, and cleared immediately after use to prevent
+ * leakage of information.
+ *
+ * Returns: %TRUE if the setting changed at all
+ **/
+gboolean
+_nm_setting_clear_secrets (NMSetting *setting)
+{
+ GParamSpec **property_specs;
+ guint n_property_specs;
+ guint i;
+ gboolean changed = FALSE;
+
+ 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];
+
+ if (prop_spec->flags & NM_SETTING_PARAM_SECRET) {
+ GValue value = G_VALUE_INIT;
+
+ g_value_init (&value, prop_spec->value_type);
+ g_object_get_property (G_OBJECT (setting), prop_spec->name, &value);
+ if (!g_param_value_defaults (prop_spec, &value)) {
+ g_param_value_set_default (prop_spec, &value);
+ g_object_set_property (G_OBJECT (setting), prop_spec->name, &value);
+ changed = TRUE;
+ }
+ g_value_unset (&value);
+ }
+ }
+
+ g_free (property_specs);
+
+ return changed;
+}
+
+static gboolean
+clear_secrets_with_flags (NMSetting *setting,
+ GParamSpec *pspec,
+ NMSettingClearSecretsWithFlagsFn func,
+ gpointer user_data)
+{
+ NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
+ gboolean changed = FALSE;
+
+ g_return_val_if_fail (!NM_IS_SETTING_VPN (setting), FALSE);
+
+ /* Clear the secret if the user function says to do so */
+ if (!nm_setting_get_secret_flags (setting, pspec->name, &flags, NULL))
+ g_return_val_if_reached (FALSE);
+
+ if (func (setting, pspec->name, flags, user_data) == TRUE) {
+ GValue value = G_VALUE_INIT;
+
+ g_value_init (&value, pspec->value_type);
+ g_object_get_property (G_OBJECT (setting), pspec->name, &value);
+ if (!g_param_value_defaults (pspec, &value)) {
+ g_param_value_set_default (pspec, &value);
+ g_object_set_property (G_OBJECT (setting), pspec->name, &value);
+ changed = TRUE;
+ }
+ g_value_unset (&value);
+ }
+
+ return changed;
+}
+
+/**
+ * _nm_setting_clear_secrets_with_flags:
+ * @setting: the #NMSetting
+ * @func: (scope call): function to be called to determine whether a
+ * specific secret should be cleared or not
+ * @user_data: caller-supplied data passed to @func
+ *
+ * Clears and frees secrets determined by @func.
+ *
+ * Returns: %TRUE if the setting changed at all
+ **/
+gboolean
+_nm_setting_clear_secrets_with_flags (NMSetting *setting,
+ NMSettingClearSecretsWithFlagsFn func,
+ gpointer user_data)
+{
+ GParamSpec **property_specs;
+ guint n_property_specs;
+ guint i;
+ gboolean changed = FALSE;
+
+ g_return_val_if_fail (setting, FALSE);
+ g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
+ g_return_val_if_fail (func != NULL, FALSE);
+
+ property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
+ for (i = 0; i < n_property_specs; i++) {
+ if (property_specs[i]->flags & NM_SETTING_PARAM_SECRET) {
+ changed |= NM_SETTING_GET_CLASS (setting)->clear_secrets_with_flags (setting,
+ property_specs[i],
+ func,
+ user_data);
+ }
+ }
+
+ g_free (property_specs);
+ return changed;
+}
+
+/**
+ * _nm_setting_need_secrets:
+ * @setting: the #NMSetting
+ *
+ * Returns an array of property names for each secret which may be required
+ * to make a successful connection. The returned hints are only intended as a
+ * guide to what secrets may be required, because in some circumstances, there
+ * is no way to conclusively determine exactly which secrets are needed.
+ *
+ * Returns: (transfer container) (element-type utf8): a #GPtrArray containing
+ * the property names of secrets of the #NMSetting which may be required; the
+ * caller owns the array and must free it with g_ptr_array_free(), but must not
+ * free the elements.
+ **/
+GPtrArray *
+_nm_setting_need_secrets (NMSetting *setting)
+{
+ GPtrArray *secrets = NULL;
+
+ g_return_val_if_fail (NM_IS_SETTING (setting), NULL);
+
+ if (NM_SETTING_GET_CLASS (setting)->need_secrets)
+ secrets = NM_SETTING_GET_CLASS (setting)->need_secrets (setting);
+
+ return secrets;
+}
+
+static int
+update_one_secret (NMSetting *setting, const char *key, GVariant *value, GError **error)
+{
+ const NMSettingProperty *property;
+ GParamSpec *prop_spec;
+ GValue prop_value = { 0, };
+
+ property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), key);
+ if (!property) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND,
+ _("secret not found"));
+ g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), key);
+ return NM_SETTING_UPDATE_SECRET_ERROR;
+ }
+
+ /* Silently ignore non-secrets */
+ prop_spec = property->param_spec;
+ if (!prop_spec || !(prop_spec->flags & NM_SETTING_PARAM_SECRET))
+ return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
+
+ if ( g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)
+ && G_IS_PARAM_SPEC_STRING (prop_spec)) {
+ /* String is expected to be a common case. Handle it specially and check
+ * whether the value is already set. Otherwise, we just reset the
+ * property and assume the value got modified.
+ */
+ char *v;
+
+ g_object_get (G_OBJECT (setting), prop_spec->name, &v, NULL);
+ if (g_strcmp0 (v, g_variant_get_string (value, NULL)) == 0) {
+ g_free (v);
+ return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
+ }
+ g_free (v);
+ }
+
+ g_value_init (&prop_value, prop_spec->value_type);
+ set_property_from_dbus (property, value, &prop_value);
+ g_object_set_property (G_OBJECT (setting), prop_spec->name, &prop_value);
+ g_value_unset (&prop_value);
+
+ return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED;
+}
+
+/**
+ * _nm_setting_update_secrets:
+ * @setting: the #NMSetting
+ * @secrets: a #GVariant of type #NM_VARIANT_TYPE_SETTING, mapping property
+ * names to secrets.
+ * @error: location to store error, or %NULL
+ *
+ * Update the setting's secrets, given a dictionary of secrets intended for that
+ * setting (deserialized from D-Bus for example).
+ *
+ * Returns: an #NMSettingUpdateSecretResult
+ **/
+NMSettingUpdateSecretResult
+_nm_setting_update_secrets (NMSetting *setting, GVariant *secrets, GError **error)
+{
+ GVariantIter iter;
+ const char *secret_key;
+ GVariant *secret_value;
+ GError *tmp_error = NULL;
+ NMSettingUpdateSecretResult result = NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
+
+ g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_UPDATE_SECRET_ERROR);
+ g_return_val_if_fail (g_variant_is_of_type (secrets, NM_VARIANT_TYPE_SETTING), NM_SETTING_UPDATE_SECRET_ERROR);
+ if (error)
+ g_return_val_if_fail (*error == NULL, NM_SETTING_UPDATE_SECRET_ERROR);
+
+ g_variant_iter_init (&iter, secrets);
+ while (g_variant_iter_next (&iter, "{&sv}", &secret_key, &secret_value)) {
+ int success;
+
+ success = NM_SETTING_GET_CLASS (setting)->update_one_secret (setting, secret_key, secret_value, &tmp_error);
+ g_assert (!((success == NM_SETTING_UPDATE_SECRET_ERROR) ^ (!!tmp_error)));
+
+ g_variant_unref (secret_value);
+
+ if (success == NM_SETTING_UPDATE_SECRET_ERROR) {
+ g_propagate_error (error, tmp_error);
+ return NM_SETTING_UPDATE_SECRET_ERROR;
+ }
+
+ if (success == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED)
+ result = NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED;
+ }
+
+ return result;
+}
+
+static gboolean
+is_secret_prop (NMSetting *setting, const char *secret_name, GError **error)
+{
+ const NMSettingProperty *property;
+ GParamSpec *pspec;
+
+ property = nm_setting_class_find_property (NM_SETTING_GET_CLASS (setting), secret_name);
+ if (!property) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_PROPERTY_NOT_FOUND,
+ _("secret is not set"));
+ g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), secret_name);
+ return FALSE;
+ }
+
+ pspec = property->param_spec;
+ if (!pspec || !(pspec->flags & NM_SETTING_PARAM_SECRET)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_PROPERTY_NOT_SECRET,
+ _("not a secret property"));
+ g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), secret_name);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+get_secret_flags (NMSetting *setting,
+ const char *secret_name,
+ gboolean verify_secret,
+ NMSettingSecretFlags *out_flags,
+ GError **error)
+{
+ char *flags_prop;
+ NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
+
+ if (verify_secret && !is_secret_prop (setting, secret_name, error)) {
+ if (out_flags)
+ *out_flags = NM_SETTING_SECRET_FLAG_NONE;
+ return FALSE;
+ }
+
+ flags_prop = g_strdup_printf ("%s-flags", secret_name);
+ g_object_get (G_OBJECT (setting), flags_prop, &flags, NULL);
+ g_free (flags_prop);
+
+ if (out_flags)
+ *out_flags = flags;
+ return TRUE;
+}
+
+/**
+ * nm_setting_get_secret_flags:
+ * @setting: the #NMSetting
+ * @secret_name: the secret key name to get flags for
+ * @out_flags: on success, the #NMSettingSecretFlags for the secret
+ * @error: location to store error, or %NULL
+ *
+ * For a given secret, retrieves the #NMSettingSecretFlags describing how to
+ * handle that secret.
+ *
+ * Returns: %TRUE on success (if the given secret name was a valid property of
+ * this setting, and if that property is secret), %FALSE if not
+ **/
+gboolean
+nm_setting_get_secret_flags (NMSetting *setting,
+ const char *secret_name,
+ NMSettingSecretFlags *out_flags,
+ GError **error)
+{
+ g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
+ g_return_val_if_fail (secret_name != NULL, FALSE);
+
+ return NM_SETTING_GET_CLASS (setting)->get_secret_flags (setting, secret_name, TRUE, out_flags, error);
+}
+
+static gboolean
+set_secret_flags (NMSetting *setting,
+ const char *secret_name,
+ gboolean verify_secret,
+ NMSettingSecretFlags flags,
+ GError **error)
+{
+ char *flags_prop;
+
+ if (verify_secret)
+ g_return_val_if_fail (is_secret_prop (setting, secret_name, error), FALSE);
+
+ flags_prop = g_strdup_printf ("%s-flags", secret_name);
+ g_object_set (G_OBJECT (setting), flags_prop, flags, NULL);
+ g_free (flags_prop);
+ return TRUE;
+}
+
+/**
+ * nm_setting_set_secret_flags:
+ * @setting: the #NMSetting
+ * @secret_name: the secret key name to set flags for
+ * @flags: the #NMSettingSecretFlags for the secret
+ * @error: location to store error, or %NULL
+ *
+ * For a given secret, stores the #NMSettingSecretFlags describing how to
+ * handle that secret.
+ *
+ * Returns: %TRUE on success (if the given secret name was a valid property of
+ * this setting, and if that property is secret), %FALSE if not
+ **/
+gboolean
+nm_setting_set_secret_flags (NMSetting *setting,
+ const char *secret_name,
+ NMSettingSecretFlags flags,
+ GError **error)
+{
+ g_return_val_if_fail (NM_IS_SETTING (setting), FALSE);
+ g_return_val_if_fail (secret_name != NULL, FALSE);
+ g_return_val_if_fail (flags <= NM_SETTING_SECRET_FLAGS_ALL, FALSE);
+
+ return NM_SETTING_GET_CLASS (setting)->set_secret_flags (setting, secret_name, TRUE, flags, error);
+}
+
+/**
+ * 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.
+ *
+ * Returns: an allocated string containing a textual representation of the
+ * setting's properties and values (including secrets!), 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);
+
+ 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);
+
+ value_str = g_strdup_value_contents (&value);
+ g_string_append_printf (string, "\t%s : %s", prop_spec->name, value_str);
+ g_free (value_str);
+
+ is_default = g_param_value_defaults (prop_spec, &value);
+ g_value_unset (&value);
+
+ 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_free (property_specs);
+ g_string_append_c (string, '\n');
+
+ return g_string_free (string, FALSE);
+}
+
+GVariant *
+_nm_setting_get_deprecated_virtual_interface_name (NMSetting *setting,
+ NMConnection *connection,
+ const char *property)
+{
+ NMSettingConnection *s_con;
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_return_val_if_fail (s_con != NULL, NULL);
+
+ if (nm_setting_connection_get_interface_name (s_con))
+ return g_variant_new_string (nm_setting_connection_get_interface_name (s_con));
+ else
+ return NULL;
+}
+
+/*****************************************************************************/
+
+static void
+nm_setting_init (NMSetting *setting)
+{
+}
+
+static void
+constructed (GObject *object)
+{
+ _ensure_setting_info (object, NM_SETTING_GET_PRIVATE (object));
+
+ G_OBJECT_CLASS (nm_setting_parent_class)->constructed (object);
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ NMSetting *setting = NM_SETTING (object);
+
+ switch (prop_id) {
+ case PROP_NAME:
+ g_value_set_string (value, nm_setting_get_name (setting));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+nm_setting_class_init (NMSettingClass *setting_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (setting_class);
+
+ if (!setting_property_overrides_quark)
+ setting_property_overrides_quark = g_quark_from_static_string ("nm-setting-property-overrides");
+ if (!setting_properties_quark)
+ setting_properties_quark = g_quark_from_static_string ("nm-setting-properties");
+
+ g_type_class_add_private (setting_class, sizeof (NMSettingPrivate));
+
+ /* virtual methods */
+ object_class->constructed = constructed;
+ object_class->get_property = get_property;
+
+ 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->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".
+ **/
+ g_object_class_install_property
+ (object_class, PROP_NAME,
+ g_param_spec_string (NM_SETTING_NAME, "", "",
+ NULL,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_STRINGS));
+}
diff --git a/libnm-core/nm-setting.h b/libnm-core/nm-setting.h
new file mode 100644
index 000000000..3601fce30
--- /dev/null
+++ b/libnm-core/nm-setting.h
@@ -0,0 +1,282 @@
+/* -*- 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 2007 - 2011 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#ifndef __NM_SETTING_H__
+#define __NM_SETTING_H__
+
+#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
+#error "Only <NetworkManager.h> can be included directly."
+#endif
+
+#include <nm-core-types.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_SETTING (nm_setting_get_type ())
+#define NM_SETTING(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTING, NMSetting))
+#define NM_SETTING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTING, NMSettingClass))
+#define NM_IS_SETTING(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTING))
+#define NM_IS_SETTING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SETTING))
+#define NM_SETTING_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTING, NMSettingClass))
+
+/* The property of the #NMSetting is required for the setting to be valid */
+#define NM_SETTING_PARAM_REQUIRED (1 << (1 + G_PARAM_USER_SHIFT))
+
+/* The property of the #NMSetting is a secret */
+#define NM_SETTING_PARAM_SECRET (1 << (2 + G_PARAM_USER_SHIFT))
+
+/* The property of the #NMSetting should be ignored during comparisons that
+ * use the %NM_SETTING_COMPARE_FLAG_FUZZY flag.
+ */
+#define NM_SETTING_PARAM_FUZZY_IGNORE (1 << (3 + G_PARAM_USER_SHIFT))
+
+/* Note: all non-glib GParamFlags bits are reserved by NetworkManager */
+
+
+#define NM_SETTING_NAME "name"
+
+/**
+ * NMSettingSecretFlags:
+ * @NM_SETTING_SECRET_FLAG_NONE: the system is responsible for providing and
+ * storing this secret (default)
+ * @NM_SETTING_SECRET_FLAG_AGENT_OWNED: a user secret agent is responsible
+ * for providing and storing this secret; when it is required agents will be
+ * asked to retrieve it
+ * @NM_SETTING_SECRET_FLAG_NOT_SAVED: this secret should not be saved, but
+ * should be requested from the user each time it is needed
+ * @NM_SETTING_SECRET_FLAG_NOT_REQUIRED: in situations where it cannot be
+ * automatically determined that the secret is required (some VPNs and PPP
+ * providers dont require all secrets) this flag indicates that the specific
+ * secret is not required
+ *
+ * These flags indicate specific behavior related to handling of a secret. Each
+ * secret has a corresponding set of these flags which indicate how the secret
+ * is to be stored and/or requested when it is needed.
+ *
+ **/
+typedef enum { /*< flags >*/
+ NM_SETTING_SECRET_FLAG_NONE = 0x00000000,
+ NM_SETTING_SECRET_FLAG_AGENT_OWNED = 0x00000001,
+ NM_SETTING_SECRET_FLAG_NOT_SAVED = 0x00000002,
+ NM_SETTING_SECRET_FLAG_NOT_REQUIRED = 0x00000004
+
+ /* NOTE: if adding flags, update nm-core-internal.h as well */
+} NMSettingSecretFlags;
+
+/**
+ * NMSettingCompareFlags:
+ * @NM_SETTING_COMPARE_FLAG_EXACT: match all properties exactly
+ * @NM_SETTING_COMPARE_FLAG_FUZZY: match only important attributes, like SSID,
+ * type, security settings, etc. Does not match, for example, connection ID
+ * or UUID.
+ * @NM_SETTING_COMPARE_FLAG_IGNORE_ID: ignore the connection's ID
+ * @NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS: ignore all secrets
+ * @NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS: ignore secrets for which
+ * the secret's flags indicate the secret is owned by a user secret agent
+ * (ie, the secret's flag includes @NM_SETTING_SECRET_FLAG_AGENT_OWNED)
+ * @NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS: ignore secrets for which
+ * the secret's flags indicate the secret should not be saved to persistent
+ * storage (ie, the secret's flag includes @NM_SETTING_SECRET_FLAG_NOT_SAVED)
+ * @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT: if this flag is set,
+ * nm_setting_diff() and nm_connection_diff() will also include properties that
+ * are set to their default value. See also @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT.
+ * @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT: if this flag is set,
+ * nm_setting_diff() and nm_connection_diff() will not include properties that
+ * are set to their default value. This is the opposite of
+ * @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT. If both flags are set together,
+ * @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT wins. If both flags are unset,
+ * this means to exclude default properties if there is a setting to compare,
+ * but include all properties, if the setting 'b' is missing. This is the legacy
+ * behaviour of libnm-util, where nm_setting_diff() behaved differently depending
+ * on whether the setting 'b' was available. If @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT
+ * is set, nm_setting_diff() will also set the flags @NM_SETTING_DIFF_RESULT_IN_A_DEFAULT
+ * and @NM_SETTING_DIFF_RESULT_IN_B_DEFAULT, if the values are default values.
+ * @NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP: ignore the connection's timestamp
+ *
+ * These flags modify the comparison behavior when comparing two settings or
+ * two connections.
+ *
+ **/
+typedef enum {
+ NM_SETTING_COMPARE_FLAG_EXACT = 0x00000000,
+ NM_SETTING_COMPARE_FLAG_FUZZY = 0x00000001,
+ NM_SETTING_COMPARE_FLAG_IGNORE_ID = 0x00000002,
+ NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS = 0x00000004,
+ NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS = 0x00000008,
+ NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS = 0x00000010,
+ NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT = 0x00000020,
+ NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT = 0x00000040,
+ NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP = 0x00000080,
+
+ /* 0x80000000 is used for a private flag */
+} NMSettingCompareFlags;
+
+
+/**
+ * NMSetting:
+ *
+ * The NMSetting struct contains only private data.
+ * It should only be accessed through the functions described below.
+ */
+struct _NMSetting {
+ GObject parent;
+};
+
+
+/**
+ * NMSettingClearSecretsWithFlagsFn:
+ * @setting: The setting for which secrets are being iterated
+ * @secret: The secret's name
+ * @flags: The secret's flags, eg %NM_SETTING_SECRET_FLAG_AGENT_OWNED
+ * @user_data: User data passed to nm_connection_clear_secrets_with_flags()
+ *
+ * Returns: %TRUE to clear the secret, %FALSE to not clear the secret
+ */
+typedef gboolean (*NMSettingClearSecretsWithFlagsFn) (NMSetting *setting,
+ const char *secret,
+ NMSettingSecretFlags flags,
+ gpointer user_data);
+
+typedef struct {
+ GObjectClass parent;
+
+ /* Virtual functions */
+ gint (*verify) (NMSetting *setting,
+ NMConnection *connection,
+ GError **error);
+
+ GPtrArray *(*need_secrets) (NMSetting *setting);
+
+ int (*update_one_secret) (NMSetting *setting,
+ const char *key,
+ GVariant *value,
+ GError **error);
+
+ gboolean (*get_secret_flags) (NMSetting *setting,
+ const char *secret_name,
+ gboolean verify_secret,
+ NMSettingSecretFlags *out_flags,
+ GError **error);
+
+ gboolean (*set_secret_flags) (NMSetting *setting,
+ const char *secret_name,
+ gboolean verify_secret,
+ NMSettingSecretFlags flags,
+ GError **error);
+
+ gboolean (*clear_secrets_with_flags) (NMSetting *setting,
+ GParamSpec *pspec,
+ NMSettingClearSecretsWithFlagsFn func,
+ gpointer user_data);
+
+ /* Returns TRUE if the given property contains the same value in both settings */
+ gboolean (*compare_property) (NMSetting *setting,
+ NMSetting *other,
+ const GParamSpec *prop_spec,
+ NMSettingCompareFlags flags);
+
+ /*< private >*/
+ gpointer padding[8];
+} NMSettingClass;
+
+/**
+ * NMSettingValueIterFn:
+ * @setting: The setting for which properties are being iterated, given to
+ * nm_setting_enumerate_values()
+ * @key: The value/property name
+ * @value: The property's value
+ * @flags: The property's flags, like %NM_SETTING_PARAM_SECRET
+ * @user_data: User data passed to nm_setting_enumerate_values()
+ */
+typedef void (*NMSettingValueIterFn) (NMSetting *setting,
+ const char *key,
+ const GValue *value,
+ GParamFlags flags,
+ gpointer user_data);
+
+
+GType nm_setting_get_type (void);
+
+GType nm_setting_lookup_type (const char *name);
+
+NMSetting *nm_setting_duplicate (NMSetting *setting);
+
+const char *nm_setting_get_name (NMSetting *setting);
+
+gboolean nm_setting_verify (NMSetting *setting,
+ NMConnection *connection,
+ GError **error);
+
+gboolean nm_setting_compare (NMSetting *a,
+ NMSetting *b,
+ NMSettingCompareFlags flags);
+
+/**
+ * NMSettingDiffResult:
+ * @NM_SETTING_DIFF_RESULT_UNKNOWN: unknown result
+ * @NM_SETTING_DIFF_RESULT_IN_A: the property is present in setting A
+ * @NM_SETTING_DIFF_RESULT_IN_B: the property is present in setting B
+ * @NM_SETTING_DIFF_RESULT_IN_A_DEFAULT: the property is present in
+ * setting A but is set to the default value. This flag is only set,
+ * if you specify @NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT.
+ * @NM_SETTING_DIFF_RESULT_IN_B_DEFAULT: analog to @NM_SETTING_DIFF_RESULT_IN_A_DEFAULT.
+ *
+ * These values indicate the result of a setting difference operation.
+ **/
+typedef enum {
+ NM_SETTING_DIFF_RESULT_UNKNOWN = 0x00000000,
+ NM_SETTING_DIFF_RESULT_IN_A = 0x00000001,
+ NM_SETTING_DIFF_RESULT_IN_B = 0x00000002,
+ NM_SETTING_DIFF_RESULT_IN_A_DEFAULT = 0x00000004,
+ NM_SETTING_DIFF_RESULT_IN_B_DEFAULT = 0x00000004,
+} NMSettingDiffResult;
+
+gboolean nm_setting_diff (NMSetting *a,
+ NMSetting *b,
+ NMSettingCompareFlags flags,
+ gboolean invert_results,
+ GHashTable **results);
+
+void nm_setting_enumerate_values (NMSetting *setting,
+ NMSettingValueIterFn func,
+ gpointer user_data);
+
+char *nm_setting_to_string (NMSetting *setting);
+
+/* Secrets */
+gboolean nm_setting_get_secret_flags (NMSetting *setting,
+ const char *secret_name,
+ NMSettingSecretFlags *out_flags,
+ GError **error);
+
+gboolean nm_setting_set_secret_flags (NMSetting *setting,
+ const char *secret_name,
+ 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-simple-connection.c b/libnm-core/nm-simple-connection.c
new file mode 100644
index 000000000..c67f62445
--- /dev/null
+++ b/libnm-core/nm-simple-connection.c
@@ -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.
+ *
+ * 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 - 2008 Novell, Inc.
+ * Copyright 2007 - 2014 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include "nm-simple-connection.h"
+#include "nm-setting-private.h"
+
+static void nm_simple_connection_interface_init (NMConnectionInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (NMSimpleConnection, nm_simple_connection, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (NM_TYPE_CONNECTION, nm_simple_connection_interface_init);
+ )
+
+static void
+nm_simple_connection_init (NMSimpleConnection *self)
+{
+}
+
+/**
+ * nm_simple_connection_new:
+ *
+ * Creates a new #NMSimpleConnection object with no #NMSetting objects. An
+ * #NMSimpleConnection does not directly represent a D-Bus-exported connection,
+ * but might be used in the process of creating a new one.
+ *
+ * Returns: (transfer full): the new empty #NMConnection object
+ **/
+NMConnection *
+nm_simple_connection_new (void)
+{
+ return (NMConnection *) g_object_new (NM_TYPE_SIMPLE_CONNECTION, NULL);
+}
+
+/**
+ * nm_simple_connection_new_from_dbus:
+ * @dict: a #GVariant of type %NM_VARIANT_TYPE_CONNECTION describing the connection
+ * @error: on unsuccessful return, an error
+ *
+ * Creates a new #NMSimpleConnection from a hash table describing the
+ * connection. See nm_connection_to_dbus() for a description of the expected
+ * hash table.
+ *
+ * Returns: (transfer full): the new #NMSimpleConnection object, populated with
+ * settings created from the values in the hash table, or %NULL if the
+ * connection failed to validate
+ **/
+NMConnection *
+nm_simple_connection_new_from_dbus (GVariant *dict, GError **error)
+{
+ NMConnection *connection;
+
+ g_return_val_if_fail (dict != NULL, NULL);
+ g_return_val_if_fail (g_variant_is_of_type (dict, NM_VARIANT_TYPE_CONNECTION), NULL);
+
+ connection = nm_simple_connection_new ();
+ if ( !nm_connection_replace_settings (connection, dict, error)
+ || !nm_connection_normalize (connection, NULL, NULL, error))
+ g_clear_object (&connection);
+ return connection;
+}
+
+/**
+ * nm_simple_connection_new_clone:
+ * @connection: the #NMConnection to clone
+ *
+ * Clones an #NMConnection as an #NMSimpleConnection.
+ *
+ * Returns: (transfer full): a new #NMConnection containing the same settings
+ * and properties as the source #NMConnection
+ **/
+NMConnection *
+nm_simple_connection_new_clone (NMConnection *connection)
+{
+ NMConnection *clone;
+
+ g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+
+ clone = nm_simple_connection_new ();
+ nm_connection_set_path (clone, nm_connection_get_path (connection));
+ nm_connection_replace_settings_from_connection (clone, connection);
+
+ return clone;
+}
+
+static void
+dispose (GObject *object)
+{
+ nm_connection_clear_secrets (NM_CONNECTION (object));
+
+ G_OBJECT_CLASS (nm_simple_connection_parent_class)->dispose (object);
+}
+
+static void
+nm_simple_connection_class_init (NMSimpleConnectionClass *simple_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (simple_class);
+
+ object_class->dispose = dispose;
+}
+
+static void
+nm_simple_connection_interface_init (NMConnectionInterface *iface)
+{
+}
diff --git a/libnm-core/nm-simple-connection.h b/libnm-core/nm-simple-connection.h
new file mode 100644
index 000000000..da6030a88
--- /dev/null
+++ b/libnm-core/nm-simple-connection.h
@@ -0,0 +1,61 @@
+/* -*- 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 2014 Red Hat, Inc.
+ */
+
+#ifndef __NM_SIMPLE_CONNECTION_H__
+#define __NM_SIMPLE_CONNECTION_H__
+
+#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
+#error "Only <NetworkManager.h> can be included directly."
+#endif
+
+#include <nm-connection.h>
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_SIMPLE_CONNECTION (nm_simple_connection_get_type ())
+#define NM_SIMPLE_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SIMPLE_CONNECTION, NMSimpleConnection))
+#define NM_SIMPLE_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SIMPLE_CONNECTION, NMSimpleConnectionClass))
+#define NM_IS_SIMPLE_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SIMPLE_CONNECTION))
+#define NM_IS_SIMPLE_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_SIMPLE_CONNECTION))
+#define NM_SIMPLE_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SIMPLE_CONNECTION, NMSimpleConnectionClass))
+
+struct _NMSimpleConnection {
+ GObject parent;
+};
+
+typedef struct {
+ GObjectClass parent_class;
+
+ /*< private >*/
+ gpointer padding[4];
+} NMSimpleConnectionClass;
+
+GType nm_simple_connection_get_type (void);
+
+NMConnection *nm_simple_connection_new (void);
+
+NMConnection *nm_simple_connection_new_from_dbus (GVariant *dict,
+ GError **error);
+
+NMConnection *nm_simple_connection_new_clone (NMConnection *connection);
+
+G_END_DECLS
+
+#endif /* __NM_SIMPLE_CONNECTION__ */
diff --git a/libnm-core/nm-utils-private.h b/libnm-core/nm-utils-private.h
new file mode 100644
index 000000000..3854d6795
--- /dev/null
+++ b/libnm-core/nm-utils-private.h
@@ -0,0 +1,51 @@
+/* -*- 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 2005 - 2014 Red Hat, Inc.
+ */
+
+#ifndef __NM_UTILS_PRIVATE_H__
+#define __NM_UTILS_PRIVATE_H__
+
+#include "nm-setting-private.h"
+
+gboolean _nm_utils_string_slist_validate (GSList *list,
+ const char **valid_values);
+
+/* D-Bus transform funcs */
+
+GVariant * _nm_utils_hwaddr_to_dbus (const GValue *prop_value);
+void _nm_utils_hwaddr_from_dbus (GVariant *dbus_value,
+ GValue *prop_value);
+
+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);
+
+GSList * _nm_utils_strv_to_slist (char **strv);
+char ** _nm_utils_slist_to_strv (GSList *slist);
+
+GPtrArray * _nm_utils_strv_to_ptrarray (char **strv);
+char ** _nm_utils_ptrarray_to_strv (GPtrArray *ptrarray);
+
+char * _nm_utils_hwaddr_canonical_or_invalid (const char *mac, gssize length);
+
+#endif
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
new file mode 100644
index 000000000..e14775ff2
--- /dev/null
+++ b/libnm-core/nm-utils.c
@@ -0,0 +1,3215 @@
+/* -*- 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 2005 - 2014 Red Hat, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <netinet/ether.h>
+#include <arpa/inet.h>
+#include <uuid/uuid.h>
+#include <libintl.h>
+#include <gmodule.h>
+#include <glib/gi18n-lib.h>
+
+#include "nm-utils.h"
+#include "nm-utils-private.h"
+#include "nm-glib-compat.h"
+#include "nm-setting-private.h"
+#include "crypto.h"
+#include "gsystem-local-alloc.h"
+#include "nm-utils-internal.h"
+
+#include "nm-setting-bond.h"
+#include "nm-setting-bridge.h"
+#include "nm-setting-infiniband.h"
+#include "nm-setting-ip6-config.h"
+#include "nm-setting-team.h"
+#include "nm-setting-vlan.h"
+#include "nm-setting-wired.h"
+#include "nm-setting-wireless.h"
+
+/* Embed the commit id in the build binary */
+static const char *const __nm_git_sha = STRLEN (NM_GIT_SHA) > 0 ? "NM_GIT_SHA:"NM_GIT_SHA : "";
+
+/**
+ * SECTION:nm-utils
+ * @short_description: Utility functions
+ *
+ * A collection of utility functions for working with SSIDs, IP addresses, Wi-Fi
+ * access points and devices, among other things.
+ */
+
+struct EncodingTriplet
+{
+ const char *encoding1;
+ const char *encoding2;
+ const char *encoding3;
+};
+
+struct IsoLangToEncodings
+{
+ const char * lang;
+ struct EncodingTriplet encodings;
+};
+
+/* 5-letter language codes */
+static const struct IsoLangToEncodings isoLangEntries5[] =
+{
+ /* Simplified Chinese */
+ { "zh_cn", {"euc-cn", "gb2312", "gb18030"} }, /* PRC */
+ { "zh_sg", {"euc-cn", "gb2312", "gb18030"} }, /* Singapore */
+
+ /* Traditional Chinese */
+ { "zh_tw", {"big5", "euc-tw", NULL} }, /* Taiwan */
+ { "zh_hk", {"big5", "euc-tw", "big5-hkcs"} },/* Hong Kong */
+ { "zh_mo", {"big5", "euc-tw", NULL} }, /* Macau */
+
+ /* Table end */
+ { NULL, {NULL, NULL, NULL} }
+};
+
+/* 2-letter language codes; we don't care about the other 3 in this table */
+static const struct IsoLangToEncodings isoLangEntries2[] =
+{
+ /* Japanese */
+ { "ja", {"euc-jp", "shift_jis", "iso-2022-jp"} },
+
+ /* Korean */
+ { "ko", {"euc-kr", "iso-2022-kr", "johab"} },
+
+ /* Thai */
+ { "th", {"iso-8859-11","windows-874", NULL} },
+
+ /* Central European */
+ { "hu", {"iso-8859-2", "windows-1250", NULL} }, /* Hungarian */
+ { "cs", {"iso-8859-2", "windows-1250", NULL} }, /* Czech */
+ { "hr", {"iso-8859-2", "windows-1250", NULL} }, /* Croatian */
+ { "pl", {"iso-8859-2", "windows-1250", NULL} }, /* Polish */
+ { "ro", {"iso-8859-2", "windows-1250", NULL} }, /* Romanian */
+ { "sk", {"iso-8859-2", "windows-1250", NULL} }, /* Slovakian */
+ { "sl", {"iso-8859-2", "windows-1250", NULL} }, /* Slovenian */
+ { "sh", {"iso-8859-2", "windows-1250", NULL} }, /* Serbo-Croatian */
+
+ /* Cyrillic */
+ { "ru", {"koi8-r", "windows-1251", "iso-8859-5"} }, /* Russian */
+ { "be", {"koi8-r", "windows-1251", "iso-8859-5"} }, /* Belorussian */
+ { "bg", {"windows-1251","koi8-r", "iso-8859-5"} }, /* Bulgarian */
+ { "mk", {"koi8-r", "windows-1251", "iso-8859-5"} }, /* Macedonian */
+ { "sr", {"koi8-r", "windows-1251", "iso-8859-5"} }, /* Serbian */
+ { "uk", {"koi8-u", "koi8-r", "windows-1251"} }, /* Ukranian */
+
+ /* Arabic */
+ { "ar", {"iso-8859-6", "windows-1256", NULL} },
+
+ /* Baltic */
+ { "et", {"iso-8859-4", "windows-1257", NULL} }, /* Estonian */
+ { "lt", {"iso-8859-4", "windows-1257", NULL} }, /* Lithuanian */
+ { "lv", {"iso-8859-4", "windows-1257", NULL} }, /* Latvian */
+
+ /* Greek */
+ { "el", {"iso-8859-7", "windows-1253", NULL} },
+
+ /* Hebrew */
+ { "he", {"iso-8859-8", "windows-1255", NULL} },
+ { "iw", {"iso-8859-8", "windows-1255", NULL} },
+
+ /* Turkish */
+ { "tr", {"iso-8859-9", "windows-1254", NULL} },
+
+ /* Table end */
+ { NULL, {NULL, NULL, NULL} }
+};
+
+
+static GHashTable * langToEncodings5 = NULL;
+static GHashTable * langToEncodings2 = NULL;
+
+static void
+init_lang_to_encodings_hash (void)
+{
+ struct IsoLangToEncodings *enc;
+
+ if (G_UNLIKELY (langToEncodings5 == NULL)) {
+ /* Five-letter codes */
+ enc = (struct IsoLangToEncodings *) &isoLangEntries5[0];
+ langToEncodings5 = g_hash_table_new (g_str_hash, g_str_equal);
+ while (enc->lang) {
+ g_hash_table_insert (langToEncodings5, (gpointer) enc->lang,
+ (gpointer) &enc->encodings);
+ enc++;
+ }
+ }
+
+ if (G_UNLIKELY (langToEncodings2 == NULL)) {
+ /* Two-letter codes */
+ enc = (struct IsoLangToEncodings *) &isoLangEntries2[0];
+ langToEncodings2 = g_hash_table_new (g_str_hash, g_str_equal);
+ while (enc->lang) {
+ g_hash_table_insert (langToEncodings2, (gpointer) enc->lang,
+ (gpointer) &enc->encodings);
+ enc++;
+ }
+ }
+}
+
+
+static gboolean
+get_encodings_for_lang (const char *lang,
+ char **encoding1,
+ char **encoding2,
+ char **encoding3)
+{
+ struct EncodingTriplet * encodings;
+ gboolean success = FALSE;
+ char * tmp_lang;
+
+ g_return_val_if_fail (lang != NULL, FALSE);
+ g_return_val_if_fail (encoding1 != NULL, FALSE);
+ g_return_val_if_fail (encoding2 != NULL, FALSE);
+ g_return_val_if_fail (encoding3 != NULL, FALSE);
+
+ *encoding1 = "iso-8859-1";
+ *encoding2 = "windows-1251";
+ *encoding3 = NULL;
+
+ init_lang_to_encodings_hash ();
+
+ tmp_lang = g_strdup (lang);
+ if ((encodings = g_hash_table_lookup (langToEncodings5, tmp_lang))) {
+ *encoding1 = (char *) encodings->encoding1;
+ *encoding2 = (char *) encodings->encoding2;
+ *encoding3 = (char *) encodings->encoding3;
+ success = TRUE;
+ }
+
+ /* Truncate tmp_lang to length of 2 */
+ if (strlen (tmp_lang) > 2)
+ tmp_lang[2] = '\0';
+ if (!success && (encodings = g_hash_table_lookup (langToEncodings2, tmp_lang))) {
+ *encoding1 = (char *) encodings->encoding1;
+ *encoding2 = (char *) encodings->encoding2;
+ *encoding3 = (char *) encodings->encoding3;
+ success = TRUE;
+ }
+
+ g_free (tmp_lang);
+ return success;
+}
+
+/* init libnm */
+
+static gboolean initialized = FALSE;
+
+static void __attribute__((constructor))
+_nm_utils_init (void)
+{
+ GModule *self;
+ gpointer func;
+
+ (void) __nm_git_sha;
+
+ if (initialized)
+ 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);
+
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+
+ g_type_init ();
+
+ _nm_dbus_errors_init ();
+}
+
+gboolean _nm_utils_is_manager_process;
+
+/* ssid helpers */
+
+/**
+ * nm_utils_ssid_to_utf8:
+ * @ssid: (array length=len): pointer to a buffer containing the SSID data
+ * @len: length of the SSID data in @ssid
+ *
+ * Wi-Fi SSIDs are byte arrays, they are _not_ strings. Thus, an SSID may
+ * contain embedded NULLs and other unprintable characters. Often it is
+ * useful to print the SSID out for debugging purposes, but that should be the
+ * _only_ use of this function. Do not use this function for any persistent
+ * storage of the SSID, since the printable SSID returned from this function
+ * cannot be converted back into the real SSID of the access point.
+ *
+ * This function does almost everything humanly possible to convert the input
+ * into a printable UTF-8 string, using roughly the following procedure:
+ *
+ * 1) if the input data is already UTF-8 safe, no conversion is performed
+ * 2) attempts to get the current system language from the LANG environment
+ * variable, and depending on the language, uses a table of alternative
+ * encodings to try. For example, if LANG=hu_HU, the table may first try
+ * the ISO-8859-2 encoding, and if that fails, try the Windows-1250 encoding.
+ * If all fallback encodings fail, replaces non-UTF-8 characters with '?'.
+ * 3) If the system language was unable to be determined, falls back to the
+ * ISO-8859-1 encoding, then to the Windows-1251 encoding.
+ * 4) If step 3 fails, replaces non-UTF-8 characters with '?'.
+ *
+ * Again, this function should be used for debugging and display purposes
+ * _only_.
+ *
+ * Returns: (transfer full): an allocated string containing a UTF-8
+ * representation of the SSID, which must be freed by the caller using g_free().
+ * Returns %NULL on errors.
+ **/
+char *
+nm_utils_ssid_to_utf8 (const guint8 *ssid, gsize len)
+{
+ char *converted = NULL;
+ char *lang, *e1 = NULL, *e2 = NULL, *e3 = NULL;
+
+ g_return_val_if_fail (ssid != NULL, NULL);
+
+ if (g_utf8_validate ((const gchar *) ssid, len, NULL))
+ return g_strndup ((const gchar *) ssid, len);
+
+ /* LANG may be a good encoding hint */
+ g_get_charset ((const char **)(&e1));
+ if ((lang = getenv ("LANG"))) {
+ char * dot;
+
+ lang = g_ascii_strdown (lang, -1);
+ if ((dot = strchr (lang, '.')))
+ *dot = '\0';
+
+ get_encodings_for_lang (lang, &e1, &e2, &e3);
+ g_free (lang);
+ }
+
+ converted = g_convert ((const gchar *) ssid, len, "UTF-8", e1, NULL, NULL, NULL);
+ if (!converted && e2)
+ converted = g_convert ((const gchar *) ssid, len, "UTF-8", e2, NULL, NULL, NULL);
+
+ if (!converted && e3)
+ converted = g_convert ((const gchar *) ssid, len, "UTF-8", e3, NULL, NULL, NULL);
+
+ if (!converted) {
+ converted = g_convert_with_fallback ((const gchar *) ssid, len,
+ "UTF-8", e1, "?", NULL, NULL, NULL);
+ }
+
+ return converted;
+}
+
+/* Shamelessly ripped from the Linux kernel ieee80211 stack */
+/**
+ * nm_utils_is_empty_ssid:
+ * @ssid: (array length=len): pointer to a buffer containing the SSID data
+ * @len: length of the SSID data in @ssid
+ *
+ * Different manufacturers use different mechanisms for not broadcasting the
+ * AP's SSID. This function attempts to detect blank/empty SSIDs using a
+ * number of known SSID-cloaking methods.
+ *
+ * Returns: %TRUE if the SSID is "empty", %FALSE if it is not
+ **/
+gboolean
+nm_utils_is_empty_ssid (const guint8 *ssid, gsize len)
+{
+ /* Single white space is for Linksys APs */
+ if (len == 1 && ssid[0] == ' ')
+ return TRUE;
+
+ /* Otherwise, if the entire ssid is 0, we assume it is hidden */
+ while (len--) {
+ if (ssid[len] != '\0')
+ return FALSE;
+ }
+ return TRUE;
+}
+
+#define ESSID_MAX_SIZE 32
+
+/**
+ * nm_utils_escape_ssid:
+ * @ssid: (array length=len): pointer to a buffer containing the SSID data
+ * @len: length of the SSID data in @ssid
+ *
+ * This function does a quick printable character conversion of the SSID, simply
+ * replacing embedded NULLs and non-printable characters with the hexadecimal
+ * representation of that character. Intended for debugging only, should not
+ * be used for display of SSIDs.
+ *
+ * Returns: pointer to the escaped SSID, which uses an internal static buffer
+ * and will be overwritten by subsequent calls to this function
+ **/
+const char *
+nm_utils_escape_ssid (const guint8 *ssid, gsize len)
+{
+ static char escaped[ESSID_MAX_SIZE * 2 + 1];
+ const guint8 *s = ssid;
+ char *d = escaped;
+
+ if (nm_utils_is_empty_ssid (ssid, len)) {
+ memcpy (escaped, "<hidden>", sizeof ("<hidden>"));
+ return escaped;
+ }
+
+ len = MIN (len, (guint32) ESSID_MAX_SIZE);
+ while (len--) {
+ if (*s == '\0') {
+ *d++ = '\\';
+ *d++ = '0';
+ s++;
+ } else {
+ *d++ = *s++;
+ }
+ }
+ *d = '\0';
+ return escaped;
+}
+
+/**
+ * nm_utils_same_ssid:
+ * @ssid1: (array length=len1): the first SSID to compare
+ * @len1: length of the SSID data in @ssid1
+ * @ssid2: (array length=len2): the second SSID to compare
+ * @len2: length of the SSID data in @ssid2
+ * @ignore_trailing_null: %TRUE to ignore one trailing NULL byte
+ *
+ * Earlier versions of the Linux kernel added a NULL byte to the end of the
+ * SSID to enable easy printing of the SSID on the console or in a terminal,
+ * but this behavior was problematic (SSIDs are simply byte arrays, not strings)
+ * and thus was changed. This function compensates for that behavior at the
+ * cost of some compatibility with odd SSIDs that may legitimately have trailing
+ * NULLs, even though that is functionally pointless.
+ *
+ * Returns: %TRUE if the SSIDs are the same, %FALSE if they are not
+ **/
+gboolean
+nm_utils_same_ssid (const guint8 *ssid1, gsize len1,
+ const guint8 *ssid2, gsize len2,
+ gboolean ignore_trailing_null)
+{
+ g_return_val_if_fail (ssid1 != NULL || len1 == 0, FALSE);
+ g_return_val_if_fail (ssid2 != NULL || len2 == 0, FALSE);
+
+ if (ssid1 == ssid2 && len1 == len2)
+ return TRUE;
+ if (!ssid1 || !ssid2)
+ return FALSE;
+
+ if (ignore_trailing_null) {
+ if (len1 && ssid1[len1 - 1] == '\0')
+ len1--;
+ if (len2 && ssid2[len2 - 1] == '\0')
+ len2--;
+ }
+
+ if (len1 != len2)
+ return FALSE;
+
+ return memcmp (ssid1, ssid2, len1) == 0 ? TRUE : FALSE;
+}
+
+gboolean
+_nm_utils_string_in_list (const char *str, const char **valid_strings)
+{
+ int i;
+
+ for (i = 0; valid_strings[i]; i++)
+ if (strcmp (str, valid_strings[i]) == 0)
+ break;
+
+ return valid_strings[i] != NULL;
+}
+
+gboolean
+_nm_utils_string_slist_validate (GSList *list, const char **valid_values)
+{
+ GSList *iter;
+
+ for (iter = list; iter; iter = iter->next) {
+ if (!_nm_utils_string_in_list ((char *) iter->data, valid_values))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * _nm_utils_hash_values_to_slist:
+ * @hash: a #GHashTable
+ *
+ * Utility function to iterate over a hash table and return
+ * it's values as a #GSList.
+ *
+ * Returns: (element-type gpointer) (transfer container): a newly allocated #GSList
+ * containing the values of the hash table. The caller must free the
+ * returned list with g_slist_free(). The hash values are not owned
+ * by the returned list.
+ **/
+GSList *
+_nm_utils_hash_values_to_slist (GHashTable *hash)
+{
+ GSList *list = NULL;
+ GHashTableIter iter;
+ void *value;
+
+ g_return_val_if_fail (hash, NULL);
+
+ g_hash_table_iter_init (&iter, hash);
+ while (g_hash_table_iter_next (&iter, NULL, &value))
+ list = g_slist_prepend (list, value);
+
+ return list;
+}
+
+GVariant *
+_nm_utils_strdict_to_dbus (const GValue *prop_value)
+{
+ GHashTable *hash;
+ GHashTableIter iter;
+ gpointer key, value;
+ GVariantBuilder builder;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
+ hash = g_value_get_boxed (prop_value);
+ if (hash) {
+ g_hash_table_iter_init (&iter, hash);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ g_variant_builder_add (&builder, "{ss}", key, value);
+ }
+
+ return g_variant_builder_end (&builder);
+}
+
+void
+_nm_utils_strdict_from_dbus (GVariant *dbus_value,
+ GValue *prop_value)
+{
+ GVariantIter iter;
+ const char *key, *value;
+ GHashTable *hash;
+
+ hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ g_variant_iter_init (&iter, dbus_value);
+ while (g_variant_iter_next (&iter, "{&s&s}", &key, &value))
+ g_hash_table_insert (hash, g_strdup (key), g_strdup (value));
+
+ g_value_take_boxed (prop_value, hash);
+}
+
+GHashTable *
+_nm_utils_copy_strdict (GHashTable *strdict)
+{
+ GHashTable *copy;
+ GHashTableIter iter;
+ gpointer key, value;
+
+ copy = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ if (strdict) {
+ g_hash_table_iter_init (&iter, strdict);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ g_hash_table_insert (copy, g_strdup (key), g_strdup (value));
+ }
+ return copy;
+}
+
+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)
+{
+ GPtrArray *copy;
+ int i;
+
+ if (!array)
+ return g_ptr_array_new_with_free_func (free_func);
+
+ copy = g_ptr_array_new_full (array->len, free_func);
+ for (i = 0; i < array->len; i++)
+ g_ptr_array_add (copy, copy_func (array->pdata[i]));
+ return copy;
+}
+
+GPtrArray *
+_nm_utils_copy_object_array (const GPtrArray *array)
+{
+ return _nm_utils_copy_array (array, g_object_ref, g_object_unref);
+}
+
+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)
+{
+ GBytes *bytes;
+
+ if (g_variant_n_children (dbus_value)) {
+ gconstpointer data;
+ gsize length;
+
+ data = g_variant_get_fixed_array (dbus_value, &length, 1);
+ bytes = g_bytes_new (data, length);
+ } else
+ bytes = NULL;
+ g_value_take_boxed (prop_value, bytes);
+}
+
+GSList *
+_nm_utils_strv_to_slist (char **strv)
+{
+ int i;
+ GSList *list = NULL;
+
+ if (strv) {
+ for (i = 0; strv[i]; i++)
+ list = g_slist_prepend (list, g_strdup (strv[i]));
+ }
+
+ return g_slist_reverse (list);
+}
+
+char **
+_nm_utils_slist_to_strv (GSList *slist)
+{
+ GSList *iter;
+ char **strv;
+ int len, i;
+
+ len = g_slist_length (slist);
+ strv = g_new (char *, len + 1);
+
+ for (i = 0, iter = slist; iter; iter = iter->next, i++)
+ strv[i] = g_strdup (iter->data);
+ strv[i] = NULL;
+
+ return strv;
+}
+
+GPtrArray *
+_nm_utils_strv_to_ptrarray (char **strv)
+{
+ GPtrArray *ptrarray;
+ int i;
+
+ ptrarray = g_ptr_array_new_with_free_func (g_free);
+
+ if (strv) {
+ for (i = 0; strv[i]; i++)
+ g_ptr_array_add (ptrarray, g_strdup (strv[i]));
+ }
+
+ return ptrarray;
+}
+
+char **
+_nm_utils_ptrarray_to_strv (GPtrArray *ptrarray)
+{
+ char **strv;
+ int i;
+
+ if (!ptrarray)
+ return g_new0 (char *, 1);
+
+ strv = g_new (char *, ptrarray->len + 1);
+
+ for (i = 0; i < ptrarray->len; i++)
+ strv[i] = g_strdup (ptrarray->pdata[i]);
+ strv[i] = NULL;
+
+ return strv;
+}
+
+/**
+ * _nm_utils_strsplit_set:
+ * @str: string to split
+ * @delimiters: string of delimiter characters
+ * @max_tokens: the maximum number of tokens to split string into. When it is
+ * less than 1, the @str is split completely.
+ *
+ * Utility function for splitting string into a string array. It is a wrapper
+ * for g_strsplit_set(), but it also removes empty strings from the vector as
+ * they are not useful in most cases.
+ *
+ * Returns: (transfer full): a newly allocated NULL-terminated array of strings.
+ * The caller must free the returned array with g_strfreev().
+ **/
+char **
+_nm_utils_strsplit_set (const char *str, const char *delimiters, int max_tokens)
+{
+ char **result;
+ uint i;
+ uint j;
+
+ result = g_strsplit_set (str, delimiters, max_tokens);
+
+ /* remove empty strings */
+ for (i = 0; result && result[i]; i++) {
+ if (*result[i] == '\0') {
+ g_free (result[i]);
+ for (j = i; result[j]; j++)
+ result[j] = result[j + 1];
+ i--;
+ }
+ }
+ return result;
+}
+
+static gboolean
+device_supports_ap_ciphers (guint32 dev_caps,
+ guint32 ap_flags,
+ gboolean static_wep)
+{
+ gboolean have_pair = FALSE;
+ gboolean have_group = FALSE;
+ /* Device needs to support at least one pairwise and one group cipher */
+
+ /* Pairwise */
+ if (static_wep) {
+ /* Static WEP only uses group ciphers */
+ have_pair = TRUE;
+ } else {
+ if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_WEP40)
+ if (ap_flags & NM_802_11_AP_SEC_PAIR_WEP40)
+ have_pair = TRUE;
+ if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_WEP104)
+ if (ap_flags & NM_802_11_AP_SEC_PAIR_WEP104)
+ have_pair = TRUE;
+ if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP)
+ if (ap_flags & NM_802_11_AP_SEC_PAIR_TKIP)
+ have_pair = TRUE;
+ if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)
+ if (ap_flags & NM_802_11_AP_SEC_PAIR_CCMP)
+ have_pair = TRUE;
+ }
+
+ /* Group */
+ if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_WEP40)
+ if (ap_flags & NM_802_11_AP_SEC_GROUP_WEP40)
+ have_group = TRUE;
+ if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_WEP104)
+ if (ap_flags & NM_802_11_AP_SEC_GROUP_WEP104)
+ have_group = TRUE;
+ if (!static_wep) {
+ if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP)
+ if (ap_flags & NM_802_11_AP_SEC_GROUP_TKIP)
+ have_group = TRUE;
+ if (dev_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)
+ if (ap_flags & NM_802_11_AP_SEC_GROUP_CCMP)
+ have_group = TRUE;
+ }
+
+ return (have_pair && have_group);
+}
+
+/**
+ * nm_utils_ap_mode_security_valid:
+ * @type: the security type to check device capabilties against,
+ * e.g. #NMU_SEC_STATIC_WEP
+ * @wifi_caps: bitfield of the capabilities of the specific Wi-Fi device, e.g.
+ * #NM_WIFI_DEVICE_CAP_CIPHER_WEP40
+ *
+ * Given a set of device capabilities, and a desired security type to check
+ * against, determines whether the combination of device capabilities and
+ * desired security type are valid for AP/Hotspot connections.
+ *
+ * Returns: %TRUE if the device capabilities are compatible with the desired
+ * @type, %FALSE if they are not.
+ **/
+gboolean
+nm_utils_ap_mode_security_valid (NMUtilsSecurityType type,
+ NMDeviceWifiCapabilities wifi_caps)
+{
+ if (!(wifi_caps & NM_WIFI_DEVICE_CAP_AP))
+ return FALSE;
+
+ /* Return TRUE for any security that wpa_supplicant's lightweight AP
+ * mode can handle: which is open, WEP, and WPA/WPA2 PSK.
+ */
+ switch (type) {
+ case NMU_SEC_NONE:
+ case NMU_SEC_STATIC_WEP:
+ case NMU_SEC_WPA_PSK:
+ case NMU_SEC_WPA2_PSK:
+ return TRUE;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+/**
+ * nm_utils_security_valid:
+ * @type: the security type to check AP flags and device capabilties against,
+ * e.g. #NMU_SEC_STATIC_WEP
+ * @wifi_caps: bitfield of the capabilities of the specific Wi-Fi device, e.g.
+ * #NM_WIFI_DEVICE_CAP_CIPHER_WEP40
+ * @have_ap: whether the @ap_flags, @ap_wpa, and @ap_rsn arguments are valid
+ * @adhoc: whether the capabilities being tested are from an Ad-Hoc AP (IBSS)
+ * @ap_flags: bitfield of AP capabilities, e.g. #NM_802_11_AP_FLAGS_PRIVACY
+ * @ap_wpa: bitfield of AP capabilties derived from the AP's WPA beacon,
+ * e.g. (#NM_802_11_AP_SEC_PAIR_TKIP | #NM_802_11_AP_SEC_KEY_MGMT_PSK)
+ * @ap_rsn: bitfield of AP capabilties derived from the AP's RSN/WPA2 beacon,
+ * e.g. (#NM_802_11_AP_SEC_PAIR_CCMP | #NM_802_11_AP_SEC_PAIR_TKIP)
+ *
+ * Given a set of device capabilities, and a desired security type to check
+ * against, determines whether the combination of device, desired security
+ * type, and AP capabilities intersect.
+ *
+ * NOTE: this function cannot handle checking security for AP/Hotspot mode;
+ * use nm_utils_ap_mode_security_valid() instead.
+ *
+ * Returns: %TRUE if the device capabilities and AP capabilties intersect and are
+ * compatible with the desired @type, %FALSE if they are not
+ **/
+gboolean
+nm_utils_security_valid (NMUtilsSecurityType type,
+ NMDeviceWifiCapabilities wifi_caps,
+ gboolean have_ap,
+ gboolean adhoc,
+ NM80211ApFlags ap_flags,
+ NM80211ApSecurityFlags ap_wpa,
+ NM80211ApSecurityFlags ap_rsn)
+{
+ gboolean good = TRUE;
+
+ if (!have_ap) {
+ if (type == NMU_SEC_NONE)
+ return TRUE;
+ if ( (type == NMU_SEC_STATIC_WEP)
+ || ((type == NMU_SEC_DYNAMIC_WEP) && !adhoc)
+ || ((type == NMU_SEC_LEAP) && !adhoc)) {
+ if (wifi_caps & (NM_WIFI_DEVICE_CAP_CIPHER_WEP40 | NM_WIFI_DEVICE_CAP_CIPHER_WEP104))
+ return TRUE;
+ else
+ return FALSE;
+ }
+ }
+
+ switch (type) {
+ case NMU_SEC_NONE:
+ g_assert (have_ap);
+ if (ap_flags & NM_802_11_AP_FLAGS_PRIVACY)
+ return FALSE;
+ if (ap_wpa || ap_rsn)
+ return FALSE;
+ break;
+ case NMU_SEC_LEAP: /* require PRIVACY bit for LEAP? */
+ if (adhoc)
+ return FALSE;
+ /* Fall through */
+ case NMU_SEC_STATIC_WEP:
+ g_assert (have_ap);
+ if (!(ap_flags & NM_802_11_AP_FLAGS_PRIVACY))
+ return FALSE;
+ if (ap_wpa || ap_rsn) {
+ if (!device_supports_ap_ciphers (wifi_caps, ap_wpa, TRUE))
+ if (!device_supports_ap_ciphers (wifi_caps, ap_rsn, TRUE))
+ return FALSE;
+ }
+ break;
+ case NMU_SEC_DYNAMIC_WEP:
+ if (adhoc)
+ return FALSE;
+ g_assert (have_ap);
+ if (ap_rsn || !(ap_flags & NM_802_11_AP_FLAGS_PRIVACY))
+ return FALSE;
+ /* Some APs broadcast minimal WPA-enabled beacons that must be handled */
+ if (ap_wpa) {
+ if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X))
+ return FALSE;
+ if (!device_supports_ap_ciphers (wifi_caps, ap_wpa, FALSE))
+ return FALSE;
+ }
+ break;
+ case NMU_SEC_WPA_PSK:
+ if (adhoc)
+ return FALSE; /* FIXME: Kernel WPA Ad-Hoc support is buggy */
+ if (!(wifi_caps & NM_WIFI_DEVICE_CAP_WPA))
+ return FALSE;
+ if (have_ap) {
+ /* Ad-Hoc WPA APs won't necessarily have the PSK flag set, and
+ * they don't have any pairwise ciphers. */
+ if (adhoc) {
+ /* coverity[dead_error_line] */
+ if ( (ap_wpa & NM_802_11_AP_SEC_GROUP_TKIP)
+ && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP))
+ return TRUE;
+ if ( (ap_wpa & NM_802_11_AP_SEC_GROUP_CCMP)
+ && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP))
+ return TRUE;
+ } else {
+ if (ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_PSK) {
+ if ( (ap_wpa & NM_802_11_AP_SEC_PAIR_TKIP)
+ && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP))
+ return TRUE;
+ if ( (ap_wpa & NM_802_11_AP_SEC_PAIR_CCMP)
+ && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP))
+ return TRUE;
+ }
+ }
+ return FALSE;
+ }
+ break;
+ case NMU_SEC_WPA2_PSK:
+ if (adhoc)
+ return FALSE; /* FIXME: Kernel WPA Ad-Hoc support is buggy */
+ if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN))
+ return FALSE;
+ if (have_ap) {
+ /* Ad-Hoc WPA APs won't necessarily have the PSK flag set, and
+ * they don't have any pairwise ciphers, nor any RSA flags yet. */
+ if (adhoc) {
+ /* coverity[dead_error_line] */
+ if (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP)
+ return TRUE;
+ if (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP)
+ return TRUE;
+ } else {
+ if (ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_PSK) {
+ if ( (ap_rsn & NM_802_11_AP_SEC_PAIR_TKIP)
+ && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_TKIP))
+ return TRUE;
+ if ( (ap_rsn & NM_802_11_AP_SEC_PAIR_CCMP)
+ && (wifi_caps & NM_WIFI_DEVICE_CAP_CIPHER_CCMP))
+ return TRUE;
+ }
+ }
+ return FALSE;
+ }
+ break;
+ case NMU_SEC_WPA_ENTERPRISE:
+ if (adhoc)
+ return FALSE;
+ if (!(wifi_caps & NM_WIFI_DEVICE_CAP_WPA))
+ return FALSE;
+ if (have_ap) {
+ if (!(ap_wpa & NM_802_11_AP_SEC_KEY_MGMT_802_1X))
+ return FALSE;
+ /* Ensure at least one WPA cipher is supported */
+ if (!device_supports_ap_ciphers (wifi_caps, ap_wpa, FALSE))
+ return FALSE;
+ }
+ break;
+ case NMU_SEC_WPA2_ENTERPRISE:
+ if (adhoc)
+ return FALSE;
+ if (!(wifi_caps & NM_WIFI_DEVICE_CAP_RSN))
+ return FALSE;
+ if (have_ap) {
+ if (!(ap_rsn & NM_802_11_AP_SEC_KEY_MGMT_802_1X))
+ return FALSE;
+ /* Ensure at least one WPA cipher is supported */
+ if (!device_supports_ap_ciphers (wifi_caps, ap_rsn, FALSE))
+ return FALSE;
+ }
+ break;
+ default:
+ good = FALSE;
+ break;
+ }
+
+ return good;
+}
+
+/**
+ * nm_utils_wep_key_valid:
+ * @key: a string that might be a WEP key
+ * @wep_type: the #NMWepKeyType type of the WEP key
+ *
+ * Checks if @key is a valid WEP key
+ *
+ * Returns: %TRUE if @key is a WEP key, %FALSE if not
+ */
+gboolean
+nm_utils_wep_key_valid (const char *key, NMWepKeyType wep_type)
+{
+ int keylen, i;
+
+ if (!key)
+ return FALSE;
+
+ keylen = strlen (key);
+ if ( wep_type == NM_WEP_KEY_TYPE_KEY
+ || wep_type == NM_WEP_KEY_TYPE_UNKNOWN) {
+ if (keylen == 10 || keylen == 26) {
+ /* Hex key */
+ for (i = 0; i < keylen; i++) {
+ if (!g_ascii_isxdigit (key[i]))
+ return FALSE;
+ }
+ } else if (keylen == 5 || keylen == 13) {
+ /* ASCII key */
+ for (i = 0; i < keylen; i++) {
+ if (!g_ascii_isprint (key[i]))
+ return FALSE;
+ }
+ } else
+ return FALSE;
+
+ } else if (wep_type == NM_WEP_KEY_TYPE_PASSPHRASE) {
+ if (!keylen || keylen > 64)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * nm_utils_wpa_psk_valid:
+ * @psk: a string that might be a WPA PSK
+ *
+ * Checks if @psk is a valid WPA PSK
+ *
+ * Returns: %TRUE if @psk is a WPA PSK, %FALSE if not
+ */
+gboolean
+nm_utils_wpa_psk_valid (const char *psk)
+{
+ int psklen, i;
+
+ if (!psk)
+ return FALSE;
+
+ psklen = strlen (psk);
+ if (psklen < 8 || psklen > 64)
+ return FALSE;
+
+ if (psklen == 64) {
+ /* Hex PSK */
+ for (i = 0; i < psklen; i++) {
+ if (!g_ascii_isxdigit (psk[i]))
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ * nm_utils_ip4_dns_to_variant:
+ * @dns: (type utf8): an array of IP address strings
+ *
+ * Utility function to convert an array of IP address strings int a #GVariant of
+ * type 'au' representing an array of IPv4 addresses.
+ *
+ * Returns: (transfer none): a new floating #GVariant representing @dns.
+ **/
+GVariant *
+nm_utils_ip4_dns_to_variant (char **dns)
+{
+ GVariantBuilder builder;
+ int i;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("au"));
+
+ if (dns) {
+ for (i = 0; dns[i]; i++) {
+ guint32 ip = 0;
+
+ inet_pton (AF_INET, dns[i], &ip);
+ g_variant_builder_add (&builder, "u", ip);
+ }
+ }
+
+ return g_variant_builder_end (&builder);
+}
+
+/**
+ * nm_utils_ip4_dns_from_variant:
+ * @value: a #GVariant of type 'au'
+ *
+ * Utility function to convert a #GVariant of type 'au' representing a list of
+ * IPv4 addresses into an array of IP address strings.
+ *
+ * Returns: (transfer full) (type utf8): a %NULL-terminated array of IP address strings.
+ **/
+char **
+nm_utils_ip4_dns_from_variant (GVariant *value)
+{
+ const guint32 *array;
+ gsize length;
+ char **dns;
+ int i;
+
+ g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("au")), NULL);
+
+ array = g_variant_get_fixed_array (value, &length, sizeof (guint32));
+ dns = g_new (char *, length + 1);
+
+ for (i = 0; i < length; i++)
+ dns[i] = g_strdup (nm_utils_inet4_ntop (array[i], NULL));
+ dns[i] = NULL;
+
+ return dns;
+}
+
+/**
+ * nm_utils_ip4_addresses_to_variant:
+ * @addresses: (element-type NMIPAddress): an array of #NMIPAddress objects
+ * @gateway: (allow-none): the gateway IP address
+ *
+ * Utility function to convert a #GPtrArray of #NMIPAddress objects representing
+ * IPv4 addresses into a #GVariant of type 'aau' representing an array of
+ * NetworkManager IPv4 addresses (which are tuples of address, prefix, and
+ * gateway). The "gateway" field of the first address will get the value of
+ * @gateway (if non-%NULL). In all of the other addresses, that field will be 0.
+ *
+ * Returns: (transfer none): a new floating #GVariant representing @addresses.
+ **/
+GVariant *
+nm_utils_ip4_addresses_to_variant (GPtrArray *addresses, const char *gateway)
+{
+ GVariantBuilder builder;
+ int i;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("aau"));
+
+ if (addresses) {
+ for (i = 0; i < addresses->len; i++) {
+ NMIPAddress *addr = addresses->pdata[i];
+ guint32 array[3];
+
+ if (nm_ip_address_get_family (addr) != AF_INET)
+ continue;
+
+ nm_ip_address_get_address_binary (addr, &array[0]);
+ array[1] = nm_ip_address_get_prefix (addr);
+ if (i == 0 && gateway)
+ inet_pton (AF_INET, gateway, &array[2]);
+ else
+ array[2] = 0;
+
+ g_variant_builder_add (&builder, "@au",
+ g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
+ array, 3, sizeof (guint32)));
+ }
+ }
+
+ return g_variant_builder_end (&builder);
+}
+
+/**
+ * nm_utils_ip4_addresses_from_variant:
+ * @value: a #GVariant of type 'aau'
+ * @out_gateway: (out) (allow-none) (transfer full): on return, will contain the IP gateway
+ *
+ * Utility function to convert a #GVariant of type 'aau' representing a list of
+ * NetworkManager IPv4 addresses (which are tuples of address, prefix, and
+ * gateway) into a #GPtrArray of #NMIPAddress objects. The "gateway" field of
+ * the first address (if set) will be returned in @out_gateway; the "gateway" fields
+ * of the other addresses are ignored.
+ *
+ * Returns: (transfer full) (element-type NMIPAddress): a newly allocated
+ * #GPtrArray of #NMIPAddress objects
+ **/
+GPtrArray *
+nm_utils_ip4_addresses_from_variant (GVariant *value, char **out_gateway)
+{
+ GPtrArray *addresses;
+ GVariantIter iter;
+ GVariant *addr_var;
+
+ g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("aau")), NULL);
+
+ if (out_gateway)
+ *out_gateway = NULL;
+
+ g_variant_iter_init (&iter, value);
+ addresses = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_address_unref);
+
+ while (g_variant_iter_next (&iter, "@au", &addr_var)) {
+ const guint32 *addr_array;
+ gsize length;
+ NMIPAddress *addr;
+ GError *error = NULL;
+
+ addr_array = g_variant_get_fixed_array (addr_var, &length, sizeof (guint32));
+ if (length < 3) {
+ g_warning ("Ignoring invalid IP4 address");
+ g_variant_unref (addr_var);
+ continue;
+ }
+
+ addr = nm_ip_address_new_binary (AF_INET, &addr_array[0], addr_array[1], &error);
+ if (addr) {
+ g_ptr_array_add (addresses, addr);
+
+ if (addr_array[2] && out_gateway && !*out_gateway)
+ *out_gateway = g_strdup (nm_utils_inet4_ntop (addr_array[2], NULL));
+ } else {
+ g_warning ("Ignoring invalid IP4 address: %s", error->message);
+ g_clear_error (&error);
+ }
+
+ g_variant_unref (addr_var);
+ }
+
+ return addresses;
+}
+
+/**
+ * nm_utils_ip4_routes_to_variant:
+ * @routes: (element-type NMIPRoute): an array of #NMIP4Route objects
+ *
+ * Utility function to convert a #GPtrArray of #NMIPRoute objects representing
+ * IPv4 routes into a #GVariant of type 'aau' representing an array of
+ * NetworkManager IPv4 routes (which are tuples of route, prefix, next hop, and
+ * metric).
+ *
+ * Returns: (transfer none): a new floating #GVariant representing @routes.
+ **/
+GVariant *
+nm_utils_ip4_routes_to_variant (GPtrArray *routes)
+{
+ GVariantBuilder builder;
+ int i;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("aau"));
+
+ if (routes) {
+ for (i = 0; i < routes->len; i++) {
+ NMIPRoute *route = routes->pdata[i];
+ guint32 array[4];
+
+ if (nm_ip_route_get_family (route) != AF_INET)
+ continue;
+
+ nm_ip_route_get_dest_binary (route, &array[0]);
+ array[1] = nm_ip_route_get_prefix (route);
+ nm_ip_route_get_next_hop_binary (route, &array[2]);
+ /* The old routes format uses "0" for default, not "-1" */
+ array[3] = MAX (0, nm_ip_route_get_metric (route));
+
+ g_variant_builder_add (&builder, "@au",
+ g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
+ array, 4, sizeof (guint32)));
+ }
+ }
+
+ return g_variant_builder_end (&builder);
+}
+
+/**
+ * nm_utils_ip4_routes_from_variant:
+ * @value: #GVariant of type 'aau'
+ *
+ * Utility function to convert a #GVariant of type 'aau' representing an array
+ * of NetworkManager IPv4 routes (which are tuples of route, prefix, next hop,
+ * and metric) into a #GPtrArray of #NMIPRoute objects.
+ *
+ * Returns: (transfer full) (element-type NMIPRoute): a newly allocated
+ * #GPtrArray of #NMIPRoute objects
+ **/
+GPtrArray *
+nm_utils_ip4_routes_from_variant (GVariant *value)
+{
+ GVariantIter iter;
+ GVariant *route_var;
+ GPtrArray *routes;
+
+ g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("aau")), NULL);
+
+ g_variant_iter_init (&iter, value);
+ routes = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_route_unref);
+
+ while (g_variant_iter_next (&iter, "@au", &route_var)) {
+ const guint32 *route_array;
+ gsize length;
+ NMIPRoute *route;
+ GError *error = NULL;
+
+ route_array = g_variant_get_fixed_array (route_var, &length, sizeof (guint32));
+ if (length < 4) {
+ g_warning ("Ignoring invalid IP4 route");
+ g_variant_unref (route_var);
+ continue;
+ }
+
+ route = nm_ip_route_new_binary (AF_INET,
+ &route_array[0],
+ route_array[1],
+ &route_array[2],
+ /* The old routes format uses "0" for default, not "-1" */
+ route_array[3] ? (gint64) route_array[3] : -1,
+ &error);
+ if (route)
+ g_ptr_array_add (routes, route);
+ else {
+ g_warning ("Ignoring invalid IP4 route: %s", error->message);
+ g_clear_error (&error);
+ }
+ g_variant_unref (route_var);
+ }
+
+ return routes;
+}
+
+/**
+ * nm_utils_ip4_netmask_to_prefix:
+ * @netmask: an IPv4 netmask in network byte order
+ *
+ * Returns: the CIDR prefix represented by the netmask
+ **/
+guint32
+nm_utils_ip4_netmask_to_prefix (guint32 netmask)
+{
+ guint32 prefix;
+ guint8 v;
+ const guint8 *p = (guint8 *) &netmask;
+
+ if (p[3]) {
+ prefix = 24;
+ v = p[3];
+ } else if (p[2]) {
+ prefix = 16;
+ v = p[2];
+ } else if (p[1]) {
+ prefix = 8;
+ v = p[1];
+ } else {
+ prefix = 0;
+ v = p[0];
+ }
+
+ while (v) {
+ prefix++;
+ v <<= 1;
+ }
+
+ return prefix;
+}
+
+/**
+ * nm_utils_ip4_prefix_to_netmask:
+ * @prefix: a CIDR prefix
+ *
+ * Returns: the netmask represented by the prefix, in network byte order
+ **/
+guint32
+nm_utils_ip4_prefix_to_netmask (guint32 prefix)
+{
+ return prefix < 32 ? ~htonl(0xFFFFFFFF >> prefix) : 0xFFFFFFFF;
+}
+
+
+/**
+ * nm_utils_ip4_get_default_prefix:
+ * @ip: an IPv4 address (in network byte order)
+ *
+ * When the Internet was originally set up, various ranges of IP addresses were
+ * segmented into three network classes: A, B, and C. This function will return
+ * a prefix that is associated with the IP address specified defining where it
+ * falls in the predefined classes.
+ *
+ * Returns: the default class prefix for the given IP
+ **/
+/* The function is originally from ipcalc.c of Red Hat's initscripts. */
+guint32
+nm_utils_ip4_get_default_prefix (guint32 ip)
+{
+ if (((ntohl (ip) & 0xFF000000) >> 24) <= 127)
+ return 8; /* Class A - 255.0.0.0 */
+ else if (((ntohl (ip) & 0xFF000000) >> 24) <= 191)
+ return 16; /* Class B - 255.255.0.0 */
+
+ return 24; /* Class C - 255.255.255.0 */
+}
+
+/**
+ * nm_utils_ip6_dns_to_variant:
+ * @dns: (type utf8): an array of IP address strings
+ *
+ * Utility function to convert an array of IP address strings int a #GVariant of
+ * type 'aay' representing an array of IPv6 addresses.
+ *
+ * Returns: (transfer none): a new floating #GVariant representing @dns.
+ **/
+GVariant *
+nm_utils_ip6_dns_to_variant (char **dns)
+{
+ GVariantBuilder builder;
+ int i;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("aay"));
+
+ if (dns) {
+ for (i = 0; dns[i]; i++) {
+ struct in6_addr ip;
+
+ inet_pton (AF_INET6, dns[i], &ip);
+ g_variant_builder_add (&builder, "@ay",
+ g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+ &ip, sizeof (ip), 1));
+ }
+ }
+
+ return g_variant_builder_end (&builder);
+}
+
+/**
+ * nm_utils_ip6_dns_from_variant:
+ * @value: a #GVariant of type 'aay'
+ *
+ * Utility function to convert a #GVariant of type 'aay' representing a list of
+ * IPv6 addresses into an array of IP address strings.
+ *
+ * Returns: (transfer full) (type utf8): a %NULL-terminated array of IP address strings.
+ **/
+char **
+nm_utils_ip6_dns_from_variant (GVariant *value)
+{
+ GVariantIter iter;
+ GVariant *ip_var;
+ char **dns;
+ int i;
+
+ g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("aay")), NULL);
+
+ dns = g_new (char *, g_variant_n_children (value) + 1);
+
+ g_variant_iter_init (&iter, value);
+ i = 0;
+ while (g_variant_iter_next (&iter, "@ay", &ip_var)) {
+ gsize length;
+ const struct in6_addr *ip = g_variant_get_fixed_array (ip_var, &length, 1);
+
+ if (length != sizeof (struct in6_addr)) {
+ g_warning ("%s: ignoring invalid IP6 address of length %d",
+ __func__, (int) length);
+ g_variant_unref (ip_var);
+ continue;
+ }
+
+ dns[i++] = g_strdup (nm_utils_inet6_ntop (ip, NULL));
+ g_variant_unref (ip_var);
+ }
+ dns[i] = NULL;
+
+ return dns;
+}
+
+/**
+ * nm_utils_ip6_addresses_to_variant:
+ * @addresses: (element-type NMIPAddress): an array of #NMIPAddress objects
+ * @gateway: (allow-none): the gateway IP address
+ *
+ * Utility function to convert a #GPtrArray of #NMIPAddress objects representing
+ * IPv6 addresses into a #GVariant of type 'a(ayuay)' representing an array of
+ * NetworkManager IPv6 addresses (which are tuples of address, prefix, and
+ * gateway). The "gateway" field of the first address will get the value of
+ * @gateway (if non-%NULL). In all of the other addresses, that field will be
+ * all 0s.
+ *
+ * Returns: (transfer none): a new floating #GVariant representing @addresses.
+ **/
+GVariant *
+nm_utils_ip6_addresses_to_variant (GPtrArray *addresses, const char *gateway)
+{
+ GVariantBuilder builder;
+ int i;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ayuay)"));
+
+ if (addresses) {
+ for (i = 0; i < addresses->len; i++) {
+ NMIPAddress *addr = addresses->pdata[i];
+ struct in6_addr ip_bytes, gateway_bytes;
+ GVariant *ip_var, *gateway_var;
+ guint32 prefix;
+
+ if (nm_ip_address_get_family (addr) != AF_INET6)
+ continue;
+
+ nm_ip_address_get_address_binary (addr, &ip_bytes);
+ ip_var = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, &ip_bytes, 16, 1);
+
+ prefix = nm_ip_address_get_prefix (addr);
+
+ if (i == 0 && gateway)
+ inet_pton (AF_INET6, gateway, &gateway_bytes);
+ else
+ memset (&gateway_bytes, 0, sizeof (gateway_bytes));
+ gateway_var = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, &gateway_bytes, 16, 1);
+
+ g_variant_builder_add (&builder, "(@ayu@ay)", ip_var, prefix, gateway_var);
+ }
+ }
+
+ return g_variant_builder_end (&builder);
+}
+
+/**
+ * nm_utils_ip6_addresses_from_variant:
+ * @value: a #GVariant of type 'a(ayuay)'
+ * @out_gateway: (out) (allow-none) (transfer full): on return, will contain the IP gateway
+ *
+ * Utility function to convert a #GVariant of type 'a(ayuay)' representing a
+ * list of NetworkManager IPv6 addresses (which are tuples of address, prefix,
+ * and gateway) into a #GPtrArray of #NMIPAddress objects. The "gateway" field
+ * of the first address (if set) will be returned in @out_gateway; the "gateway"
+ * fields of the other addresses are ignored.
+ *
+ * Returns: (transfer full) (element-type NMIPAddress): a newly allocated
+ * #GPtrArray of #NMIPAddress objects
+ **/
+GPtrArray *
+nm_utils_ip6_addresses_from_variant (GVariant *value, char **out_gateway)
+{
+ GVariantIter iter;
+ GVariant *addr_var, *gateway_var;
+ guint32 prefix;
+ GPtrArray *addresses;
+
+ g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("a(ayuay)")), NULL);
+
+ if (out_gateway)
+ *out_gateway = NULL;
+
+ g_variant_iter_init (&iter, value);
+ addresses = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_address_unref);
+
+ while (g_variant_iter_next (&iter, "(@ayu@ay)", &addr_var, &prefix, &gateway_var)) {
+ NMIPAddress *addr;
+ const struct in6_addr *addr_bytes, *gateway_bytes;
+ gsize addr_len, gateway_len;
+ GError *error = NULL;
+
+ if ( !g_variant_is_of_type (addr_var, G_VARIANT_TYPE_BYTESTRING)
+ || !g_variant_is_of_type (gateway_var, G_VARIANT_TYPE_BYTESTRING)) {
+ g_warning ("%s: ignoring invalid IP6 address structure", __func__);
+ goto next;
+ }
+
+ addr_bytes = g_variant_get_fixed_array (addr_var, &addr_len, 1);
+ if (addr_len != 16) {
+ g_warning ("%s: ignoring invalid IP6 address of length %d",
+ __func__, (int) addr_len);
+ goto next;
+ }
+
+ addr = nm_ip_address_new_binary (AF_INET6, addr_bytes, prefix, &error);
+ if (addr) {
+ g_ptr_array_add (addresses, addr);
+
+ if (out_gateway && !*out_gateway) {
+ gateway_bytes = g_variant_get_fixed_array (gateway_var, &gateway_len, 1);
+ if (gateway_len != 16) {
+ g_warning ("%s: ignoring invalid IP6 address of length %d",
+ __func__, (int) gateway_len);
+ goto next;
+ }
+ if (!IN6_IS_ADDR_UNSPECIFIED (gateway_bytes))
+ *out_gateway = g_strdup (nm_utils_inet6_ntop (gateway_bytes, NULL));
+ }
+ } else {
+ g_warning ("Ignoring invalid IP4 address: %s", error->message);
+ g_clear_error (&error);
+ }
+
+ next:
+ g_variant_unref (addr_var);
+ g_variant_unref (gateway_var);
+ }
+
+ return addresses;
+}
+
+/**
+ * nm_utils_ip6_routes_to_variant:
+ * @routes: (element-type NMIPRoute): an array of #NMIPRoute objects
+ *
+ * Utility function to convert a #GPtrArray of #NMIPRoute objects representing
+ * IPv6 routes into a #GVariant of type 'a(ayuayu)' representing an array of
+ * NetworkManager IPv6 routes (which are tuples of route, prefix, next hop, and
+ * metric).
+ *
+ * Returns: (transfer none): a new floating #GVariant representing @routes.
+ **/
+GVariant *
+nm_utils_ip6_routes_to_variant (GPtrArray *routes)
+{
+ GVariantBuilder builder;
+ int i;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ayuayu)"));
+
+ if (routes) {
+ for (i = 0; i < routes->len; i++) {
+ NMIPRoute *route = routes->pdata[i];
+ struct in6_addr dest_bytes, next_hop_bytes;
+ GVariant *dest, *next_hop;
+ guint32 prefix, metric;
+
+ if (nm_ip_route_get_family (route) != AF_INET6)
+ continue;
+
+ nm_ip_route_get_dest_binary (route, &dest_bytes);
+ dest = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, &dest_bytes, 16, 1);
+ prefix = nm_ip_route_get_prefix (route);
+ nm_ip_route_get_next_hop_binary (route, &next_hop_bytes);
+ next_hop = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, &next_hop_bytes, 16, 1);
+ /* The old routes format uses "0" for default, not "-1" */
+ metric = MAX (0, nm_ip_route_get_metric (route));
+
+ g_variant_builder_add (&builder, "(@ayu@ayu)", dest, prefix, next_hop, metric);
+ }
+ }
+
+ return g_variant_builder_end (&builder);
+}
+
+/**
+ * nm_utils_ip6_routes_from_variant:
+ * @value: #GVariant of type 'a(ayuayu)'
+ *
+ * Utility function to convert a #GVariant of type 'a(ayuayu)' representing an
+ * array of NetworkManager IPv6 routes (which are tuples of route, prefix, next
+ * hop, and metric) into a #GPtrArray of #NMIPRoute objects.
+ *
+ * Returns: (transfer full) (element-type NMIPRoute): a newly allocated
+ * #GPtrArray of #NMIPRoute objects
+ **/
+GPtrArray *
+nm_utils_ip6_routes_from_variant (GVariant *value)
+{
+ GPtrArray *routes;
+ GVariantIter iter;
+ GVariant *dest_var, *next_hop_var;
+ const struct in6_addr *dest, *next_hop;
+ gsize dest_len, next_hop_len;
+ guint32 prefix, metric;
+
+ g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("a(ayuayu)")), NULL);
+
+ routes = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_route_unref);
+
+ g_variant_iter_init (&iter, value);
+ while (g_variant_iter_next (&iter, "(@ayu@ayu)", &dest_var, &prefix, &next_hop_var, &metric)) {
+ NMIPRoute *route;
+ GError *error = NULL;
+
+ if ( !g_variant_is_of_type (dest_var, G_VARIANT_TYPE_BYTESTRING)
+ || !g_variant_is_of_type (next_hop_var, G_VARIANT_TYPE_BYTESTRING)) {
+ g_warning ("%s: ignoring invalid IP6 address structure", __func__);
+ goto next;
+ }
+
+ dest = g_variant_get_fixed_array (dest_var, &dest_len, 1);
+ if (dest_len != 16) {
+ g_warning ("%s: ignoring invalid IP6 address of length %d",
+ __func__, (int) dest_len);
+ goto next;
+ }
+
+ next_hop = g_variant_get_fixed_array (next_hop_var, &next_hop_len, 1);
+ if (next_hop_len != 16) {
+ g_warning ("%s: ignoring invalid IP6 address of length %d",
+ __func__, (int) next_hop_len);
+ goto next;
+ }
+
+ route = nm_ip_route_new_binary (AF_INET6, dest, prefix, next_hop,
+ metric ? (gint64) metric : -1,
+ &error);
+ if (route)
+ g_ptr_array_add (routes, route);
+ else {
+ g_warning ("Ignoring invalid IP6 route: %s", error->message);
+ g_clear_error (&error);
+ }
+
+ next:
+ g_variant_unref (dest_var);
+ g_variant_unref (next_hop_var);
+ }
+
+ return routes;
+}
+
+/**
+ * nm_utils_ip_addresses_to_variant:
+ * @addresses: (element-type NMIPAddress): an array of #NMIPAddress objects
+ *
+ * Utility function to convert a #GPtrArray of #NMIPAddress objects representing
+ * IPv4 or IPv6 addresses into a #GVariant of type 'aa{sv}' representing an
+ * array of new-style NetworkManager IP addresses. All addresses will include
+ * "address" (an IP address string), and "prefix" (a uint). Some addresses may
+ * include additional attributes.
+ *
+ * Returns: (transfer none): a new floating #GVariant representing @addresses.
+ **/
+GVariant *
+nm_utils_ip_addresses_to_variant (GPtrArray *addresses)
+{
+ GVariantBuilder builder;
+ int i;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}"));
+
+ if (addresses) {
+ for (i = 0; i < addresses->len; i++) {
+ NMIPAddress *addr = addresses->pdata[i];
+ GVariantBuilder addr_builder;
+ char **names;
+ int n;
+
+ g_variant_builder_init (&addr_builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (&addr_builder, "{sv}",
+ "address",
+ g_variant_new_string (nm_ip_address_get_address (addr)));
+ g_variant_builder_add (&addr_builder, "{sv}",
+ "prefix",
+ g_variant_new_uint32 (nm_ip_address_get_prefix (addr)));
+
+ names = nm_ip_address_get_attribute_names (addr);
+ for (n = 0; names[n]; n++) {
+ g_variant_builder_add (&addr_builder, "{sv}",
+ names[n],
+ nm_ip_address_get_attribute (addr, names[n]));
+ }
+ g_strfreev (names);
+
+ g_variant_builder_add (&builder, "a{sv}", &addr_builder);
+ }
+ }
+
+ return g_variant_builder_end (&builder);
+}
+
+/**
+ * nm_utils_ip_addresses_from_variant:
+ * @value: a #GVariant of type 'aa{sv}'
+ * @family: an IP address family
+ *
+ * Utility function to convert a #GVariant representing a list of new-style
+ * NetworkManager IPv4 or IPv6 addresses (as described in the documentation for
+ * nm_utils_ip_addresses_to_variant()) into a #GPtrArray of #NMIPAddress
+ * objects.
+ *
+ * Returns: (transfer full) (element-type NMIPAddress): a newly allocated
+ * #GPtrArray of #NMIPAddress objects
+ **/
+GPtrArray *
+nm_utils_ip_addresses_from_variant (GVariant *value,
+ int family)
+{
+ GPtrArray *addresses;
+ GVariantIter iter, attrs_iter;
+ GVariant *addr_var;
+ const char *ip;
+ guint32 prefix;
+ const char *attr_name;
+ GVariant *attr_val;
+ NMIPAddress *addr;
+ GError *error = NULL;
+
+ g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("aa{sv}")), NULL);
+
+ g_variant_iter_init (&iter, value);
+ addresses = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_address_unref);
+
+ while (g_variant_iter_next (&iter, "@a{sv}", &addr_var)) {
+ if ( !g_variant_lookup (addr_var, "address", "&s", &ip)
+ || !g_variant_lookup (addr_var, "prefix", "u", &prefix)) {
+ g_warning ("Ignoring invalid address");
+ g_variant_unref (addr_var);
+ continue;
+ }
+
+ addr = nm_ip_address_new (family, ip, prefix, &error);
+ if (!addr) {
+ g_warning ("Ignoring invalid address: %s", error->message);
+ g_clear_error (&error);
+ g_variant_unref (addr_var);
+ continue;
+ }
+
+ g_variant_iter_init (&attrs_iter, addr_var);
+ while (g_variant_iter_next (&attrs_iter, "{&sv}", &attr_name, &attr_val)) {
+ if ( strcmp (attr_name, "address") != 0
+ && strcmp (attr_name, "prefix") != 0)
+ nm_ip_address_set_attribute (addr, attr_name, attr_val);
+ g_variant_unref (attr_val);
+ }
+
+ g_ptr_array_add (addresses, addr);
+ }
+
+ return addresses;
+}
+
+/**
+ * nm_utils_ip_routes_to_variant:
+ * @routes: (element-type NMIPRoute): an array of #NMIPRoute objects
+ *
+ * Utility function to convert a #GPtrArray of #NMIPRoute objects representing
+ * IPv4 or IPv6 routes into a #GVariant of type 'aa{sv}' representing an array
+ * of new-style NetworkManager IP routes (which are tuples of destination,
+ * prefix, next hop, metric, and additional attributes).
+ *
+ * Returns: (transfer none): a new floating #GVariant representing @routes.
+ **/
+GVariant *
+nm_utils_ip_routes_to_variant (GPtrArray *routes)
+{
+ GVariantBuilder builder;
+ int i;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("aa{sv}"));
+
+ if (routes) {
+ for (i = 0; i < routes->len; i++) {
+ NMIPRoute *route = routes->pdata[i];
+ GVariantBuilder route_builder;
+ char **names;
+ int n;
+
+ g_variant_builder_init (&route_builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (&route_builder, "{sv}",
+ "dest",
+ g_variant_new_string (nm_ip_route_get_dest (route)));
+ g_variant_builder_add (&route_builder, "{sv}",
+ "prefix",
+ g_variant_new_uint32 (nm_ip_route_get_prefix (route)));
+ if (nm_ip_route_get_next_hop (route)) {
+ g_variant_builder_add (&route_builder, "{sv}",
+ "next-hop",
+ g_variant_new_string (nm_ip_route_get_next_hop (route)));
+ }
+ if (nm_ip_route_get_metric (route) != -1) {
+ g_variant_builder_add (&route_builder, "{sv}",
+ "metric",
+ g_variant_new_uint32 ((guint32) nm_ip_route_get_metric (route)));
+ }
+
+ names = nm_ip_route_get_attribute_names (route);
+ for (n = 0; names[n]; n++) {
+ g_variant_builder_add (&route_builder, "{sv}",
+ names[n],
+ nm_ip_route_get_attribute (route, names[n]));
+ }
+ g_strfreev (names);
+
+ g_variant_builder_add (&builder, "a{sv}", &route_builder);
+ }
+ }
+
+ return g_variant_builder_end (&builder);
+}
+
+/**
+ * nm_utils_ip_routes_from_variant:
+ * @value: a #GVariant of type 'aa{sv}'
+ * @family: an IP address family
+ *
+ * Utility function to convert a #GVariant representing a list of new-style
+ * NetworkManager IPv4 or IPv6 addresses (which are tuples of destination,
+ * prefix, next hop, metric, and additional attributes) into a #GPtrArray of
+ * #NMIPRoute objects.
+ *
+ * Returns: (transfer full) (element-type NMIPRoute): a newly allocated
+ * #GPtrArray of #NMIPRoute objects
+ **/
+GPtrArray *
+nm_utils_ip_routes_from_variant (GVariant *value,
+ int family)
+{
+ GPtrArray *routes;
+ GVariantIter iter, attrs_iter;
+ GVariant *route_var;
+ const char *dest, *next_hop;
+ guint32 prefix, metric32;
+ gint64 metric;
+ const char *attr_name;
+ GVariant *attr_val;
+ NMIPRoute *route;
+ GError *error = NULL;
+
+ g_return_val_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE ("aa{sv}")), NULL);
+
+ g_variant_iter_init (&iter, value);
+ routes = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_route_unref);
+
+ while (g_variant_iter_next (&iter, "@a{sv}", &route_var)) {
+ if ( !g_variant_lookup (route_var, "dest", "&s", &dest)
+ || !g_variant_lookup (route_var, "prefix", "u", &prefix)) {
+ g_warning ("Ignoring invalid address");
+ g_variant_unref (route_var);
+ continue;
+ }
+ if (!g_variant_lookup (route_var, "next-hop", "&s", &next_hop))
+ next_hop = NULL;
+ if (g_variant_lookup (route_var, "metric", "u", &metric32))
+ metric = metric32;
+ else
+ metric = -1;
+
+ route = nm_ip_route_new (family, dest, prefix, next_hop, metric, &error);
+ if (!route) {
+ g_warning ("Ignoring invalid route: %s", error->message);
+ g_clear_error (&error);
+ g_variant_unref (route_var);
+ continue;
+ }
+
+ g_variant_iter_init (&attrs_iter, route_var);
+ while (g_variant_iter_next (&attrs_iter, "{&sv}", &attr_name, &attr_val)) {
+ if ( strcmp (attr_name, "dest") != 0
+ && strcmp (attr_name, "prefix") != 0
+ && strcmp (attr_name, "next-hop") != 0
+ && strcmp (attr_name, "metric") != 0)
+ nm_ip_route_set_attribute (route, attr_name, attr_val);
+ g_variant_unref (attr_val);
+ }
+
+ g_ptr_array_add (routes, route);
+ }
+
+ return routes;
+}
+
+/**
+ * nm_utils_uuid_generate:
+ *
+ * Returns: a newly allocated UUID suitable for use as the #NMSettingConnection
+ * object's #NMSettingConnection:id: property. Should be freed with g_free()
+ **/
+char *
+nm_utils_uuid_generate (void)
+{
+ uuid_t uuid;
+ char *buf;
+
+ buf = g_malloc0 (37);
+ uuid_generate_random (uuid);
+ uuid_unparse_lower (uuid, &buf[0]);
+ return buf;
+}
+
+/**
+ * nm_utils_uuid_generate_from_string:
+ * @s: a string to use as the seed for the UUID
+ * @slen: if negative, treat @s as zero terminated C string.
+ * Otherwise, assume the length as given (and allow @s to be
+ * non-null terminated or contain '\0').
+ * @uuid_type: a type identifier which UUID format to generate.
+ * @type_args: additional arguments, depending on the uuid_type
+ *
+ * For a given @s, this function will always return the same UUID.
+ *
+ * Returns: a newly allocated UUID suitable for use as the #NMSettingConnection
+ * object's #NMSettingConnection:id: property
+ **/
+char *
+nm_utils_uuid_generate_from_string (const char *s, gssize slen, int uuid_type, gpointer type_args)
+{
+ uuid_t uuid;
+ char *buf;
+
+ g_return_val_if_fail (slen == 0 || s, FALSE);
+
+ 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);
+
+ switch (uuid_type) {
+ case NM_UTILS_UUID_TYPE_LEGACY:
+ crypto_md5_hash (NULL, 0, s, slen, (char *) uuid, sizeof (uuid));
+ break;
+ case NM_UTILS_UUID_TYPE_VARIANT3: {
+ uuid_t ns_uuid = { 0 };
+
+ if (type_args) {
+ /* type_args can be a name space UUID. Interpret it as (char *) */
+ if (uuid_parse ((char *) type_args, ns_uuid) != 0)
+ g_return_val_if_reached (NULL);
+ }
+
+ crypto_md5_hash (s, slen, (char *) ns_uuid, sizeof (ns_uuid), (char *) uuid, sizeof (uuid));
+
+ uuid[6] = (uuid[6] & 0x0F) | 0x30;
+ uuid[8] = (uuid[8] & 0x3F) | 0x80;
+ break;
+ }
+ default:
+ g_return_val_if_reached (NULL);
+ }
+
+ buf = g_malloc0 (37);
+ uuid_unparse_lower (uuid, &buf[0]);
+
+ return buf;
+}
+
+/**
+ * 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[])
+{
+ const char *ext;
+ int i;
+
+ ext = strrchr (filename, '.');
+ if (!ext)
+ return FALSE;
+
+ for (i = 0; extensions[i]; i++) {
+ if (!g_ascii_strcasecmp (ext, extensions[i]))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ * nm_utils_file_is_certificate:
+ * @filename: name of the file to test
+ *
+ * Tests if @filename has a valid extension for an X.509 certificate file
+ * (".cer", ".crt", ".der", or ".pem"), and contains a certificate in a format
+ * recognized by NetworkManager.
+ *
+ * Returns: %TRUE if the file is a certificate, %FALSE if it is not
+ **/
+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;
+
+ 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);
+
+ return file_format = NM_CRYPTO_FILE_FORMAT_X509;
+}
+
+/**
+ * nm_utils_file_is_private_key:
+ * @filename: name of the file to test
+ * @out_encrypted: (out): on return, whether the file is encrypted
+ *
+ * Tests if @filename has a valid extension for an X.509 private key file
+ * (".der", ".key", ".pem", or ".p12"), and contains a private key in a format
+ * recognized by NetworkManager.
+ *
+ * Returns: %TRUE if the file is a private key, %FALSE if it is not
+ **/
+gboolean
+nm_utils_file_is_private_key (const char *filename, gboolean *out_encrypted)
+{
+ const char *extensions[] = { ".der", ".pem", ".p12", ".key", NULL };
+
+ g_return_val_if_fail (filename != NULL, FALSE);
+ g_return_val_if_fail (out_encrypted == NULL || *out_encrypted == FALSE, FALSE);
+
+ if (!file_has_extension (filename, extensions))
+ return FALSE;
+
+ return crypto_verify_private_key (filename, NULL, out_encrypted, NULL) != NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+}
+
+/**
+ * nm_utils_file_is_pkcs12:
+ * @filename: name of the file to test
+ *
+ * Tests if @filename is a PKCS#<!-- -->12 file.
+ *
+ * Returns: %TRUE if the file is PKCS#<!-- -->12, %FALSE if it is not
+ **/
+gboolean
+nm_utils_file_is_pkcs12 (const char *filename)
+{
+ g_return_val_if_fail (filename != NULL, FALSE);
+
+ return crypto_is_pkcs12_file (filename, NULL);
+}
+
+/**********************************************************************************************/
+
+/**
+ * nm_utils_file_search_in_paths:
+ * @progname: the helper program name, like "iptables"
+ * Must be a non-empty string, without path separator (/).
+ * @try_first: (allow-none): a custom path to try first before searching.
+ * It is silently ignored if it is empty or not an absolute path.
+ * @paths: (allow-none): a %NULL terminated list of search paths.
+ * Can be empty or %NULL, in which case only @try_first is checked.
+ * @file_test_flags: the flags passed to g_file_test() when searching
+ * for @progname. Set it to 0 to skip the g_file_test().
+ * @predicate: (scope call): if given, pass the file name to this function
+ * for additional checks. This check is performed after the check for
+ * @file_test_flags. You cannot omit both @file_test_flags and @predicate.
+ * @user_data: (closure): (allow-none): user data for @predicate function.
+ * @error: on failure, a "not found" error using @error_domain and @error_code
+ *
+ * Searches for a @progname file in a list of search @paths.
+ *
+ * Returns: (transfer none): the full path to the helper, if found, or %NULL if not found.
+ * The returned string is not owned by the caller, but later
+ * invocations of the function might overwrite it.
+ */
+const char *
+nm_utils_file_search_in_paths (const char *progname,
+ const char *try_first,
+ const char *const *paths,
+ GFileTest file_test_flags,
+ NMUtilsFileSearchInPathsPredicate predicate,
+ gpointer user_data,
+ GError **error)
+{
+ GString *tmp;
+ const char *ret;
+
+ g_return_val_if_fail (!error || !*error, NULL);
+ g_return_val_if_fail (progname && progname[0] && !strchr (progname, '/'), NULL);
+ g_return_val_if_fail (file_test_flags || predicate, NULL);
+
+ /* Only consider @try_first if it is a valid, absolute path. This makes
+ * it simpler to pass in a path from configure checks. */
+ if ( try_first
+ && try_first[0] == '/'
+ && (file_test_flags == 0 || g_file_test (try_first, file_test_flags))
+ && (!predicate || predicate (try_first, user_data)))
+ return g_intern_string (try_first);
+
+ if (!paths || !*paths)
+ goto NOT_FOUND;
+
+ tmp = g_string_sized_new (50);
+ for (; *paths; paths++) {
+ if (!*paths)
+ continue;
+ g_string_append (tmp, *paths);
+ if (tmp->str[tmp->len - 1] != '/')
+ g_string_append_c (tmp, '/');
+ g_string_append (tmp, progname);
+ if ( (file_test_flags == 0 || g_file_test (tmp->str, file_test_flags))
+ && (!predicate || predicate (tmp->str, user_data))) {
+ ret = g_intern_string (tmp->str);
+ g_string_free (tmp, TRUE);
+ return ret;
+ }
+ g_string_set_size (tmp, 0);
+ }
+ g_string_free (tmp, TRUE);
+
+NOT_FOUND:
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("Could not find \"%s\" binary"), progname);
+ return NULL;
+}
+
+/**********************************************************************************************/
+
+/* Band, channel/frequency stuff for wireless */
+struct cf_pair {
+ guint32 chan;
+ guint32 freq;
+};
+
+static struct cf_pair a_table[] = {
+ /* A band */
+ { 7, 5035 },
+ { 8, 5040 },
+ { 9, 5045 },
+ { 11, 5055 },
+ { 12, 5060 },
+ { 16, 5080 },
+ { 34, 5170 },
+ { 36, 5180 },
+ { 38, 5190 },
+ { 40, 5200 },
+ { 42, 5210 },
+ { 44, 5220 },
+ { 46, 5230 },
+ { 48, 5240 },
+ { 50, 5250 },
+ { 52, 5260 },
+ { 56, 5280 },
+ { 58, 5290 },
+ { 60, 5300 },
+ { 64, 5320 },
+ { 100, 5500 },
+ { 104, 5520 },
+ { 108, 5540 },
+ { 112, 5560 },
+ { 116, 5580 },
+ { 120, 5600 },
+ { 124, 5620 },
+ { 128, 5640 },
+ { 132, 5660 },
+ { 136, 5680 },
+ { 140, 5700 },
+ { 149, 5745 },
+ { 152, 5760 },
+ { 153, 5765 },
+ { 157, 5785 },
+ { 160, 5800 },
+ { 161, 5805 },
+ { 165, 5825 },
+ { 183, 4915 },
+ { 184, 4920 },
+ { 185, 4925 },
+ { 187, 4935 },
+ { 188, 4945 },
+ { 192, 4960 },
+ { 196, 4980 },
+ { 0, -1 }
+};
+
+static struct cf_pair bg_table[] = {
+ /* B/G band */
+ { 1, 2412 },
+ { 2, 2417 },
+ { 3, 2422 },
+ { 4, 2427 },
+ { 5, 2432 },
+ { 6, 2437 },
+ { 7, 2442 },
+ { 8, 2447 },
+ { 9, 2452 },
+ { 10, 2457 },
+ { 11, 2462 },
+ { 12, 2467 },
+ { 13, 2472 },
+ { 14, 2484 },
+ { 0, -1 }
+};
+
+/**
+ * nm_utils_wifi_freq_to_channel:
+ * @freq: frequency
+ *
+ * Utility function to translate a Wi-Fi frequency to its corresponding channel.
+ *
+ * Returns: the channel represented by the frequency or 0
+ **/
+guint32
+nm_utils_wifi_freq_to_channel (guint32 freq)
+{
+ int i = 0;
+
+ if (freq > 4900) {
+ while (a_table[i].chan && (a_table[i].freq != freq))
+ i++;
+ return a_table[i].chan;
+ } else {
+ while (bg_table[i].chan && (bg_table[i].freq != freq))
+ i++;
+ return bg_table[i].chan;
+ }
+
+ return 0;
+}
+
+/**
+ * nm_utils_wifi_channel_to_freq:
+ * @channel: channel
+ * @band: frequency band for wireless ("a" or "bg")
+ *
+ * Utility function to translate a Wi-Fi channel to its corresponding frequency.
+ *
+ * Returns: the frequency represented by the channel of the band,
+ * or -1 when the freq is invalid, or 0 when the band
+ * is invalid
+ **/
+guint32
+nm_utils_wifi_channel_to_freq (guint32 channel, const char *band)
+{
+ int i = 0;
+
+ if (!strcmp (band, "a")) {
+ while (a_table[i].chan && (a_table[i].chan != channel))
+ i++;
+ return a_table[i].freq;
+ } else if (!strcmp (band, "bg")) {
+ while (bg_table[i].chan && (bg_table[i].chan != channel))
+ i++;
+ return bg_table[i].freq;
+ }
+
+ return 0;
+}
+
+/**
+ * nm_utils_wifi_find_next_channel:
+ * @channel: current channel
+ * @direction: whether going downward (0 or less) or upward (1 or more)
+ * @band: frequency band for wireless ("a" or "bg")
+ *
+ * Utility function to find out next/previous Wi-Fi channel for a channel.
+ *
+ * Returns: the next channel in the specified direction or 0
+ **/
+guint32
+nm_utils_wifi_find_next_channel (guint32 channel, int direction, char *band)
+{
+ size_t a_size = sizeof (a_table) / sizeof (struct cf_pair);
+ size_t bg_size = sizeof (bg_table) / sizeof (struct cf_pair);
+ struct cf_pair *pair = NULL;
+
+ if (!strcmp (band, "a")) {
+ if (channel < a_table[0].chan)
+ return a_table[0].chan;
+ if (channel > a_table[a_size - 2].chan)
+ return a_table[a_size - 2].chan;
+ pair = &a_table[0];
+ } else if (!strcmp (band, "bg")) {
+ if (channel < bg_table[0].chan)
+ return bg_table[0].chan;
+ if (channel > bg_table[bg_size - 2].chan)
+ return bg_table[bg_size - 2].chan;
+ pair = &bg_table[0];
+ } else {
+ g_assert_not_reached ();
+ return 0;
+ }
+
+ while (pair->chan) {
+ if (channel == pair->chan)
+ return channel;
+ if ((channel < (pair+1)->chan) && (channel > pair->chan)) {
+ if (direction > 0)
+ return (pair+1)->chan;
+ else
+ return pair->chan;
+ }
+ pair++;
+ }
+ return 0;
+}
+
+/**
+ * nm_utils_wifi_is_channel_valid:
+ * @channel: channel
+ * @band: frequency band for wireless ("a" or "bg")
+ *
+ * Utility function to verify Wi-Fi channel validity.
+ *
+ * Returns: %TRUE or %FALSE
+ **/
+gboolean
+nm_utils_wifi_is_channel_valid (guint32 channel, const char *band)
+{
+ struct cf_pair *table = NULL;
+ int i = 0;
+
+ if (!strcmp (band, "a"))
+ table = a_table;
+ else if (!strcmp (band, "bg"))
+ table = bg_table;
+ else
+ return FALSE;
+
+ while (table[i].chan && (table[i].chan != channel))
+ i++;
+
+ if (table[i].chan != 0)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+/**
+ * nm_utils_wifi_strength_bars:
+ * @strength: the access point strength, from 0 to 100
+ *
+ * Converts @strength into a 4-character-wide graphical representation of
+ * strength suitable for printing to stdout. If the current locale and terminal
+ * support it, this will use unicode graphics characters to represent
+ * "bars". Otherwise it will use 0 to 4 asterisks.
+ *
+ * Returns: the graphical representation of the access point strength
+ */
+const char *
+nm_utils_wifi_strength_bars (guint8 strength)
+{
+ static const char *strength_full, *strength_high, *strength_med, *strength_low, *strength_none;
+
+ if (G_UNLIKELY (strength_full == NULL)) {
+ gboolean can_show_graphics = TRUE;
+ char *locale_str;
+
+ if (!g_get_charset (NULL)) {
+ /* Non-UTF-8 locale */
+ locale_str = g_locale_from_utf8 ("\342\226\202\342\226\204\342\226\206\342\226\210", -1, NULL, NULL, NULL);
+ if (locale_str)
+ g_free (locale_str);
+ else
+ can_show_graphics = FALSE;
+ }
+
+ /* The linux console font doesn't have these characters */
+ if (g_strcmp0 (g_getenv ("TERM"), "linux") == 0)
+ can_show_graphics = FALSE;
+
+ if (can_show_graphics) {
+ strength_full = /* ▂▄▆█ */ "\342\226\202\342\226\204\342\226\206\342\226\210";
+ strength_high = /* â–‚â–„â–†_ */ "\342\226\202\342\226\204\342\226\206_";
+ strength_med = /* â–‚â–„__ */ "\342\226\202\342\226\204__";
+ strength_low = /* â–‚___ */ "\342\226\202___";
+ strength_none = /* ____ */ "____";
+ } else {
+ strength_full = "****";
+ strength_high = "*** ";
+ strength_med = "** ";
+ strength_low = "* ";
+ strength_none = " ";
+ }
+ }
+
+ if (strength > 80)
+ return strength_full;
+ else if (strength > 55)
+ return strength_high;
+ else if (strength > 30)
+ return strength_med;
+ else if (strength > 5)
+ return strength_low;
+ else
+ return strength_none;
+}
+
+/**
+ * nm_utils_hwaddr_len:
+ * @type: the type of address; either <literal>ARPHRD_ETHER</literal> or
+ * <literal>ARPHRD_INFINIBAND</literal>
+ *
+ * Returns the length in octets of a hardware address of type @type.
+ *
+ * It is an error to call this function with any value other than
+ * <literal>ARPHRD_ETHER</literal> or <literal>ARPHRD_INFINIBAND</literal>.
+ *
+ * Return value: the length.
+ */
+gsize
+nm_utils_hwaddr_len (int type)
+{
+ g_return_val_if_fail (type == ARPHRD_ETHER || type == ARPHRD_INFINIBAND, 0);
+
+ if (type == ARPHRD_ETHER)
+ return ETH_ALEN;
+ else if (type == ARPHRD_INFINIBAND)
+ return INFINIBAND_ALEN;
+
+ g_assert_not_reached ();
+}
+
+#define HEXVAL(c) ((c) <= '9' ? (c) - '0' : ((c) & 0x4F) - 'A' + 10)
+
+/**
+ * nm_utils_hwaddr_atoba:
+ * @asc: the ASCII representation of a hardware address
+ * @length: the expected length in bytes of the result
+ *
+ * Parses @asc and converts it to binary form in a #GByteArray. See
+ * nm_utils_hwaddr_aton() if you don't want a #GByteArray.
+ *
+ * Return value: (transfer full): a new #GByteArray, or %NULL if @asc couldn't
+ * be parsed
+ */
+GByteArray *
+nm_utils_hwaddr_atoba (const char *asc, gsize length)
+{
+ GByteArray *ba;
+
+ g_return_val_if_fail (asc != NULL, NULL);
+ g_return_val_if_fail (length > 0 && length <= NM_UTILS_HWADDR_LEN_MAX, NULL);
+
+ ba = g_byte_array_sized_new (length);
+ g_byte_array_set_size (ba, length);
+ if (!nm_utils_hwaddr_aton (asc, ba->data, length)) {
+ g_byte_array_unref (ba);
+ return NULL;
+ }
+
+ return ba;
+}
+
+/**
+ * nm_utils_hwaddr_aton:
+ * @asc: the ASCII representation of a hardware address
+ * @buffer: buffer to store the result into
+ * @length: the expected length in bytes of the result and
+ * the size of the buffer in bytes.
+ *
+ * Parses @asc and converts it to binary form in @buffer.
+ * Bytes in @asc can be sepatared by colons (:), or hyphens (-), but not mixed.
+ *
+ * Return value: @buffer, or %NULL if @asc couldn't be parsed
+ * or would be shorter or longer than @length.
+ */
+guint8 *
+nm_utils_hwaddr_aton (const char *asc, gpointer buffer, gsize length)
+{
+ const char *in = asc;
+ guint8 *out = (guint8 *)buffer;
+ char delimiter = '\0';
+
+ g_return_val_if_fail (asc != NULL, NULL);
+ g_return_val_if_fail (buffer != NULL, NULL);
+ g_return_val_if_fail (length > 0 && length <= NM_UTILS_HWADDR_LEN_MAX, NULL);
+
+ while (length && *in) {
+ guint8 d1 = in[0], d2 = in[1];
+
+ if (!g_ascii_isxdigit (d1))
+ return NULL;
+
+ /* If there's no leading zero (ie "aa:b:cc") then fake it */
+ if (d2 && g_ascii_isxdigit (d2)) {
+ *out++ = (HEXVAL (d1) << 4) + HEXVAL (d2);
+ in += 2;
+ } else {
+ /* Fake leading zero */
+ *out++ = (HEXVAL ('0') << 4) + HEXVAL (d1);
+ in += 1;
+ }
+
+ length--;
+ if (*in) {
+ if (delimiter == '\0') {
+ if (*in == ':' || *in == '-')
+ delimiter = *in;
+ else
+ return NULL;
+ } else {
+ if (*in != delimiter)
+ return NULL;
+ }
+ in++;
+ }
+ }
+
+ if (length == 0 && !*in)
+ return buffer;
+ else
+ return NULL;
+}
+
+/**
+ * nm_utils_hwaddr_ntoa:
+ * @addr: (type guint8) (array length=length): a binary hardware address
+ * @length: the length of @addr
+ *
+ * Converts @addr to textual form.
+ *
+ * Return value: (transfer full): the textual form of @addr
+ */
+char *
+nm_utils_hwaddr_ntoa (gconstpointer addr, gsize length)
+{
+ const guint8 *in = addr;
+ char *out, *result;
+ const char *LOOKUP = "0123456789ABCDEF";
+
+ g_return_val_if_fail (addr != NULL, g_strdup (""));
+ g_return_val_if_fail (length > 0 && length <= NM_UTILS_HWADDR_LEN_MAX, g_strdup (""));
+
+ result = out = g_malloc (length * 3);
+ while (length--) {
+ guint8 v = *in++;
+
+ *out++ = LOOKUP[v >> 4];
+ *out++ = LOOKUP[v & 0x0F];
+ if (length)
+ *out++ = ':';
+ }
+
+ *out = 0;
+ return result;
+}
+
+static int
+hwaddr_binary_len (const char *asc)
+{
+ int octets = 1;
+
+ if (!*asc)
+ return 0;
+
+ for (; *asc; asc++) {
+ if (*asc == ':' || *asc == '-')
+ octets++;
+ }
+ return octets;
+}
+
+/**
+ * nm_utils_hwaddr_valid:
+ * @asc: the ASCII representation of a hardware address
+ * @length: the length of address that @asc is expected to convert to
+ * (or -1 to accept any length up to %NM_UTILS_HWADDR_LEN_MAX)
+ *
+ * Parses @asc to see if it is a valid hardware address of the given
+ * length.
+ *
+ * Return value: %TRUE if @asc appears to be a valid hardware address
+ * of the indicated length, %FALSE if not.
+ */
+gboolean
+nm_utils_hwaddr_valid (const char *asc, gssize length)
+{
+ guint8 buf[NM_UTILS_HWADDR_LEN_MAX];
+
+ g_return_val_if_fail (asc != NULL, FALSE);
+ g_return_val_if_fail (length == -1 || (length > 0 && length <= NM_UTILS_HWADDR_LEN_MAX), FALSE);
+
+ if (length == -1) {
+ length = hwaddr_binary_len (asc);
+ if (length == 0 || length > NM_UTILS_HWADDR_LEN_MAX)
+ return FALSE;
+ }
+
+ return nm_utils_hwaddr_aton (asc, buf, length) != NULL;
+}
+
+/**
+ * nm_utils_hwaddr_canonical:
+ * @asc: the ASCII representation of a hardware address
+ * @length: the length of address that @asc is expected to convert to
+ * (or -1 to accept any length up to %NM_UTILS_HWADDR_LEN_MAX)
+ *
+ * Parses @asc to see if it is a valid hardware address of the given
+ * length, and if so, returns it in canonical form (uppercase, with
+ * leading 0s as needed, and with colons rather than hyphens).
+ *
+ * Return value: (transfer full): the canonicalized address if @asc appears to
+ * be a valid hardware address of the indicated length, %NULL if not.
+ */
+char *
+nm_utils_hwaddr_canonical (const char *asc, gssize length)
+{
+ guint8 buf[NM_UTILS_HWADDR_LEN_MAX];
+
+ g_return_val_if_fail (asc != NULL, NULL);
+ g_return_val_if_fail (length == -1 || (length > 0 && length <= NM_UTILS_HWADDR_LEN_MAX), NULL);
+
+ if (length == -1) {
+ length = hwaddr_binary_len (asc);
+ if (length == 0 || length > NM_UTILS_HWADDR_LEN_MAX)
+ return NULL;
+ }
+
+ if (nm_utils_hwaddr_aton (asc, buf, length) == NULL)
+ return NULL;
+
+ return g_strdup (nm_utils_hwaddr_ntoa (buf, length));
+}
+
+/* This is used to possibly canonicalize values passed to MAC address property
+ * setters. Unlike nm_utils_hwaddr_canonical(), it accepts %NULL, and if you
+ * pass it an invalid MAC address, it just returns that string rather than
+ * returning %NULL (so that we can return a proper error from verify() later).
+ */
+char *
+_nm_utils_hwaddr_canonical_or_invalid (const char *mac, gssize length)
+{
+ char *canonical;
+
+ if (!mac)
+ return NULL;
+
+ canonical = nm_utils_hwaddr_canonical (mac, length);
+ if (canonical)
+ return canonical;
+ else
+ return g_strdup (mac);
+}
+
+/**
+ * nm_utils_hwaddr_matches:
+ * @hwaddr1: pointer to a binary or ASCII hardware address, or %NULL
+ * @hwaddr1_len: size of @hwaddr1, or -1 if @hwaddr1 is ASCII
+ * @hwaddr2: pointer to a binary or ASCII hardware address, or %NULL
+ * @hwaddr2_len: size of @hwaddr2, or -1 if @hwaddr2 is ASCII
+ *
+ * Generalized hardware address comparison function. Tests if @hwaddr1 and
+ * @hwaddr2 "equal" (or more precisely, "equivalent"), with several advantages
+ * over a simple memcmp():
+ *
+ * 1. If @hwaddr1_len or @hwaddr2_len is -1, then the corresponding address is
+ * assumed to be ASCII rather than binary, and will be converted to binary
+ * before being compared.
+ *
+ * 2. If @hwaddr1 or @hwaddr2 is %NULL, it is treated instead as though it was
+ * a zero-filled buffer @hwaddr1_len or @hwaddr2_len bytes long.
+ *
+ * 3. If @hwaddr1 and @hwaddr2 are InfiniBand hardware addresses (that is, if
+ * they are <literal>INFINIBAND_ALEN</literal> bytes long in binary form)
+ * then only the last 8 bytes are compared, since those are the only bytes
+ * that actually identify the hardware. (The other 12 bytes will change
+ * depending on the configuration of the InfiniBand fabric that the device
+ * is connected to.)
+ *
+ * If a passed-in ASCII hardware address cannot be parsed, or would parse to an
+ * address larger than %NM_UTILS_HWADDR_LEN_MAX, then it will silently fail to
+ * match. (This means that externally-provided address strings do not need to be
+ * sanity-checked before comparing them against known good addresses; they are
+ * guaranteed to not match if they are invalid.)
+ *
+ * Return value: %TRUE if @hwaddr1 and @hwaddr2 are equivalent, %FALSE if they are
+ * different (or either of them is invalid).
+ */
+gboolean
+nm_utils_hwaddr_matches (gconstpointer hwaddr1,
+ gssize hwaddr1_len,
+ gconstpointer hwaddr2,
+ gssize hwaddr2_len)
+{
+ guint8 buf1[NM_UTILS_HWADDR_LEN_MAX], buf2[NM_UTILS_HWADDR_LEN_MAX];
+
+ if (hwaddr1_len == -1) {
+ g_return_val_if_fail (hwaddr1 != NULL, FALSE);
+
+ hwaddr1_len = hwaddr_binary_len (hwaddr1);
+ if (hwaddr1_len == 0 || hwaddr1_len > NM_UTILS_HWADDR_LEN_MAX)
+ return FALSE;
+ if (!nm_utils_hwaddr_aton (hwaddr1, buf1, hwaddr1_len))
+ return FALSE;
+
+ hwaddr1 = buf1;
+ } else {
+ g_return_val_if_fail (hwaddr1_len > 0 && hwaddr1_len <= NM_UTILS_HWADDR_LEN_MAX, FALSE);
+
+ if (!hwaddr1) {
+ memset (buf1, 0, hwaddr1_len);
+ hwaddr1 = buf1;
+ }
+ }
+
+ if (hwaddr2_len == -1) {
+ g_return_val_if_fail (hwaddr2 != NULL, FALSE);
+
+ if (!nm_utils_hwaddr_aton (hwaddr2, buf2, hwaddr1_len))
+ return FALSE;
+
+ hwaddr2 = buf2;
+ hwaddr2_len = hwaddr1_len;
+ } else {
+ g_return_val_if_fail (hwaddr2_len > 0 && hwaddr2_len <= NM_UTILS_HWADDR_LEN_MAX, FALSE);
+
+ if (!hwaddr2) {
+ memset (buf2, 0, hwaddr2_len);
+ hwaddr2 = buf2;
+ }
+ }
+
+ if (hwaddr1_len != hwaddr2_len)
+ return FALSE;
+
+ if (hwaddr1_len == INFINIBAND_ALEN) {
+ hwaddr1 = (guint8 *)hwaddr1 + INFINIBAND_ALEN - 8;
+ hwaddr2 = (guint8 *)hwaddr2 + INFINIBAND_ALEN - 8;
+ hwaddr1_len = hwaddr2_len = 8;
+ }
+
+ return !memcmp (hwaddr1, hwaddr2, hwaddr1_len);
+}
+
+GVariant *
+_nm_utils_hwaddr_to_dbus (const GValue *prop_value)
+{
+ const char *str = g_value_get_string (prop_value);
+ guint8 buf[NM_UTILS_HWADDR_LEN_MAX];
+ int len;
+
+ if (str) {
+ len = hwaddr_binary_len (str);
+ g_return_val_if_fail (len > 0 && len <= NM_UTILS_HWADDR_LEN_MAX, NULL);
+ if (!nm_utils_hwaddr_aton (str, buf, len))
+ len = 0;
+ } else
+ len = 0;
+
+ return g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, buf, len, 1);
+}
+
+void
+_nm_utils_hwaddr_from_dbus (GVariant *dbus_value,
+ GValue *prop_value)
+{
+ gsize length = 0;
+ const guint8 *array = g_variant_get_fixed_array (dbus_value, &length, 1);
+ char *str;
+
+ str = length ? nm_utils_hwaddr_ntoa (array, length) : NULL;
+ g_value_take_string (prop_value, str);
+}
+
+/**
+ * nm_utils_bin2hexstr:
+ * @src: (type guint8) (array length=len): an array of bytes
+ * @len: the length of the @src array
+ * @final_len: an index where to cut off the returned string, or -1
+ *
+ * Converts the byte array @src into a hexadecimal string. If @final_len is
+ * greater than -1, the returned string is terminated at that index
+ * (returned_string[final_len] == '\0'),
+ *
+ * Return value: (transfer full): the textual form of @bytes
+ */
+/*
+ * Code originally by Alex Larsson <alexl@redhat.com> and
+ * copyright Red Hat, Inc. under terms of the LGPL.
+ */
+char *
+nm_utils_bin2hexstr (gconstpointer src, gsize len, int final_len)
+{
+ static char hex_digits[] = "0123456789abcdef";
+ const guint8 *bytes = src;
+ char *result;
+ int i;
+ gsize buflen = (len * 2) + 1;
+
+ g_return_val_if_fail (bytes != NULL, NULL);
+ g_return_val_if_fail (len > 0, NULL);
+ g_return_val_if_fail (len < 4096, NULL); /* Arbitrary limit */
+ if (final_len > -1)
+ g_return_val_if_fail (final_len < buflen, NULL);
+
+ result = g_malloc0 (buflen);
+ for (i = 0; i < len; i++) {
+ result[2*i] = hex_digits[(bytes[i] >> 4) & 0xf];
+ result[2*i+1] = hex_digits[bytes[i] & 0xf];
+ }
+ /* Cut converted key off at the correct length for this cipher type */
+ if (final_len > -1)
+ result[final_len] = '\0';
+ else
+ result[buflen - 1] = '\0';
+
+ return result;
+}
+
+/**
+ * nm_utils_hexstr2bin:
+ * @hex: a string of hexadecimal characters with optional ':' separators
+ *
+ * Converts a hexadecimal string @hex into an array of bytes. The optional
+ * separator ':' may be used between single or pairs of hexadecimal characters,
+ * eg "00:11" or "0:1". Any "0x" at the beginning of @hex is ignored. @hex
+ * may not start or end with ':'.
+ *
+ * Return value: (transfer full): the converted bytes, or %NULL on error
+ */
+GBytes *
+nm_utils_hexstr2bin (const char *hex)
+{
+ guint i = 0, x = 0;
+ gs_free guint8 *c = NULL;
+ int a, b;
+ gboolean found_colon = FALSE;
+
+ g_return_val_if_fail (hex != NULL, NULL);
+
+ if (strncasecmp (hex, "0x", 2) == 0)
+ hex += 2;
+ found_colon = !!strchr (hex, ':');
+
+ c = g_malloc (strlen (hex) / 2 + 1);
+ for (;;) {
+ a = g_ascii_xdigit_value (hex[i++]);
+ if (a < 0)
+ return NULL;
+
+ if (hex[i] && hex[i] != ':') {
+ b = g_ascii_xdigit_value (hex[i++]);
+ if (b < 0)
+ return NULL;
+ c[x++] = ((guint) a << 4) | ((guint) b);
+ } else
+ c[x++] = (guint) a;
+
+ if (!hex[i])
+ break;
+ if (hex[i] == ':') {
+ if (!hex[i + 1]) {
+ /* trailing ':' is invalid */
+ return NULL;
+ }
+ i++;
+ } else if (found_colon) {
+ /* If colons exist, they must delimit 1 or 2 hex chars */
+ return NULL;
+ }
+ }
+
+ return g_bytes_new (c, x);
+}
+
+/**
+ * nm_utils_iface_valid_name:
+ * @name: Name of interface
+ *
+ * This function is a 1:1 copy of the kernel's interface validation
+ * function in net/core/dev.c.
+ *
+ * Returns: %TRUE if interface name is valid, otherwise %FALSE is returned.
+ */
+gboolean
+nm_utils_iface_valid_name (const char *name)
+{
+ g_return_val_if_fail (name != NULL, FALSE);
+
+ if (*name == '\0')
+ return FALSE;
+
+ if (strlen (name) >= 16)
+ return FALSE;
+
+ if (!strcmp (name, ".") || !strcmp (name, ".."))
+ return FALSE;
+
+ while (*name) {
+ if (*name == '/' || g_ascii_isspace (*name))
+ return FALSE;
+ name++;
+ }
+
+ return TRUE;
+}
+
+/**
+ * nm_utils_is_uuid:
+ * @str: a string that might be a UUID
+ *
+ * Checks if @str is a UUID
+ *
+ * Returns: %TRUE if @str is a UUID, %FALSE if not
+ */
+gboolean
+nm_utils_is_uuid (const char *str)
+{
+ const char *p = str;
+ int num_dashes = 0;
+
+ while (*p) {
+ if (*p == '-')
+ num_dashes++;
+ else if (!g_ascii_isxdigit (*p))
+ return FALSE;
+ p++;
+ }
+
+ if ((num_dashes == 4) && (p - str == 36))
+ return TRUE;
+
+ /* Backwards compat for older configurations */
+ if ((num_dashes == 0) && (p - str == 40))
+ return TRUE;
+
+ return FALSE;
+}
+
+static char _nm_utils_inet_ntop_buffer[NM_UTILS_INET_ADDRSTRLEN];
+
+/**
+ * nm_utils_inet4_ntop: (skip)
+ * @inaddr: the address that should be converted to string.
+ * @dst: the destination buffer, it must contain at least
+ * <literal>INET_ADDRSTRLEN</literal> or %NM_UTILS_INET_ADDRSTRLEN
+ * characters. If set to %NULL, it will return a pointer to an internal, static
+ * buffer (shared with nm_utils_inet6_ntop()). Beware, that the internal
+ * buffer will be overwritten with ever new call of nm_utils_inet4_ntop() or
+ * nm_utils_inet6_ntop() that does not provied it's own @dst buffer. Also,
+ * using the internal buffer is not thread safe. When in doubt, pass your own
+ * @dst buffer to avoid these issues.
+ *
+ * Wrapper for inet_ntop.
+ *
+ * Returns: the input buffer @dst, or a pointer to an
+ * internal, static buffer. This function cannot fail.
+ **/
+const char *
+nm_utils_inet4_ntop (in_addr_t inaddr, char *dst)
+{
+ return inet_ntop (AF_INET, &inaddr, dst ? dst : _nm_utils_inet_ntop_buffer,
+ INET_ADDRSTRLEN);
+}
+
+/**
+ * nm_utils_inet6_ntop: (skip)
+ * @in6addr: the address that should be converted to string.
+ * @dst: the destination buffer, it must contain at least
+ * <literal>INET6_ADDRSTRLEN</literal> or %NM_UTILS_INET_ADDRSTRLEN
+ * characters. If set to %NULL, it will return a pointer to an internal, static
+ * buffer (shared with nm_utils_inet4_ntop()). Beware, that the internal
+ * buffer will be overwritten with ever new call of nm_utils_inet4_ntop() or
+ * nm_utils_inet6_ntop() that does not provied it's own @dst buffer. Also,
+ * using the internal buffer is not thread safe. When in doubt, pass your own
+ * @dst buffer to avoid these issues.
+ *
+ * Wrapper for inet_ntop.
+ *
+ * Returns: the input buffer @dst, or a pointer to an
+ * internal, static buffer. %NULL is not allowed as @in6addr,
+ * otherwise, this function cannot fail.
+ **/
+const char *
+nm_utils_inet6_ntop (const struct in6_addr *in6addr, char *dst)
+{
+ g_return_val_if_fail (in6addr, NULL);
+ return inet_ntop (AF_INET6, in6addr, dst ? dst : _nm_utils_inet_ntop_buffer,
+ INET6_ADDRSTRLEN);
+}
+
+/**
+ * nm_utils_ipaddr_valid:
+ * @family: <literal>AF_INET</literal> or <literal>AF_INET6</literal>, or
+ * <literal>AF_UNSPEC</literal> to accept either
+ * @ip: an IP address
+ *
+ * Checks if @ip contains a valid IP address of the given family.
+ *
+ * Return value: %TRUE or %FALSE
+ */
+gboolean
+nm_utils_ipaddr_valid (int family, const char *ip)
+{
+ guint8 buf[sizeof (struct in6_addr)];
+
+ g_return_val_if_fail (family == AF_INET || family == AF_INET6 || family == AF_UNSPEC, FALSE);
+
+ if (family == AF_UNSPEC)
+ family = strchr (ip, ':') ? AF_INET6 : AF_INET;
+
+ return inet_pton (family, ip, buf) == 1;
+}
+
+/**
+ * nm_utils_check_virtual_device_compatibility:
+ * @virtual_type: a virtual connection type
+ * @other_type: a connection type to test against @virtual_type
+ *
+ * Determines if a connection of type @virtual_type can (in the
+ * general case) work with connections of type @other_type.
+ *
+ * If @virtual_type is %NM_TYPE_SETTING_VLAN, then this checks if
+ * @other_type is a valid type for the parent of a VLAN.
+ *
+ * If @virtual_type is a "master" type (eg, %NM_TYPE_SETTING_BRIDGE),
+ * then this checks if @other_type is a valid type for a slave of that
+ * master.
+ *
+ * Note that even if this returns %TRUE it is not guaranteed that
+ * <emphasis>every</emphasis> connection of type @other_type is
+ * compatible with @virtual_type; it may depend on the exact
+ * configuration of the two connections, or on the capabilities of an
+ * underlying device driver.
+ *
+ * Returns: %TRUE or %FALSE
+ */
+gboolean
+nm_utils_check_virtual_device_compatibility (GType virtual_type, GType other_type)
+{
+ g_return_val_if_fail (_nm_setting_type_is_base_type (virtual_type), FALSE);
+ g_return_val_if_fail (_nm_setting_type_is_base_type (other_type), FALSE);
+
+ if (virtual_type == NM_TYPE_SETTING_BOND) {
+ return ( other_type == NM_TYPE_SETTING_INFINIBAND
+ || other_type == NM_TYPE_SETTING_WIRED
+ || other_type == NM_TYPE_SETTING_BRIDGE
+ || other_type == NM_TYPE_SETTING_BOND
+ || other_type == NM_TYPE_SETTING_TEAM
+ || other_type == NM_TYPE_SETTING_VLAN);
+ } else if (virtual_type == NM_TYPE_SETTING_BRIDGE) {
+ return ( other_type == NM_TYPE_SETTING_WIRED
+ || other_type == NM_TYPE_SETTING_BOND
+ || other_type == NM_TYPE_SETTING_TEAM
+ || other_type == NM_TYPE_SETTING_VLAN);
+ } else if (virtual_type == NM_TYPE_SETTING_TEAM) {
+ return ( other_type == NM_TYPE_SETTING_WIRED
+ || other_type == NM_TYPE_SETTING_BRIDGE
+ || other_type == NM_TYPE_SETTING_BOND
+ || other_type == NM_TYPE_SETTING_TEAM
+ || other_type == NM_TYPE_SETTING_VLAN);
+ } else if (virtual_type == NM_TYPE_SETTING_VLAN) {
+ return ( other_type == NM_TYPE_SETTING_WIRED
+ || other_type == NM_TYPE_SETTING_WIRELESS
+ || other_type == NM_TYPE_SETTING_BRIDGE
+ || other_type == NM_TYPE_SETTING_BOND
+ || other_type == NM_TYPE_SETTING_TEAM
+ || other_type == NM_TYPE_SETTING_VLAN);
+ } else {
+ g_warn_if_reached ();
+ return FALSE;
+ }
+}
diff --git a/libnm-core/nm-utils.h b/libnm-core/nm-utils.h
new file mode 100644
index 000000000..8c22cfd16
--- /dev/null
+++ b/libnm-core/nm-utils.h
@@ -0,0 +1,190 @@
+/* -*- 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 2005 - 2013 Red Hat, Inc.
+ */
+
+#ifndef __NM_UTILS_H__
+#define __NM_UTILS_H__
+
+#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
+#error "Only <NetworkManager.h> can be included directly."
+#endif
+
+#include <glib.h>
+
+#include <netinet/in.h>
+
+/* For ETH_ALEN and INFINIBAND_ALEN */
+#include <linux/if_ether.h>
+#include <linux/if_infiniband.h>
+
+#include "nm-dbus-interface.h"
+#include "nm-core-enum-types.h"
+#include "nm-setting-wireless-security.h"
+
+G_BEGIN_DECLS
+
+/* SSID helpers */
+gboolean nm_utils_is_empty_ssid (const guint8 *ssid, gsize len);
+const char *nm_utils_escape_ssid (const guint8 *ssid, gsize len);
+gboolean nm_utils_same_ssid (const guint8 *ssid1, gsize len1,
+ const guint8 *ssid2, gsize len2,
+ gboolean ignore_trailing_null);
+char * nm_utils_ssid_to_utf8 (const guint8 *ssid, gsize len);
+
+/**
+ * NMUtilsSecurityType:
+ * @NMU_SEC_INVALID: unknown or invalid security, placeholder and not used
+ * @NMU_SEC_NONE: unencrypted and open
+ * @NMU_SEC_STATIC_WEP: static WEP keys are used for encryption
+ * @NMU_SEC_LEAP: Cisco LEAP is used for authentication and for generating the
+ * dynamic WEP keys automatically
+ * @NMU_SEC_DYNAMIC_WEP: standard 802.1x is used for authentication and
+ * generating the dynamic WEP keys automatically
+ * @NMU_SEC_WPA_PSK: WPA1 is used with Pre-Shared Keys (PSK)
+ * @NMU_SEC_WPA_ENTERPRISE: WPA1 is used with 802.1x authentication
+ * @NMU_SEC_WPA2_PSK: WPA2/RSN is used with Pre-Shared Keys (PSK)
+ * @NMU_SEC_WPA2_ENTERPRISE: WPA2 is used with 802.1x authentication
+ *
+ * Describes generic security mechanisms that 802.11 access points may offer.
+ * Used with nm_utils_security_valid() for checking whether a given access
+ * point is compatible with a network device.
+ **/
+typedef enum {
+ NMU_SEC_INVALID = 0,
+ NMU_SEC_NONE,
+ NMU_SEC_STATIC_WEP,
+ NMU_SEC_LEAP,
+ NMU_SEC_DYNAMIC_WEP,
+ NMU_SEC_WPA_PSK,
+ NMU_SEC_WPA_ENTERPRISE,
+ NMU_SEC_WPA2_PSK,
+ NMU_SEC_WPA2_ENTERPRISE
+} NMUtilsSecurityType;
+
+gboolean nm_utils_security_valid (NMUtilsSecurityType type,
+ NMDeviceWifiCapabilities wifi_caps,
+ gboolean have_ap,
+ gboolean adhoc,
+ NM80211ApFlags ap_flags,
+ NM80211ApSecurityFlags ap_wpa,
+ NM80211ApSecurityFlags ap_rsn);
+
+gboolean nm_utils_ap_mode_security_valid (NMUtilsSecurityType type,
+ NMDeviceWifiCapabilities wifi_caps);
+
+gboolean nm_utils_wep_key_valid (const char *key, NMWepKeyType wep_type);
+gboolean nm_utils_wpa_psk_valid (const char *psk);
+
+GVariant *nm_utils_ip4_dns_to_variant (char **dns);
+char **nm_utils_ip4_dns_from_variant (GVariant *value);
+GVariant *nm_utils_ip4_addresses_to_variant (GPtrArray *addresses,
+ const char *gateway);
+GPtrArray *nm_utils_ip4_addresses_from_variant (GVariant *value,
+ char **out_gateway);
+GVariant *nm_utils_ip4_routes_to_variant (GPtrArray *routes);
+GPtrArray *nm_utils_ip4_routes_from_variant (GVariant *value);
+
+guint32 nm_utils_ip4_netmask_to_prefix (guint32 netmask);
+guint32 nm_utils_ip4_prefix_to_netmask (guint32 prefix);
+guint32 nm_utils_ip4_get_default_prefix (guint32 ip);
+
+GVariant *nm_utils_ip6_dns_to_variant (char **dns);
+char **nm_utils_ip6_dns_from_variant (GVariant *value);
+GVariant *nm_utils_ip6_addresses_to_variant (GPtrArray *addresses,
+ const char *gateway);
+GPtrArray *nm_utils_ip6_addresses_from_variant (GVariant *value,
+ char **out_gateway);
+GVariant *nm_utils_ip6_routes_to_variant (GPtrArray *routes);
+GPtrArray *nm_utils_ip6_routes_from_variant (GVariant *value);
+
+GVariant *nm_utils_ip_addresses_to_variant (GPtrArray *addresses);
+GPtrArray *nm_utils_ip_addresses_from_variant (GVariant *value,
+ int family);
+GVariant *nm_utils_ip_routes_to_variant (GPtrArray *routes);
+GPtrArray *nm_utils_ip_routes_from_variant (GVariant *value,
+ int family);
+
+char *nm_utils_uuid_generate (void);
+
+gboolean nm_utils_file_is_certificate (const char *filename);
+gboolean nm_utils_file_is_private_key (const char *filename, gboolean *out_encrypted);
+gboolean nm_utils_file_is_pkcs12 (const char *filename);
+
+typedef gboolean (*NMUtilsFileSearchInPathsPredicate) (const char *filename, gpointer user_data);
+
+const char *nm_utils_file_search_in_paths (const char *progname,
+ const char *try_first,
+ const char *const *paths,
+ GFileTest file_test_flags,
+ NMUtilsFileSearchInPathsPredicate predicate,
+ gpointer user_data,
+ GError **error);
+
+guint32 nm_utils_wifi_freq_to_channel (guint32 freq);
+guint32 nm_utils_wifi_channel_to_freq (guint32 channel, const char *band);
+guint32 nm_utils_wifi_find_next_channel (guint32 channel, int direction, char *band);
+gboolean nm_utils_wifi_is_channel_valid (guint32 channel, const char *band);
+
+const char *nm_utils_wifi_strength_bars (guint8 strength);
+
+/**
+ * NM_UTILS_HWADDR_LEN_MAX:
+ *
+ * The maximum length of hardware addresses handled by NetworkManager itself,
+ * nm_utils_hwaddr_len(), and nm_utils_hwaddr_aton().
+ */
+#define NM_UTILS_HWADDR_LEN_MAX 20 /* INFINIBAND_ALEN */
+
+gsize nm_utils_hwaddr_len (int type) G_GNUC_PURE;
+
+char *nm_utils_hwaddr_ntoa (gconstpointer addr, gsize length);
+GByteArray *nm_utils_hwaddr_atoba (const char *asc, gsize length);
+guint8 *nm_utils_hwaddr_aton (const char *asc, gpointer buffer, gsize length);
+
+gboolean nm_utils_hwaddr_valid (const char *asc, gssize length);
+char *nm_utils_hwaddr_canonical (const char *asc, gssize length);
+gboolean nm_utils_hwaddr_matches (gconstpointer hwaddr1,
+ gssize hwaddr1_len,
+ gconstpointer hwaddr2,
+ gssize hwaddr2_len);
+
+char *nm_utils_bin2hexstr (gconstpointer src, gsize len, int final_len);
+GBytes *nm_utils_hexstr2bin (const char *hex);
+
+gboolean nm_utils_iface_valid_name(const char *name);
+
+gboolean nm_utils_is_uuid (const char *str);
+
+/**
+ * NM_UTILS_INET_ADDRSTRLEN:
+ *
+ * Defines the minimal length for a char buffer that is suitable as @dst argument
+ * for both nm_utils_inet4_ntop() and nm_utils_inet6_ntop().
+ **/
+#define NM_UTILS_INET_ADDRSTRLEN INET6_ADDRSTRLEN
+const char *nm_utils_inet4_ntop (in_addr_t inaddr, char *dst);
+const char *nm_utils_inet6_ntop (const struct in6_addr *in6addr, char *dst);
+
+gboolean nm_utils_ipaddr_valid (int family, const char *ip);
+
+gboolean nm_utils_check_virtual_device_compatibility (GType virtual_type, GType other_type);
+
+G_END_DECLS
+
+#endif /* __NM_UTILS_H__ */
diff --git a/libnm-core/nm-version.h b/libnm-core/nm-version.h
new file mode 100644
index 000000000..39cfd63f5
--- /dev/null
+++ b/libnm-core/nm-version.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.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2011 Red Hat, Inc.
+ */
+
+#ifndef NM_VERSION_H
+#define NM_VERSION_H
+
+/**
+ * NM_MAJOR_VERSION:
+ *
+ * Evaluates to the major version number of NetworkManager which this source
+ * is compiled against.
+ */
+#define NM_MAJOR_VERSION (1)
+
+/**
+ * NM_MINOR_VERSION:
+ *
+ * Evaluates to the minor version number of NetworkManager which this source
+ * is compiled against.
+ */
+#define NM_MINOR_VERSION (0)
+
+/**
+ * NM_MICRO_VERSION:
+ *
+ * Evaluates to the micro version number of NetworkManager which this source
+ * compiled against.
+ */
+#define NM_MICRO_VERSION (0)
+
+/**
+ * NM_CHECK_VERSION:
+ * @major: major version (e.g. 1 for version 1.2.5)
+ * @minor: minor version (e.g. 2 for version 1.2.5)
+ * @micro: micro version (e.g. 5 for version 1.2.5)
+ *
+ * Returns: %TRUE if the version of the NetworkManager header files
+ * is the same as or newer than the passed-in version.
+ */
+#define NM_CHECK_VERSION(major,minor,micro) \
+ (NM_MAJOR_VERSION > (major) || \
+ (NM_MAJOR_VERSION == (major) && NM_MINOR_VERSION > (minor)) || \
+ (NM_MAJOR_VERSION == (major) && NM_MINOR_VERSION == (minor) && NM_MICRO_VERSION >= (micro)))
+
+
+/* Deprecation / Availability macros */
+
+#define NM_ENCODE_VERSION(major,minor,micro) ((major) << 16 | (minor) << 8 | (micro))
+
+#define NM_VERSION_0_9_8 (NM_ENCODE_VERSION (0, 9, 8))
+#define NM_VERSION_0_9_10 (NM_ENCODE_VERSION (0, 9, 10))
+#define NM_VERSION_1_0 (NM_ENCODE_VERSION (1, 0, 0))
+
+#define NM_VERSION_CUR_STABLE NM_VERSION_0_9_10
+#define NM_VERSION_NEXT_STABLE NM_VERSION_1_0
+
+#if !defined (NM_VERSION_MIN_REQUIRED) || (NM_VERSION_MIN_REQUIRED == 0)
+# undef NM_VERSION_MIN_REQUIRED
+# define NM_VERSION_MIN_REQUIRED (NM_VERSION_CUR_STABLE)
+#endif
+
+#if !defined (NM_VERSION_MAX_ALLOWED) || (NM_VERSION_MAX_ALLOWED == 0)
+# undef NM_VERSION_MAX_ALLOWED
+# define NM_VERSION_MAX_ALLOWED (NM_VERSION_CUR_STABLE)
+#endif
+
+/* sanity checks */
+#if NM_VERSION_MIN_REQUIRED > NM_VERSION_NEXT_STABLE
+#error "NM_VERSION_MIN_REQUIRED must be <= NM_VERSION_NEXT_STABLE"
+#endif
+#if NM_VERSION_MAX_ALLOWED < NM_VERSION_MIN_REQUIRED
+#error "NM_VERSION_MAX_ALLOWED must be >= NM_VERSION_MIN_REQUIRED"
+#endif
+#if NM_VERSION_MIN_REQUIRED < NM_VERSION_0_9_8
+#error "NM_VERSION_MIN_REQUIRED must be >= NM_VERSION_0_9_8"
+#endif
+
+#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_0_9_10
+# define NM_DEPRECATED_IN_0_9_10 G_DEPRECATED
+# define NM_DEPRECATED_IN_0_9_10_FOR(f) G_DEPRECATED_FOR(f)
+#else
+# define NM_DEPRECATED_IN_0_9_10
+# define NM_DEPRECATED_IN_0_9_10_FOR(f)
+#endif
+
+#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_0
+# define NM_DEPRECATED_IN_1_0 G_DEPRECATED
+# define NM_DEPRECATED_IN_1_0_FOR(f) G_DEPRECATED_FOR(f)
+#else
+# define NM_DEPRECATED_IN_1_0
+# define NM_DEPRECATED_IN_1_0_FOR(f)
+#endif
+
+#if NM_VERSION_MAX_ALLOWED < NM_VERSION_0_9_10
+# define NM_AVAILABLE_IN_0_9_10 G_UNAVAILABLE(0.9,10)
+#else
+# define NM_AVAILABLE_IN_0_9_10
+#endif
+
+#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_0
+# define NM_AVAILABLE_IN_1_0 G_UNAVAILABLE(1,0)
+#else
+# define NM_AVAILABLE_IN_1_0
+#endif
+
+#endif /* NM_VERSION_H */
diff --git a/libnm-core/nm-version.h.in b/libnm-core/nm-version.h.in
new file mode 100644
index 000000000..0a33ac295
--- /dev/null
+++ b/libnm-core/nm-version.h.in
@@ -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.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2011 Red Hat, Inc.
+ */
+
+#ifndef NM_VERSION_H
+#define NM_VERSION_H
+
+/**
+ * NM_MAJOR_VERSION:
+ *
+ * Evaluates to the major version number of NetworkManager which this source
+ * is compiled against.
+ */
+#define NM_MAJOR_VERSION (@NM_MAJOR_VERSION@)
+
+/**
+ * NM_MINOR_VERSION:
+ *
+ * Evaluates to the minor version number of NetworkManager which this source
+ * is compiled against.
+ */
+#define NM_MINOR_VERSION (@NM_MINOR_VERSION@)
+
+/**
+ * NM_MICRO_VERSION:
+ *
+ * Evaluates to the micro version number of NetworkManager which this source
+ * compiled against.
+ */
+#define NM_MICRO_VERSION (@NM_MICRO_VERSION@)
+
+/**
+ * NM_CHECK_VERSION:
+ * @major: major version (e.g. 1 for version 1.2.5)
+ * @minor: minor version (e.g. 2 for version 1.2.5)
+ * @micro: micro version (e.g. 5 for version 1.2.5)
+ *
+ * Returns: %TRUE if the version of the NetworkManager header files
+ * is the same as or newer than the passed-in version.
+ */
+#define NM_CHECK_VERSION(major,minor,micro) \
+ (NM_MAJOR_VERSION > (major) || \
+ (NM_MAJOR_VERSION == (major) && NM_MINOR_VERSION > (minor)) || \
+ (NM_MAJOR_VERSION == (major) && NM_MINOR_VERSION == (minor) && NM_MICRO_VERSION >= (micro)))
+
+
+/* Deprecation / Availability macros */
+
+#define NM_ENCODE_VERSION(major,minor,micro) ((major) << 16 | (minor) << 8 | (micro))
+
+#define NM_VERSION_0_9_8 (NM_ENCODE_VERSION (0, 9, 8))
+#define NM_VERSION_0_9_10 (NM_ENCODE_VERSION (0, 9, 10))
+#define NM_VERSION_1_0 (NM_ENCODE_VERSION (1, 0, 0))
+
+#define NM_VERSION_CUR_STABLE NM_VERSION_0_9_10
+#define NM_VERSION_NEXT_STABLE NM_VERSION_1_0
+
+#if !defined (NM_VERSION_MIN_REQUIRED) || (NM_VERSION_MIN_REQUIRED == 0)
+# undef NM_VERSION_MIN_REQUIRED
+# define NM_VERSION_MIN_REQUIRED (NM_VERSION_CUR_STABLE)
+#endif
+
+#if !defined (NM_VERSION_MAX_ALLOWED) || (NM_VERSION_MAX_ALLOWED == 0)
+# undef NM_VERSION_MAX_ALLOWED
+# define NM_VERSION_MAX_ALLOWED (NM_VERSION_CUR_STABLE)
+#endif
+
+/* sanity checks */
+#if NM_VERSION_MIN_REQUIRED > NM_VERSION_NEXT_STABLE
+#error "NM_VERSION_MIN_REQUIRED must be <= NM_VERSION_NEXT_STABLE"
+#endif
+#if NM_VERSION_MAX_ALLOWED < NM_VERSION_MIN_REQUIRED
+#error "NM_VERSION_MAX_ALLOWED must be >= NM_VERSION_MIN_REQUIRED"
+#endif
+#if NM_VERSION_MIN_REQUIRED < NM_VERSION_0_9_8
+#error "NM_VERSION_MIN_REQUIRED must be >= NM_VERSION_0_9_8"
+#endif
+
+#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_0_9_10
+# define NM_DEPRECATED_IN_0_9_10 G_DEPRECATED
+# define NM_DEPRECATED_IN_0_9_10_FOR(f) G_DEPRECATED_FOR(f)
+#else
+# define NM_DEPRECATED_IN_0_9_10
+# define NM_DEPRECATED_IN_0_9_10_FOR(f)
+#endif
+
+#if NM_VERSION_MIN_REQUIRED >= NM_VERSION_1_0
+# define NM_DEPRECATED_IN_1_0 G_DEPRECATED
+# define NM_DEPRECATED_IN_1_0_FOR(f) G_DEPRECATED_FOR(f)
+#else
+# define NM_DEPRECATED_IN_1_0
+# define NM_DEPRECATED_IN_1_0_FOR(f)
+#endif
+
+#if NM_VERSION_MAX_ALLOWED < NM_VERSION_0_9_10
+# define NM_AVAILABLE_IN_0_9_10 G_UNAVAILABLE(0.9,10)
+#else
+# define NM_AVAILABLE_IN_0_9_10
+#endif
+
+#if NM_VERSION_MAX_ALLOWED < NM_VERSION_1_0
+# define NM_AVAILABLE_IN_1_0 G_UNAVAILABLE(1,0)
+#else
+# define NM_AVAILABLE_IN_1_0
+#endif
+
+#endif /* NM_VERSION_H */
diff --git a/libnm-core/nm-vpn-dbus-interface.h b/libnm-core/nm-vpn-dbus-interface.h
new file mode 100644
index 000000000..c4099be2a
--- /dev/null
+++ b/libnm-core/nm-vpn-dbus-interface.h
@@ -0,0 +1,307 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2004 Red Hat, Inc.
+ */
+
+/* D-Bus-related definitions for NetworkManager VPN plugins.
+ *
+ * Note that although this header is installed as part of libnm, it is also
+ * used by some external code that does not link to libnm.
+ */
+
+#ifndef __NM_VPN_DBUS_INTERFACE_H__
+#define __NM_VPN_DBUS_INTERFACE_H__
+
+/*
+ * dbus services details
+ */
+#define NM_DBUS_PATH_VPN "/org/freedesktop/NetworkManager/VPN/Manager"
+#define NM_DBUS_INTERFACE_VPN "org.freedesktop.NetworkManager.VPN.Manager"
+
+#define NM_DBUS_PATH_VPN_CONNECTION "/org/freedesktop/NetworkManager/VPN/Connection"
+#define NM_DBUS_INTERFACE_VPN_CONNECTION "org.freedesktop.NetworkManager.VPN.Connection"
+
+#define NM_VPN_DBUS_PLUGIN_PATH "/org/freedesktop/NetworkManager/VPN/Plugin"
+#define NM_VPN_DBUS_PLUGIN_INTERFACE "org.freedesktop.NetworkManager.VPN.Plugin"
+
+/*
+ * VPN Errors
+ */
+#define NM_DBUS_NO_ACTIVE_VPN_CONNECTION "org.freedesktop.NetworkManager.VPNConnections.NoActiveVPNConnection"
+#define NM_DBUS_NO_VPN_CONNECTIONS "org.freedesktop.NetworkManager.VPNConnections.NoVPNConnections"
+#define NM_DBUS_INVALID_VPN_CONNECTION "org.freedesktop.NetworkManager.VPNConnections.InvalidVPNConnection"
+
+#define NM_DBUS_VPN_ERROR_PREFIX "org.freedesktop.NetworkManager.VPN.Error"
+#define NM_DBUS_VPN_STARTING_IN_PROGRESS "StartingInProgress"
+#define NM_DBUS_VPN_ALREADY_STARTED "AlreadyStarted"
+#define NM_DBUS_VPN_STOPPING_IN_PROGRESS "StoppingInProgress"
+#define NM_DBUS_VPN_ALREADY_STOPPED "AlreadyStopped"
+#define NM_DBUS_VPN_WRONG_STATE "WrongState"
+#define NM_DBUS_VPN_BAD_ARGUMENTS "BadArguments"
+#define NM_DBUS_VPN_INTERACTIVE_NOT_SUPPORTED "InteractiveNotSupported"
+
+
+/*
+ * VPN daemon signals
+ */
+#define NM_DBUS_VPN_SIGNAL_LOGIN_BANNER "LoginBanner"
+#define NM_DBUS_VPN_SIGNAL_LOGIN_FAILED "LoginFailed"
+#define NM_DBUS_VPN_SIGNAL_LAUNCH_FAILED "LaunchFailed"
+#define NM_DBUS_VPN_SIGNAL_CONNECT_FAILED "ConnectFailed"
+#define NM_DBUS_VPN_SIGNAL_VPN_CONFIG_BAD "VPNConfigBad"
+#define NM_DBUS_VPN_SIGNAL_IP_CONFIG_BAD "IPConfigBad"
+#define NM_DBUS_VPN_SIGNAL_STATE_CHANGE "StateChange"
+#define NM_DBUS_VPN_SIGNAL_IP4_CONFIG "IP4Config"
+
+/**
+ * NMVpnServiceState:
+ * @NM_VPN_SERVICE_STATE_UNKNOWN: The state of the VPN plugin is unknown.
+ * @NM_VPN_SERVICE_STATE_INIT: The VPN plugin is initialized.
+ * @NM_VPN_SERVICE_STATE_SHUTDOWN: Not used.
+ * @NM_VPN_SERVICE_STATE_STARTING: The plugin is attempting to connect to a VPN server.
+ * @NM_VPN_SERVICE_STATE_STARTED: The plugin has connected to a VPN server.
+ * @NM_VPN_SERVICE_STATE_STOPPING: The plugin is disconnecting from the VPN server.
+ * @NM_VPN_SERVICE_STATE_STOPPED: The plugin has disconnected from the VPN server.
+ *
+ * VPN daemon states
+ *
+ * (Corresponds to the NM_VPN_SERVICE_STATE type in nm-vpn-connection.xml.)
+ */
+typedef enum {
+ NM_VPN_SERVICE_STATE_UNKNOWN = 0,
+ NM_VPN_SERVICE_STATE_INIT,
+ NM_VPN_SERVICE_STATE_SHUTDOWN,
+ NM_VPN_SERVICE_STATE_STARTING,
+ NM_VPN_SERVICE_STATE_STARTED,
+ NM_VPN_SERVICE_STATE_STOPPING,
+ NM_VPN_SERVICE_STATE_STOPPED
+} NMVpnServiceState;
+
+
+/**
+ * NMVpnConnectionState:
+ * @NM_VPN_CONNECTION_STATE_UNKNOWN: The state of the VPN connection is
+ * unknown.
+ * @NM_VPN_CONNECTION_STATE_PREPARE: The VPN connection is preparing to
+ * connect.
+ * @NM_VPN_CONNECTION_STATE_NEED_AUTH: The VPN connection needs authorization
+ * credentials.
+ * @NM_VPN_CONNECTION_STATE_CONNECT: The VPN connection is being established.
+ * @NM_VPN_CONNECTION_STATE_IP_CONFIG_GET: The VPN connection is getting an IP
+ * address.
+ * @NM_VPN_CONNECTION_STATE_ACTIVATED: The VPN connection is active.
+ * @NM_VPN_CONNECTION_STATE_FAILED: The VPN connection failed.
+ * @NM_VPN_CONNECTION_STATE_DISCONNECTED: The VPN connection is disconnected.
+ *
+ * VPN connection states
+ *
+ * (Corresponds to the NM_VPN_CONNECTION_STATE type in nm-vpn-connection.xml.)
+ */
+typedef enum {
+ NM_VPN_CONNECTION_STATE_UNKNOWN = 0,
+ NM_VPN_CONNECTION_STATE_PREPARE,
+ NM_VPN_CONNECTION_STATE_NEED_AUTH,
+ NM_VPN_CONNECTION_STATE_CONNECT,
+ NM_VPN_CONNECTION_STATE_IP_CONFIG_GET,
+ NM_VPN_CONNECTION_STATE_ACTIVATED,
+ NM_VPN_CONNECTION_STATE_FAILED,
+ NM_VPN_CONNECTION_STATE_DISCONNECTED
+} NMVpnConnectionState;
+
+/**
+ * NMVpnConnectionStateReason:
+ * @NM_VPN_CONNECTION_STATE_REASON_UNKNOWN: The reason for the VPN connection
+ * state change is unknown.
+ * @NM_VPN_CONNECTION_STATE_REASON_NONE: No reason was given for the VPN
+ * connection state change.
+ * @NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED: The VPN connection changed
+ * state because the user disconnected it.
+ * @NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED: The VPN connection
+ * changed state because the device it was using was disconnected.
+ * @NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED: The service providing the
+ * VPN connection was stopped.
+ * @NM_VPN_CONNECTION_STATE_REASON_IP_CONFIG_INVALID: The IP config of the VPN
+ * connection was invalid.
+ * @NM_VPN_CONNECTION_STATE_REASON_CONNECT_TIMEOUT: The connection attempt to
+ * the VPN service timed out.
+ * @NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT: A timeout occurred
+ * while starting the service providing the VPN connection.
+ * @NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED: Starting the service
+ * starting the service providing the VPN connection failed.
+ * @NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS: Necessary secrets for the VPN
+ * connection were not provided.
+ * @NM_VPN_CONNECTION_STATE_REASON_LOGIN_FAILED: Authentication to the VPN
+ * server failed.
+ * @NM_VPN_CONNECTION_STATE_REASON_CONNECTION_REMOVED: The connection was
+ * deleted from settings.
+ *
+ * VPN connection state reasons
+ *
+ * (Corresponds to the NM_VPN_CONNECTION_STATE_REASON type in nm-vpn-connection.xml.)
+ */
+typedef enum {
+ NM_VPN_CONNECTION_STATE_REASON_UNKNOWN = 0,
+ NM_VPN_CONNECTION_STATE_REASON_NONE,
+ NM_VPN_CONNECTION_STATE_REASON_USER_DISCONNECTED,
+ NM_VPN_CONNECTION_STATE_REASON_DEVICE_DISCONNECTED,
+ NM_VPN_CONNECTION_STATE_REASON_SERVICE_STOPPED,
+ NM_VPN_CONNECTION_STATE_REASON_IP_CONFIG_INVALID,
+ NM_VPN_CONNECTION_STATE_REASON_CONNECT_TIMEOUT,
+ NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_TIMEOUT,
+ NM_VPN_CONNECTION_STATE_REASON_SERVICE_START_FAILED,
+ NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS,
+ NM_VPN_CONNECTION_STATE_REASON_LOGIN_FAILED,
+ NM_VPN_CONNECTION_STATE_REASON_CONNECTION_REMOVED
+} NMVpnConnectionStateReason;
+
+/**
+ * NMVpnPluginFailure:
+ * @NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED: Login failed.
+ * @NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED: Connect failed.
+ * @NM_VPN_PLUGIN_FAILURE_BAD_IP_CONFIG: Invalid IP configuration returned from
+ * the VPN plugin.
+ *
+ * VPN plugin failure reasons
+ *
+ * (Corresponds to the NM_VPN_PLUGIN_FAILURE type in nm-vpn-plugin.xml.)
+ */
+typedef enum {
+ NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED,
+ NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED,
+ NM_VPN_PLUGIN_FAILURE_BAD_IP_CONFIG
+} NMVpnPluginFailure;
+
+
+/*** Generic config ***/
+
+/* string: VPN interface name (tun0, tap0, etc) */
+#define NM_VPN_PLUGIN_CONFIG_TUNDEV "tundev"
+
+/* string: Login message */
+#define NM_VPN_PLUGIN_CONFIG_BANNER "banner"
+
+/* uint32 / array of uint8: IP address of the public external VPN gateway (network byte order) */
+#define NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY "gateway"
+
+/* uint32: Maximum Transfer Unit that the VPN interface should use */
+#define NM_VPN_PLUGIN_CONFIG_MTU "mtu"
+
+/* boolean: Has IP4 configuration? */
+#define NM_VPN_PLUGIN_CONFIG_HAS_IP4 "has-ip4"
+
+/* boolean: Has IP6 configuration? */
+#define NM_VPN_PLUGIN_CONFIG_HAS_IP6 "has-ip6"
+
+/* boolean: If %TRUE the VPN plugin can persist/reconnect the connection over
+ * link changes and VPN server dropouts.
+ */
+#define NM_VPN_PLUGIN_CAN_PERSIST "can-persist"
+
+
+/*** Ip4Config ***/
+
+/* uint32: IP address of the internal gateway of the subnet the VPN interface is
+ * on, if the VPN uses subnet configuration (network byte order)
+ */
+#define NM_VPN_PLUGIN_IP4_CONFIG_INT_GATEWAY "internal-gateway"
+
+/* uint32: internal IP address of the local VPN interface (network byte order) */
+#define NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS "address"
+
+/* uint32: IP address of the other side of Point-to-Point connection if the VPN
+ * uses Point-to-Point configuration. (network byte order)
+ */
+#define NM_VPN_PLUGIN_IP4_CONFIG_PTP "ptp"
+
+/* uint32: IP prefix of the VPN interface; 1 - 32 inclusive */
+#define NM_VPN_PLUGIN_IP4_CONFIG_PREFIX "prefix"
+
+/* array of uint32: IP addresses of DNS servers for the VPN (network byte order) */
+#define NM_VPN_PLUGIN_IP4_CONFIG_DNS "dns"
+
+/* array of uint32: IP addresses of NBNS/WINS servers for the VPN (network byte order) */
+#define NM_VPN_PLUGIN_IP4_CONFIG_NBNS "nbns"
+
+/* uint32: Message Segment Size that the VPN interface should use */
+#define NM_VPN_PLUGIN_IP4_CONFIG_MSS "mss"
+
+/* string: DNS domain name */
+#define NM_VPN_PLUGIN_IP4_CONFIG_DOMAIN "domain"
+
+/* array of strings: DNS domain names */
+#define NM_VPN_PLUGIN_IP4_CONFIG_DOMAINS "domains"
+
+/* [ip4 routes]: custom routes the client should apply, in the format used
+ * by nm_utils_ip4_routes_to/from_gvalue
+ */
+#define NM_VPN_PLUGIN_IP4_CONFIG_ROUTES "routes"
+
+/* boolean: prevent this VPN connection from ever getting the default route */
+#define NM_VPN_PLUGIN_IP4_CONFIG_NEVER_DEFAULT "never-default"
+
+/* Deprecated */
+#define NM_VPN_PLUGIN_IP4_CONFIG_GATEWAY NM_VPN_PLUGIN_IP4_CONFIG_EXT_GATEWAY
+
+/* Legacy IP4 items; these are included in the IP4 config by older plugins,
+ * but in the generic config by newer plugins.
+ */
+
+#define NM_VPN_PLUGIN_IP4_CONFIG_BANNER NM_VPN_PLUGIN_CONFIG_BANNER
+#define NM_VPN_PLUGIN_IP4_CONFIG_EXT_GATEWAY NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY
+#define NM_VPN_PLUGIN_IP4_CONFIG_MTU NM_VPN_PLUGIN_CONFIG_MTU
+#define NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV NM_VPN_PLUGIN_CONFIG_TUNDEV
+
+
+/*** Ip6Config ***/
+
+/* array of uint8: IP address of the internal gateway of the subnet the VPN interface is
+ * on, if the VPN uses subnet configuration (network byte order)
+ */
+#define NM_VPN_PLUGIN_IP6_CONFIG_INT_GATEWAY "internal-gateway"
+
+/* array of uint8: internal IP address of the local VPN interface (network byte order) */
+#define NM_VPN_PLUGIN_IP6_CONFIG_ADDRESS "address"
+
+/* array of uint8: IP address of the other side of Point-to-Point connection if the VPN
+ * uses Point-to-Point configuration. (network byte order)
+ */
+#define NM_VPN_PLUGIN_IP6_CONFIG_PTP "ptp"
+
+/* uint32: prefix length of the VPN interface; 1 - 128 inclusive */
+#define NM_VPN_PLUGIN_IP6_CONFIG_PREFIX "prefix"
+
+/* array of array of uint8: IP addresses of DNS servers for the VPN (network byte order) */
+#define NM_VPN_PLUGIN_IP6_CONFIG_DNS "dns"
+
+/* uint32: Message Segment Size that the VPN interface should use */
+#define NM_VPN_PLUGIN_IP6_CONFIG_MSS "mss"
+
+/* string: DNS domain name */
+#define NM_VPN_PLUGIN_IP6_CONFIG_DOMAIN "domain"
+
+/* array of strings: DNS domain names */
+#define NM_VPN_PLUGIN_IP6_CONFIG_DOMAINS "domains"
+
+/* [ip6 routes]: custom routes the client should apply, in the format used
+ * by nm_utils_ip6_routes_to/from_gvalue
+ */
+#define NM_VPN_PLUGIN_IP6_CONFIG_ROUTES "routes"
+
+/* boolean: prevent this VPN connection from ever getting the default route */
+#define NM_VPN_PLUGIN_IP6_CONFIG_NEVER_DEFAULT "never-default"
+
+#endif /* __NM_VPN_DBUS_INTERFACE_H__ */
diff --git a/libnm-core/tests/Makefile.am b/libnm-core/tests/Makefile.am
new file mode 100644
index 000000000..a21c131cb
--- /dev/null
+++ b/libnm-core/tests/Makefile.am
@@ -0,0 +1,56 @@
+if ENABLE_TESTS
+
+certsdir = $(srcdir)/certs
+
+AM_CPPFLAGS = \
+ -I${top_srcdir}/include \
+ -I$(top_srcdir)/libnm-core \
+ -I$(top_builddir)/libnm-core \
+ -DNETWORKMANAGER_COMPILATION \
+ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
+ $(GLIB_CFLAGS) \
+ -DTEST_CERT_DIR=\"$(certsdir)\"
+
+noinst_PROGRAMS = \
+ test-compare \
+ test-crypto \
+ test-general \
+ test-secrets \
+ test-setting-8021x \
+ test-setting-dcb \
+ test-settings-defaults
+
+LDADD = \
+ $(top_builddir)/libnm-core/libnm-core.la \
+ $(GLIB_LIBS)
+
+TESTS = $(noinst_PROGRAMS)
+
+endif
+
+# test-cert.p12 created with:
+#
+# openssl pkcs12 -export \
+# -in test_key_and_cert.pem \
+# -inkey test_key_and_cert.pem \
+# -certfile test_ca_cert.pem \
+# -name "test-pkcs12" \
+# -out test-cert.p12
+
+EXTRA_DIST = \
+ certs/test_ca_cert.pem \
+ certs/test_ca_cert.der \
+ certs/test_key_and_cert.pem \
+ certs/test-cert.p12 \
+ certs/test2_ca_cert.pem \
+ certs/test2_key_and_cert.pem \
+ certs/test2-cert.p12 \
+ certs/ca-no-ending-newline.pem \
+ certs/test-key-only.pem \
+ certs/test-key-only-decrypted.der \
+ certs/test-key-only-decrypted.pem \
+ certs/pkcs8-enc-key.pem \
+ certs/pkcs8-noenc-key.pem \
+ certs/pkcs8-decrypted.der \
+ certs/test-aes-key.pem
+
diff --git a/libnm-core/tests/Makefile.in b/libnm-core/tests/Makefile.in
new file mode 100644
index 000000000..b62df8b45
--- /dev/null
+++ b/libnm-core/tests/Makefile.in
@@ -0,0 +1,959 @@
+# Makefile.in generated by automake 1.13.4 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+@ENABLE_TESTS_TRUE@noinst_PROGRAMS = test-compare$(EXEEXT) \
+@ENABLE_TESTS_TRUE@ test-crypto$(EXEEXT) test-general$(EXEEXT) \
+@ENABLE_TESTS_TRUE@ test-secrets$(EXEEXT) \
+@ENABLE_TESTS_TRUE@ test-setting-8021x$(EXEEXT) \
+@ENABLE_TESTS_TRUE@ test-setting-dcb$(EXEEXT) \
+@ENABLE_TESTS_TRUE@ test-settings-defaults$(EXEEXT)
+subdir = libnm-core/tests
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/build-aux/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \
+ $(top_srcdir)/m4/compiler_warnings.m4 \
+ $(top_srcdir)/m4/gettext.m4 \
+ $(top_srcdir)/m4/gnome-code-coverage.m4 \
+ $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \
+ $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \
+ $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/lib-ld.m4 \
+ $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \
+ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \
+ $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+PROGRAMS = $(noinst_PROGRAMS)
+test_compare_SOURCES = test-compare.c
+test_compare_OBJECTS = test-compare.$(OBJEXT)
+test_compare_LDADD = $(LDADD)
+am__DEPENDENCIES_1 =
+@ENABLE_TESTS_TRUE@test_compare_DEPENDENCIES = \
+@ENABLE_TESTS_TRUE@ $(top_builddir)/libnm-core/libnm-core.la \
+@ENABLE_TESTS_TRUE@ $(am__DEPENDENCIES_1)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+test_crypto_SOURCES = test-crypto.c
+test_crypto_OBJECTS = test-crypto.$(OBJEXT)
+test_crypto_LDADD = $(LDADD)
+@ENABLE_TESTS_TRUE@test_crypto_DEPENDENCIES = \
+@ENABLE_TESTS_TRUE@ $(top_builddir)/libnm-core/libnm-core.la \
+@ENABLE_TESTS_TRUE@ $(am__DEPENDENCIES_1)
+test_general_SOURCES = test-general.c
+test_general_OBJECTS = test-general.$(OBJEXT)
+test_general_LDADD = $(LDADD)
+@ENABLE_TESTS_TRUE@test_general_DEPENDENCIES = \
+@ENABLE_TESTS_TRUE@ $(top_builddir)/libnm-core/libnm-core.la \
+@ENABLE_TESTS_TRUE@ $(am__DEPENDENCIES_1)
+test_secrets_SOURCES = test-secrets.c
+test_secrets_OBJECTS = test-secrets.$(OBJEXT)
+test_secrets_LDADD = $(LDADD)
+@ENABLE_TESTS_TRUE@test_secrets_DEPENDENCIES = \
+@ENABLE_TESTS_TRUE@ $(top_builddir)/libnm-core/libnm-core.la \
+@ENABLE_TESTS_TRUE@ $(am__DEPENDENCIES_1)
+test_setting_8021x_SOURCES = test-setting-8021x.c
+test_setting_8021x_OBJECTS = test-setting-8021x.$(OBJEXT)
+test_setting_8021x_LDADD = $(LDADD)
+@ENABLE_TESTS_TRUE@test_setting_8021x_DEPENDENCIES = \
+@ENABLE_TESTS_TRUE@ $(top_builddir)/libnm-core/libnm-core.la \
+@ENABLE_TESTS_TRUE@ $(am__DEPENDENCIES_1)
+test_setting_dcb_SOURCES = test-setting-dcb.c
+test_setting_dcb_OBJECTS = test-setting-dcb.$(OBJEXT)
+test_setting_dcb_LDADD = $(LDADD)
+@ENABLE_TESTS_TRUE@test_setting_dcb_DEPENDENCIES = \
+@ENABLE_TESTS_TRUE@ $(top_builddir)/libnm-core/libnm-core.la \
+@ENABLE_TESTS_TRUE@ $(am__DEPENDENCIES_1)
+test_settings_defaults_SOURCES = test-settings-defaults.c
+test_settings_defaults_OBJECTS = test-settings-defaults.$(OBJEXT)
+test_settings_defaults_LDADD = $(LDADD)
+@ENABLE_TESTS_TRUE@test_settings_defaults_DEPENDENCIES = \
+@ENABLE_TESTS_TRUE@ $(top_builddir)/libnm-core/libnm-core.la \
+@ENABLE_TESTS_TRUE@ $(am__DEPENDENCIES_1)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = test-compare.c test-crypto.c test-general.c test-secrets.c \
+ test-setting-8021x.c test-setting-dcb.c \
+ test-settings-defaults.c
+DIST_SOURCES = test-compare.c test-crypto.c test-general.c \
+ test-secrets.c test-setting-8021x.c test-setting-dcb.c \
+ test-settings-defaults.c
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors_dummy = \
+ mgn= red= grn= lgn= blu= brg= std=; \
+ am__color_tests=no
+am__tty_colors = { \
+ $(am__tty_colors_dummy); \
+ if test "X$(AM_COLOR_TESTS)" = Xno; then \
+ am__color_tests=no; \
+ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+ am__color_tests=yes; \
+ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+ am__color_tests=yes; \
+ fi; \
+ if test $$am__color_tests = yes; then \
+ red=''; \
+ grn=''; \
+ lgn=''; \
+ blu=''; \
+ mgn=''; \
+ brg=''; \
+ std=''; \
+ fi; \
+}
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BLUEZ5_CFLAGS = @BLUEZ5_CFLAGS@
+BLUEZ5_LIBS = @BLUEZ5_LIBS@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CKDB_PATH = @CKDB_PATH@
+CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@
+CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@
+CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@
+DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@
+DBUS_LIBS = @DBUS_LIBS@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DHCLIENT_PATH = @DHCLIENT_PATH@
+DHCPCD_PATH = @DHCPCD_PATH@
+DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@
+DLLTOOL = @DLLTOOL@
+DNSMASQ_PATH = @DNSMASQ_PATH@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GENHTML = @GENHTML@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MAKEFILE = @GLIB_MAKEFILE@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@
+GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@
+GTKDOC_MKPDF = @GTKDOC_MKPDF@
+GTKDOC_REBASE = @GTKDOC_REBASE@
+GUDEV_CFLAGS = @GUDEV_CFLAGS@
+GUDEV_LIBS = @GUDEV_LIBS@
+HTML_DIR = @HTML_DIR@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
+INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
+INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
+INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
+INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@
+INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@
+INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@
+INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@
+INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@
+INTROSPECTION_LIBS = @INTROSPECTION_LIBS@
+INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@
+INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@
+INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@
+IPTABLES_PATH = @IPTABLES_PATH@
+IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@
+IWMX_SDK_LIBS = @IWMX_SDK_LIBS@
+KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBDL = @LIBDL@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBM = @LIBM@
+LIBNDP_CFLAGS = @LIBNDP_CFLAGS@
+LIBNDP_LIBS = @LIBNDP_LIBS@
+LIBNL_CFLAGS = @LIBNL_CFLAGS@
+LIBNL_LIBS = @LIBNL_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@
+LIBSOUP_LIBS = @LIBSOUP_LIBS@
+LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@
+LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBICONV = @LTLIBICONV@
+LTLIBINTL = @LTLIBINTL@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MM_GLIB_CFLAGS = @MM_GLIB_CFLAGS@
+MM_GLIB_LIBS = @MM_GLIB_LIBS@
+MOC = @MOC@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NEWT_CFLAGS = @NEWT_CFLAGS@
+NEWT_LIBS = @NEWT_LIBS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@
+NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
+NM_MICRO_VERSION = @NM_MICRO_VERSION@
+NM_MINOR_VERSION = @NM_MINOR_VERSION@
+NM_MODIFY_SYSTEM_POLICY = @NM_MODIFY_SYSTEM_POLICY@
+NM_VERSION = @NM_VERSION@
+NSS_CFLAGS = @NSS_CFLAGS@
+NSS_LIBS = @NSS_LIBS@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POLKIT_CFLAGS = @POLKIT_CFLAGS@
+POLKIT_LIBS = @POLKIT_LIBS@
+POSUB = @POSUB@
+PPPD_PATH = @PPPD_PATH@
+PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
+PPPOE_PATH = @PPPOE_PATH@
+QT_CFLAGS = @QT_CFLAGS@
+QT_LIBS = @QT_LIBS@
+RANLIB = @RANLIB@
+READLINE_LIBS = @READLINE_LIBS@
+SED = @SED@
+SELINUX_CFLAGS = @SELINUX_CFLAGS@
+SELINUX_LIBS = @SELINUX_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@
+SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@
+SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@
+SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@
+SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@
+SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@
+SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
+UDEV_DIR = @UDEV_DIR@
+USE_NLS = @USE_NLS@
+UUID_CFLAGS = @UUID_CFLAGS@
+UUID_LIBS = @UUID_LIBS@
+VALGRIND_RULES = @VALGRIND_RULES@
+VAPIGEN = @VAPIGEN@
+VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@
+VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+XGETTEXT_015 = @XGETTEXT_015@
+XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+intltool__v_merge_options_ = @intltool__v_merge_options_@
+intltool__v_merge_options_0 = @intltool__v_merge_options_0@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+nmbinary = @nmbinary@
+nmconfdir = @nmconfdir@
+nmdatadir = @nmdatadir@
+nmrundir = @nmrundir@
+nmstatedir = @nmstatedir@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+systemdsystemunitdir = @systemdsystemunitdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+with_dhclient = @with_dhclient@
+with_dhcpcd = @with_dhcpcd@
+with_netconfig = @with_netconfig@
+with_resolvconf = @with_resolvconf@
+with_valgrind = @with_valgrind@
+@ENABLE_TESTS_TRUE@certsdir = $(srcdir)/certs
+@ENABLE_TESTS_TRUE@AM_CPPFLAGS = \
+@ENABLE_TESTS_TRUE@ -I${top_srcdir}/include \
+@ENABLE_TESTS_TRUE@ -I$(top_srcdir)/libnm-core \
+@ENABLE_TESTS_TRUE@ -I$(top_builddir)/libnm-core \
+@ENABLE_TESTS_TRUE@ -DNETWORKMANAGER_COMPILATION \
+@ENABLE_TESTS_TRUE@ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
+@ENABLE_TESTS_TRUE@ $(GLIB_CFLAGS) \
+@ENABLE_TESTS_TRUE@ -DTEST_CERT_DIR=\"$(certsdir)\"
+
+@ENABLE_TESTS_TRUE@LDADD = \
+@ENABLE_TESTS_TRUE@ $(top_builddir)/libnm-core/libnm-core.la \
+@ENABLE_TESTS_TRUE@ $(GLIB_LIBS)
+
+@ENABLE_TESTS_TRUE@TESTS = $(noinst_PROGRAMS)
+
+# test-cert.p12 created with:
+#
+# openssl pkcs12 -export \
+# -in test_key_and_cert.pem \
+# -inkey test_key_and_cert.pem \
+# -certfile test_ca_cert.pem \
+# -name "test-pkcs12" \
+# -out test-cert.p12
+EXTRA_DIST = \
+ certs/test_ca_cert.pem \
+ certs/test_ca_cert.der \
+ certs/test_key_and_cert.pem \
+ certs/test-cert.p12 \
+ certs/test2_ca_cert.pem \
+ certs/test2_key_and_cert.pem \
+ certs/test2-cert.p12 \
+ certs/ca-no-ending-newline.pem \
+ certs/test-key-only.pem \
+ certs/test-key-only-decrypted.der \
+ certs/test-key-only-decrypted.pem \
+ certs/pkcs8-enc-key.pem \
+ certs/pkcs8-noenc-key.pem \
+ certs/pkcs8-decrypted.der \
+ certs/test-aes-key.pem
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libnm-core/tests/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu libnm-core/tests/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+test-compare$(EXEEXT): $(test_compare_OBJECTS) $(test_compare_DEPENDENCIES) $(EXTRA_test_compare_DEPENDENCIES)
+ @rm -f test-compare$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_compare_OBJECTS) $(test_compare_LDADD) $(LIBS)
+
+test-crypto$(EXEEXT): $(test_crypto_OBJECTS) $(test_crypto_DEPENDENCIES) $(EXTRA_test_crypto_DEPENDENCIES)
+ @rm -f test-crypto$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_crypto_OBJECTS) $(test_crypto_LDADD) $(LIBS)
+
+test-general$(EXEEXT): $(test_general_OBJECTS) $(test_general_DEPENDENCIES) $(EXTRA_test_general_DEPENDENCIES)
+ @rm -f test-general$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_general_OBJECTS) $(test_general_LDADD) $(LIBS)
+
+test-secrets$(EXEEXT): $(test_secrets_OBJECTS) $(test_secrets_DEPENDENCIES) $(EXTRA_test_secrets_DEPENDENCIES)
+ @rm -f test-secrets$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_secrets_OBJECTS) $(test_secrets_LDADD) $(LIBS)
+
+test-setting-8021x$(EXEEXT): $(test_setting_8021x_OBJECTS) $(test_setting_8021x_DEPENDENCIES) $(EXTRA_test_setting_8021x_DEPENDENCIES)
+ @rm -f test-setting-8021x$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_setting_8021x_OBJECTS) $(test_setting_8021x_LDADD) $(LIBS)
+
+test-setting-dcb$(EXEEXT): $(test_setting_dcb_OBJECTS) $(test_setting_dcb_DEPENDENCIES) $(EXTRA_test_setting_dcb_DEPENDENCIES)
+ @rm -f test-setting-dcb$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_setting_dcb_OBJECTS) $(test_setting_dcb_LDADD) $(LIBS)
+
+test-settings-defaults$(EXEEXT): $(test_settings_defaults_OBJECTS) $(test_settings_defaults_DEPENDENCIES) $(EXTRA_test_settings_defaults_DEPENDENCIES)
+ @rm -f test-settings-defaults$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(test_settings_defaults_OBJECTS) $(test_settings_defaults_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-compare.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-crypto.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-general.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-secrets.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-setting-8021x.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-setting-dcb.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-settings-defaults.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ $(am__tty_colors); \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=XPASS; \
+ ;; \
+ *) \
+ col=$$grn; res=PASS; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xfail=`expr $$xfail + 1`; \
+ col=$$lgn; res=XFAIL; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=FAIL; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ col=$$blu; res=SKIP; \
+ fi; \
+ echo "$${col}$$res$${std}: $$tst"; \
+ done; \
+ if test "$$all" -eq 1; then \
+ tests="test"; \
+ All=""; \
+ else \
+ tests="tests"; \
+ All="All "; \
+ fi; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="$$All$$all $$tests passed"; \
+ else \
+ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all $$tests failed"; \
+ else \
+ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ if test "$$skip" -eq 1; then \
+ skipped="($$skip test was not run)"; \
+ else \
+ skipped="($$skip tests were not run)"; \
+ fi; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ if test "$$failed" -eq 0; then \
+ col="$$grn"; \
+ else \
+ col="$$red"; \
+ fi; \
+ echo "$${col}$$dashes$${std}"; \
+ echo "$${col}$$banner$${std}"; \
+ test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \
+ test -z "$$report" || echo "$${col}$$report$${std}"; \
+ echo "$${col}$$dashes$${std}"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \
+ clean-generic clean-libtool clean-noinstPROGRAMS cscopelist-am \
+ ctags ctags-am distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/libnm-core/tests/certs/ca-no-ending-newline.pem b/libnm-core/tests/certs/ca-no-ending-newline.pem
new file mode 100644
index 000000000..664e299aa
--- /dev/null
+++ b/libnm-core/tests/certs/ca-no-ending-newline.pem
@@ -0,0 +1,15 @@
+-----BEGIN CERTIFICATE-----
+MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD
+VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv
+bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv
+b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV
+UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU
+cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds
+b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH
+iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS
+r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4
+04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r
+GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9
+3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P
+lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/
+-----END CERTIFICATE----- \ No newline at end of file
diff --git a/libnm-core/tests/certs/pkcs8-decrypted.der b/libnm-core/tests/certs/pkcs8-decrypted.der
new file mode 100644
index 000000000..2cbdeb5e3
--- /dev/null
+++ b/libnm-core/tests/certs/pkcs8-decrypted.der
Binary files differ
diff --git a/libnm-core/tests/certs/pkcs8-enc-key.pem b/libnm-core/tests/certs/pkcs8-enc-key.pem
new file mode 100644
index 000000000..0d08f2d29
--- /dev/null
+++ b/libnm-core/tests/certs/pkcs8-enc-key.pem
@@ -0,0 +1,29 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE6TAbBgkqhkiG9w0BBQMwDgQIwiGFT4Jz6RsCAggABIIEyJNMddDYofbhydUp
+J3VyrYIjv3LziJ7dkTXE3+mEYRCQrGLgljWBbib2JOLVCFt8melL6Yv1RcoVR7X7
+vrRqyycu0DumI4f5+Bf4wc234JNVhSaLYsw244fFtcnK2Gyn4IaVmWmrNvrwfX/w
+SKcVmO30D5C5PCKzv2bou5FmnJLKdDQV1t816cr9T8pTx7MHvBzSZXbh86334BhF
+T3zNwo8j2/+Gq2NBWUn+2GTTV8/r26aIwPcFi4QH6I2ghBwFmFHqU3/PoRm6nkmg
+CqJj2Dggy+8zE5qg0iId7lrio0OjCH+Qed6NGwIa2lgv/bhuJVP3FOk4gqamJWHi
+WMaq9McmS+03q2iokYeSQGbx85x+I90RTFZKhFx4dkerf6oTC/YoL4F++ff0e91v
+sOrQsBkgRhrRtFwa9OFCzbsknlixONdd+ITkyX490xz1wcZTDkKtMDRLIPWa2O0b
+MEq75jPYThZ5pF1vc5r+rqPafN7SfI+DDmhzJYEQNRoCWA4pH9Gwv0ayKnOgoj4K
+TuFhXvcyWzTnVXmcqEFyf3CRrB0Ti+Z61enupC+FCuYV5lGsx9kJaTumTk2UPD02
+9Ap3asDLozdEPSXBG3+oCM2s01/IJlxtR84C97r9rpmWTc9K6DCBScETe9KnIghW
+PU7XFogueG5Gwpe+x+IlTDq+qiyUNVX1uMGDcIaCC3VsoWqZrpnGGBhsovwBaXKt
+T9fT2nE27Fd6DRWso4fgos6PPx7RVveu17BTMVQeUq9L8GrV4JNrE3a9aoXdbUhc
+6gMiyAqxh/HEyciYoXsR9oVNi+VM0y8q3hL5nIcgDrCZr/c9aQ8+fuQBDXRrmrQd
+bR2iwNLCBnbmQmM/vM333VhJ4MSOKd3SGw/j41K+Nr3uP5KRZUwV+5yy3ef/hGxU
+i9JjCmSUt2bfWRUFlNaf1hCTYaKD0xnVr1SLFU4snIgh2qKawyqVc9EE2f+FcOM5
+0RtwQ3ku6FOk3cy6/xeKpResCHbWDS6nQaIKYyLukV+gm5MJIhOMkj2z4T1eXGUr
+Nu/L7Gz+ps7ct0lM8W82n5lzSEa5/l1eNGM0wtQoAwutFEZp7Nx/IBKK87jVttr6
+82UVJeRk7rO2Mpobfw2LbKwga4rsuLrx3UwVDBWdLx7dNIc1rGoAxhsc72+skFgF
+Uztwy4Yv1Uiji4T6v+mObPZD/HiIDL0vF02Pz08rNlgB0DgaTKrpql2FutIuQAdf
+AciffQIoh9VGERlJoWuunG/UTxg2XRl2m1vCDrgBMInax+PXCv7/5Vh21AQc3fWP
+uf4k6JSy46hYni7VTVKn6C/Di9z7oIrGl/jDkDsaenAbToyX9VWr3s7EBwnhTQ/I
+OQ9bkWCagHIQlwJbu4M4/VAbiR26NrcR0C3JXBlPlT0qvFFB8gKbJAQEXtwIFS2h
+m2fe0k6mQASMwdbJYXZ/wfsg5PPAWsKtny1aMvi0mTPSD5uRhIfEGEuR+AT4UbEW
+BkEIE0lgGly4P1SpunKDQQE6m/e7h8Nl4pi8SMSme3YoX5MJwCP/CNkLBDVenAZI
+oBrdoVox86SjwnUozVG192lcEAULlk+3ZGt6T9JXLBQl9hpNtyTC6SFh84R+5RoN
+AevNl1bDfO+Vci0uJw==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/libnm-core/tests/certs/pkcs8-noenc-key.pem b/libnm-core/tests/certs/pkcs8-noenc-key.pem
new file mode 100644
index 000000000..f73fb55ab
--- /dev/null
+++ b/libnm-core/tests/certs/pkcs8-noenc-key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQC80HGgFdlFIL2F
+W5rHQ99xOkMrWcZ7an9YurDebAE3M0UwqxM24+5mWbxc8FJ8yYugdMzuI5Nq77IA
+DwJpv9ZjMfnKC1VDMj3bmmMdPurfx8pLdLw/jhk3wBaYk6vMvh4z66Yvmb7valGq
+Pxh6CRTnekNGI9XA7me4JNBlisl0Qasn9g4pl9PiGJAruEamS4Pk6dSWbfw58bs7
+/Yo5ejyt/Mn1n0Q/r3Gv/lAS0qRvmrW6GE1rMtANMfuGRNlAln21TzNcJzykm+sp
+RWptxXEI0NY7u9+RP4M3C1mJxWir7AZDbtinpOZH6vF+92yMzgEYOLK/WZVdSPdW
+tROv9xtPAgMBAAECggEBAJAfp+vjYZJjuGaYEuAxjdhW+biYcWn5U7V9484TsSXa
+i+DnZOZMO8iCjMaAZuZ7zYmwPlE0dK12w29KBbSEy3eySRIRboa5TgBXq3pCcXRZ
+g6/vLlZw+AzXIiha6BODt3g4UwUYnWcQx79lJCDa18sNR1a9ucbn8+Har/wiYT3M
+JjTbUT6wR6rKEXchB58ZugYGhOTfugSDQg4U/dwEHPIaJ/wme++JUV5B/tjeGCG3
+F43o2Oos5vjfrDSpUKIYZn+2BdhP434jkwj22wQ2sy0ruU/kQx8nogMTRfP1v4GU
+9QmNXj/DB24K388ZxcDmcxBJxrGAJ0MohYFo28DqRBECgYEA6hyKEqe2UbJx/+B6
+8mYgHb+pS2j0M4jPl11q9MMLVxLnDY9xZ85IEyWHQEC0GavPSAois0oiDeGAm32c
+j6TFyV3/oPTmZSyV93/agWgnH9Xtc481pbNAb0GMfyotvRRE/+6ti9+Cl7oH9Qmm
+ldMk7Hn6sK9t2mUOW8idPjKqlqcCgYEAzne25BryLJoIinbRMZg9KTfxfgUE6EKc
+Tk5+9CFQn0/AItQJuKbIUyggYH4psWW5hWq6hFlmMYMR48FKv9ry7pZTB0djaoYD
+lN+wSuhzUYWXedkAjvPmekITmf6rbnPfwOZvsr8CGMEUekqJPnPLzsQy+Ea2y/fb
+QY4SHe7gExkCgYEAr+1scOJpZvFjK7ckjT3jipd6ADpJsORxo7zG4FImFnQU/6K4
+xRpGHWVJQyaccOIkrW04cGUYPDgmrjJx0ZwwKceijvEaphMgS1JgAHklVY4sl3ea
+CAAxPqoSi4lFv94Yj/9rmT4IZD6fNivfbJ20FKUBl37tXX4tkRmr2I64lOcCgYEA
+x3eqzrclrmdlxvfBZOuScwbkHP6WXhk0TwbQ6eRhsnfmxP8bITSoJoaGuRJKD2Oa
+l0WkSobgDwd0uhecsrvBpTS/pDGY32n3fdWZyNTHzEOHMyWtv23tBcJek5ERaBU0
+X3WBBiw4x1eKBBeMfjR6+xhbsbcHlQiw36V05UxJWMkCgYEAhtcYvrfU4K48IJTU
+qp03nvd+dMY3IUTdZNOCh8bswLKyn3aq3MfWF9Vp7kDAI3cfyMpSrAQnmg4nVcn6
+Gf3wakG8bpiSRbJnGN+iLm8JsD+3Vw9KzvKOOQVmpT7xt5Kupx1hWvLHQWvfYgOG
+qEtTM8/+LD7W3I7midJNt50CD8A=
+-----END PRIVATE KEY-----
diff --git a/libnm-core/tests/certs/test-aes-key.pem b/libnm-core/tests/certs/test-aes-key.pem
new file mode 100644
index 000000000..aab8f463c
--- /dev/null
+++ b/libnm-core/tests/certs/test-aes-key.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,800391B7DD72364B4C2562E0B6AEA000
+
+E9dgNCIATOr4CN5c8o6B+8wdqq/I1BLmPmW2qT7YZepoF7E+RUb8ZLjo1VO2XsJw
+Ir4EzuH7837zBD9dP5CjlY8cWfR63gZpEWRY5Jub8kzvqiL4UZ0Qr8IHOZxAkKEz
+EL1Pn7e+tYt4kA372LPZHWO3vRCgmL1iSJj2/k3avPWAx7NUie4bzGI+00WNv699
+ClKzsJbWB1eiQvYgOr4aVV26oWfa896JkBoGhgZQ6ckqFpsdAos8m46iOSVZrwgq
+Y2/d1CvfQod+87c8LRatwAjf+d6YAJJaeMyxjCGuAY6/JyDsorUkM2OlvbTt6WOA
+gSPWO8I+Ov6THb4IuPhpIJ30Sl88tc6MlIByW49EWu2G1jPw3L8iqRzZ50Z85dyz
+N9yFP91wEwi5F0Zed4iEpg3NVfklEe/VYqCldc5f9fZ84G5V98ZlAdNSqwd/UNBU
+iPTflGqVpp1u+J2isOk+Agpj1MCxh2q0RNuvY9KHzOYBScirfbG4DKNbQgS/5Zw7
+3g9YL5Wbo7BczHLiXf/2adu6T8wI1LKRjkeLV9dK1Vw3ZaGy3mB9oFhCgjh9BNHw
+wC78CVcUErjtOXdQagiCQn5k5EGeAB97QFROoAFjAmGvq3xCi4EHd9Sk6fcMm7Oi
+1fuVR5EXUubF4Llq06lFzQp01s2F73noH49bs3qwdf0n8nrL2XhKB0XCOV/I3K5c
+Y3W+YSl361QGjZ/NUcFLIIy+Uro90MmUBNk6af+wGHRJeflpVnK0ATX1PtpNHziz
+jiMiIZicjgfVLxl1a5zTl6KUmGWKlZb533adQ0s6q9Qmi5Vk5L5W/GdMjcFtZbM6
+GU7EOkwihMLb3DVsNbm7vb8tUXqe/e5RmXtij8Yb+2a6/M9yaOHa0VjHzdiKHecr
+eEYaKQDj7NCWLslNnRRh9GmgXcu2pqBhqRM3HAt3cEaHKKWHTcoWcz11pFwMHNtn
+bU9GjGRVc3lCGhVNRiloO0zrKHmcBpDVLw2+ycXXpj/RaBW2fy0xRLKolyla+jEr
+zdLzVI61O50ZMycOtPmE7DVZpkokn32hGer1eCOFnsN1lywi4cWLvU0jbQC+CJyw
+T9vS8zB3WgOl8rC1AHsfQ4KYajlKleQm89deurQymnt/Qx49SiQA+TpwG9Xvx2TP
+3Vc1NwZfM9ZZ1+6xit/rTuS3LhnmhEnGnV5ZyvAdmkCcV2iHjOnLnQWWQn24MHU3
+8Y9D4AdpI5V7Igwr3vH2NZMiw1W2Yc5EJuPAT8nIs5sgOYhXB/QLPJvulvOQhuNC
+NPwJ6A505JrVNfHuEaoGUyA+mPeWuLwQo8y8cM6ZdFMG3RrwFNzuYTrc1Z/9GsmA
+C0UfHf5dL0r7oWZ1SbpSvsmHYqc8sIypq0ohuLEbpegS/hWP8b2/XDRTjfTiJOrM
+4LsUH9PMOJSxDlwS+7e3FdcGfgXfsMgB3aOjQvNpKEolOuv4A5LVFeMrrwtw4Xo1
+EuhstZwyarUTJenDUXzkakhA+8Yw/g2a7RsnANVTkeBuv2PbqFL4zdlsWvcpkz41
+ESxx1siSeU1E9beOII0zSi8vUD0IAevRHaWSlfU2po600IzX1FN97pa4DJV2ycgn
+-----END RSA PRIVATE KEY-----
diff --git a/libnm-core/tests/certs/test-cert.p12 b/libnm-core/tests/certs/test-cert.p12
new file mode 100644
index 000000000..ae4a68304
--- /dev/null
+++ b/libnm-core/tests/certs/test-cert.p12
Binary files differ
diff --git a/libnm-core/tests/certs/test-key-only-decrypted.der b/libnm-core/tests/certs/test-key-only-decrypted.der
new file mode 100644
index 000000000..c8652537a
--- /dev/null
+++ b/libnm-core/tests/certs/test-key-only-decrypted.der
Binary files differ
diff --git a/libnm-core/tests/certs/test-key-only-decrypted.pem b/libnm-core/tests/certs/test-key-only-decrypted.pem
new file mode 100644
index 000000000..1a25da5e7
--- /dev/null
+++ b/libnm-core/tests/certs/test-key-only-decrypted.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAztLp+/SkzmaHzIst0sO4+r7qUwiVnidKBHgxoTbS5UL1dvck
+cbjTEP23V4ZoKQIb6ZMrr8B+PVgWNBAlhX4oLUL8NH/WTwrntrlAUcjliWDNc1Fj
+Z+FZNjFe0IdLXZeKQiLTQvKDYnmERVvYIJfi0TQjXuy/ikF8rYBQ85scUV3kKRzB
+xnyhAHAP9nl3AyL1S6t2yiCr4U5TbIZo6dYPbpVLtbXP02zUc9vAPR0gIHKrPiW7
+P81fLXf91wuo6wxzwD90JxdWzzGaqe3BOSfHqul3SPRtVok1XHlb9i+Mn5O8ExzQ
+dF8wGxVDcY7/Gt9lZWnCilqrBEqA3iApjUgcgwIDAQABAoIBAQC77HCmepf04ryp
+Yhz00NoXG7mWUMqBtXlPrlaKAWKG5dxbiBwZKLK/UYlxgbLK8BuklBCx1Nnfq1Yh
+YDp3nTWsSp0WpsF3eJUqNhD3Pu8xcD+9dEo6bUu+LgXUu9oC5Fq/1RzYS7qNk5RX
+4Sf0FY4GQLWS3tL7MJ20mE71yg5k7qRbDydOyhTh1m1CpRYONWxSsWVLM8KGRDJp
+iF0cdPfD5yoPFpgDk8gwzrnXJH2Wqzv8GvyYykRK5AW7tE50y0rTAM42WZ7YS6aZ
+FNMmtYxeyzXLY3LgPP0uko5anz3OXRcqCfHfFANG0y7B9MehbrjMgI6S1BbzFl07
+V1zVQVqhAoGBAPIfrWMlh1fHlRh4iRGXK2Hvxyv2oNz9KvQ4qRaLV9ejRDzdt7Pi
+/utbi5LGBuDw9016nXM3I77b6PukHzsHFnWGRnyRSbkMMt6mE17nggmNqcpFWfE8
+E7HcKMhk4gbuo5AHD3Ee1Gac2AUDnzYiE+sS6WI3O9d77cc5ych5jZ+nAoGBANqt
+VZCttjY0E+hEyTP37eaE8u0jfdK8AflTJlNUHWKXglES525iu8I/Bso8KaQYsYF3
+SezGRd3KQepQhtMjFKfSpF+tbnboP57Y3XGo8xhbxqV4kRX+XGsVoW3Vg2nPKBrR
++dIY5nMwua+gkHWp9RDcemD2reiIZBVx95fK8dfFAoGAdCSH2pBs/MlrFqLzNTHr
+iH4pb0hN39O9YAsx6POMfo79s6izbyHLIID4Ub6WHB7ashrIHjVr+yin+NXAeWMr
+/dIcS7Kxx4c3e5/0mMi6kvSWZsWfoF0uIVo3YfEqjyK36OXKHXwpbNN9t+IF5ESy
+g0e+FfPiy7nR1Ig+5+CO8+8CgYEAp/75+Ug677FaidouaMpT7gC9UAkwJLFjItQK
+YYIBgTi8WOSY/2jCrhwVb1CA/RwrYjbuiARasGUt9oEe0x3kRHnC5e4rKxaJqdMZ
+bLRK7a+0EHNrouXiwjG/7s1VQ/ht6wzdS9btVBlezdogoQSMzQNU0SExwa7mlMMV
+X3v+B7ECgYAK+Yt4jnLH1LNWoDTU0Ug5hyXsQXV8lVBSnrkvS7GtP6ZA/4OqG7lJ
+/bTYFZGoiAGzOnC+YlAqSIu45CEnpr2xBsThQiWUVxspmQD1lEWWFcd77DPUwn3C
+59pLgx0AqJE3n6lBOwehiXbFKBdVzX8PfPZpuCK6qc/RiTILktwURA==
+-----END RSA PRIVATE KEY-----
diff --git a/libnm-core/tests/certs/test-key-only.pem b/libnm-core/tests/certs/test-key-only.pem
new file mode 100644
index 000000000..5ef530e9a
--- /dev/null
+++ b/libnm-core/tests/certs/test-key-only.pem
@@ -0,0 +1,92 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,B29FCA6ECB7C0C48
+
+KuRV4sEVQkY0r0E+E81Se2qpm54HeboUMIJcMVqAt/HIeYwpjEzmXHUywXgayA5k
+r5Uvru95vymFz80q/rl6i4Mt3ckEQ3/VHmBI4pPj/JeRbiDhqTyLqpB5zMgbuti+
+PsEemlbiaCMZFdJk8rJBWADTkirGbXs5ciLwTJyrJXhkBVTqoHtphSWMELxcrnQj
+5bAXZ+rnApWA7LR3yCY1UE0Nj39Yu8lkzDJtbsSXPJVO//OQiGuQRcY6roAUzeS/
+amLdIYqoZm3OF83Ro88XZCIDCG6XjgKoqojtekClVIytB6mHWk+IHhI7DgU/pDBj
+yOskzVRMja9ECnqaVX+bmlmJGZBgcd7+XiebCXNY9IAx/ZQDMbDJDoJusvH6npJR
+PBgag8QBSzwpFyEP/1LrlyVyggZcGuXDWfUiM2rt2UvLm8QYeT5WGfUI+QwW6JRV
+xEz2QwRiPsmj0uK2fXLKHbY0Pv79IMLqgesCAUbndWsi94kjAhpJGa/WfKVb8Dpg
+T+mVa2OT0pgewPWJ3h5f47ag27WDJthsIUHAvNZ03uM23DIqDh6o03/B3/4r1Uab
+HzsLWhUOzbLihO08qcPk/JqtDVCv579mpgvy7bL2ZsZUzefnmg+ah+1bhLguryZu
+Zrt1hTu5WTz27UbYwWNtkxWnWcM9sSF9y+KVwumYhIUGTvg3Jds/jmp/Z5ad8tev
+0RQuWmqnXVD51Y92tOXobJH7JwGbQ4GeRNG/UX7DS9Lvb6rPgmmxvGbXMcjEMapB
+m5DLjCD7Lz4++sfzhCic3/nL8e8fjoYZmCbL/SpYjGjTrfoNaGYaT0De8MxCSjPf
+rNT+ldWFD0oAOTmT0uqOFkeIx3vxczSQUyRfzGOLqtb9mAXk8lvdb8Myb5atfe8f
+FNBL5ocz6Szv2AmKmjZE5P6NKSllyryCYl+H2QU0e3OyY8S9aG2aG8fqeVKaA01S
+uOOjsK6IKMpkit+VFDP7RWvS8p1FTwTVRdbMZzASW8+D98OHsTlOENtQuuFyvNaN
+vPHrbHltTkwDlYVab9UpFr/ZRW3cNJrmcl0hyeCJxk5u8B9UwW6yZmd24hxda2xt
+1QjnxfWlX0i5KTmfWFyPmRYt1WH9rdVaH6wqRbGNbMRT7Lez0E/2+LXjFiiEe0Vh
+ZuryhyhUXpHY8yyHxFY92XT504Z3wPUaJ1tQxGhdziZ7HcqFT8f4oTNJdBNtzqNw
+l63gSTaKUkSB14CBOyR84cqpgSMwZvWZb3RQFYY4GSALWwhnn6PWeRhjWAXPms2v
+tRmfEyDUCyPxDarezvS9kUir3XbvnCkoJOrK/lw4a8ygGBCBqRKOdI0SRUf1Nnjm
+aZBrKrXHv5vP66fyC7cGMTq35+iiHbE//rRDGPrf9vpmw3ki3FlDMyAXOC5yWDco
+0n+cNDyHJDdIW3+3nfZvSgPPMwmTdfNO90X3YczSmMTGjnIuhQMf7FMFmMZOSrqD
+u234vYCjIIlph3aVpbzjOqKg3d4nuP9oouyAgRAr+vShgHRmq0jvsAiGH3Q6RqEj
+DvkM1NgoloMy5RhKF4hIeaQM/UlgoXrcEx0RGCJHykQcQmVa5cf5EwjrO7b+w2Lg
+-----END RSA PRIVATE KEY-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: md5WithRSAEncryption
+ Issuer: C=US, ST=Berkshire, L=Newbury, O=My Company Ltd, OU=test, CN=test/emailAddress=test@test.com
+ Validity
+ Not Before: Feb 2 02:22:25 2009 GMT
+ Not After : Jan 31 02:22:25 2019 GMT
+ Subject: C=US, ST=Berkshire, O=My Company Ltd, OU=test-client, CN=test-client/emailAddress=test-client@test.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (2048 bit)
+ Modulus (2048 bit):
+ 00:ce:d2:e9:fb:f4:a4:ce:66:87:cc:8b:2d:d2:c3:
+ b8:fa:be:ea:53:08:95:9e:27:4a:04:78:31:a1:36:
+ d2:e5:42:f5:76:f7:24:71:b8:d3:10:fd:b7:57:86:
+ 68:29:02:1b:e9:93:2b:af:c0:7e:3d:58:16:34:10:
+ 25:85:7e:28:2d:42:fc:34:7f:d6:4f:0a:e7:b6:b9:
+ 40:51:c8:e5:89:60:cd:73:51:63:67:e1:59:36:31:
+ 5e:d0:87:4b:5d:97:8a:42:22:d3:42:f2:83:62:79:
+ 84:45:5b:d8:20:97:e2:d1:34:23:5e:ec:bf:8a:41:
+ 7c:ad:80:50:f3:9b:1c:51:5d:e4:29:1c:c1:c6:7c:
+ a1:00:70:0f:f6:79:77:03:22:f5:4b:ab:76:ca:20:
+ ab:e1:4e:53:6c:86:68:e9:d6:0f:6e:95:4b:b5:b5:
+ cf:d3:6c:d4:73:db:c0:3d:1d:20:20:72:ab:3e:25:
+ bb:3f:cd:5f:2d:77:fd:d7:0b:a8:eb:0c:73:c0:3f:
+ 74:27:17:56:cf:31:9a:a9:ed:c1:39:27:c7:aa:e9:
+ 77:48:f4:6d:56:89:35:5c:79:5b:f6:2f:8c:9f:93:
+ bc:13:1c:d0:74:5f:30:1b:15:43:71:8e:ff:1a:df:
+ 65:65:69:c2:8a:5a:ab:04:4a:80:de:20:29:8d:48:
+ 1c:83
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 34:E9:5C:D8:FC:C7:AF:F7:5D:F4:13:D3:82:1A:CD:52:0F:4A:BB:0B
+ X509v3 Authority Key Identifier:
+ keyid:52:33:2E:22:66:79:82:E5:41:2E:8D:3B:B2:E5:CC:FA:BE:99:33:8E
+ DirName:/C=US/ST=Berkshire/L=Newbury/O=My Company Ltd/OU=test/CN=test/emailAddress=test@test.com
+ serial:E6:4C:5C:96:26:5E:D6:D0
+
+ Signature Algorithm: md5WithRSAEncryption
+ 88:c4:dd:c5:4a:a6:8e:1f:36:62:80:31:6b:2b:85:34:0d:6c:
+ a7:dc:e1:5a:3c:dd:74:57:db:59:be:8b:f2:79:40:2d:bd:9b:
+ e1:ab:0e:03:75:20:75:2f:ea:97:f9:d4:7e:15:75:c2:82:f5:
+ b1:37:e4:8b:24:d4:ef:02:3b:19:6a:56:bb:9f:c3:a5:b4:c4:
+ 39:a0:64:96:5b:c3:a8:19:74:ec:0b:cf:33:df:f3:12:f3:e2:
+ ab:1d:7d:de:21:64:cd:b1:a0:6f:7a:77:84:d4:62:8a:50:e6:
+ 76:5d:af:3a:ef:1a:87:0e:1a:38:c4:f9:0d:2f:14:e0:20:32:
+ 4c:2e:70:d2:71:82:d5:e5:c9:13:2c:4e:b4:c8:63:65:1d:48:
+ e8:c3:56:6d:88:84:57:65:13:1e:42:48:b4:03:25:71:4e:12:
+ 9d:1a:88:65:d5:71:21:3b:0e:be:37:1c:f0:88:6b:45:0c:0e:
+ 6c:e5:60:cb:86:bf:bf:40:30:c4:cf:94:f8:1c:60:d4:1b:df:
+ 88:02:7a:45:7e:d1:c6:f3:07:b9:b1:8f:2a:55:2f:be:77:9f:
+ d1:46:64:05:b7:67:c5:b2:ac:8c:42:8f:6a:51:a4:0d:2b:16:
+ a4:d6:39:a5:f8:25:ed:68:25:13:b5:19:ac:6c:e9:ec:ee:03:
+ 6b:80:38:6e
+
diff --git a/libnm-core/tests/certs/test2-cert.p12 b/libnm-core/tests/certs/test2-cert.p12
new file mode 100644
index 000000000..9d5732b0a
--- /dev/null
+++ b/libnm-core/tests/certs/test2-cert.p12
Binary files differ
diff --git a/libnm-core/tests/certs/test2_ca_cert.pem b/libnm-core/tests/certs/test2_ca_cert.pem
new file mode 100644
index 000000000..9a487ca4b
--- /dev/null
+++ b/libnm-core/tests/certs/test2_ca_cert.pem
@@ -0,0 +1,27 @@
+-----BEGIN CERTIFICATE-----
+MIIEpDCCA4ygAwIBAgIJANDnVhixAO1GMA0GCSqGSIb3DQEBBQUAMIGSMQswCQYD
+VQQGEwJVUzEWMBQGA1UECBMNTWFzc2FjaHVzZXR0czERMA8GA1UEBxMIV2VzdGZv
+cmQxFjAUBgNVBAoTDVJlZCBIYXQsIEluYy4xFDASBgNVBAsTC0VuZ2luZWVyaW5n
+MRAwDgYDVQQDEwdlYXB0ZXN0MRgwFgYJKoZIhvcNAQkBFglpdEBpdC5jb20wHhcN
+MDcxMTA5MTU0ODI1WhcNMTcxMTA2MTU0ODI1WjCBkjELMAkGA1UEBhMCVVMxFjAU
+BgNVBAgTDU1hc3NhY2h1c2V0dHMxETAPBgNVBAcTCFdlc3Rmb3JkMRYwFAYDVQQK
+Ew1SZWQgSGF0LCBJbmMuMRQwEgYDVQQLEwtFbmdpbmVlcmluZzEQMA4GA1UEAxMH
+ZWFwdGVzdDEYMBYGCSqGSIb3DQEJARYJaXRAaXQuY29tMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAz9zRLSiQyQangDgEliEP8xSpnPJS7GjXzrkZS3sk
+gZLuVuwoFeZRq3Hsrq/wGd/vM0KUFNmEaMc+47jnuv0UHQcQ45ZACO7s4/Aflhzj
+lkmud/z06hVknIzjXmvS6q2ttCviHsXnfokl+wAxuUhsd+le0xjP9H1jXny4YBuS
+jP+yGUz7PL4w1sFFghKIPrlB7m4GkFbQRqvH7FSJg86GWopPwJvNvIzhOZiO1a1D
+CAAL4Ru3jxtNFxqWT87C/qUEe/2Qb7jtNyqFcKfwZyZh4u1bo0c8bjErlUZERbWz
+zM3hTFypuw+i2v+0h3A8/Xb0hTjcHkUoJgfSdbsOLC5TOwIDAQABo4H6MIH3MB0G
+A1UdDgQWBBR+UOaH4e8nrEuMcEXJl7UN5r/wDTCBxwYDVR0jBIG/MIG8gBR+UOaH
+4e8nrEuMcEXJl7UN5r/wDaGBmKSBlTCBkjELMAkGA1UEBhMCVVMxFjAUBgNVBAgT
+DU1hc3NhY2h1c2V0dHMxETAPBgNVBAcTCFdlc3Rmb3JkMRYwFAYDVQQKEw1SZWQg
+SGF0LCBJbmMuMRQwEgYDVQQLEwtFbmdpbmVlcmluZzEQMA4GA1UEAxMHZWFwdGVz
+dDEYMBYGCSqGSIb3DQEJARYJaXRAaXQuY29tggkA0OdWGLEA7UYwDAYDVR0TBAUw
+AwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAmE2jqUymfxN2Vv7bPafoK/EpZwGPxu+z
+phRFsgUgWVzidc/GtOxN81LduJ+ow8MEbQIabo4JV/MdKzuPuhAHToAQdeb0LIWa
+p59vTIZiVhUt0cMAbQwKcTnfmDnXw9wytvtKgeAXJq0Jd6F+uNXTiR1btlYLZqmF
+oSu54cHQlXpUT9z0BnQ8eXd7m0TwfzGQkTHQI7xBa87lZDAkJaTlhv7fR5vPmJYY
+0LiXii71ce+4hxdlp7hQfwQ2sb8FPY3RlVboTRD0CvGaWypWhdSZnS790dBXgZOs
+NCge6NGuHzW5LtiZE9ppuv8qJysVcIFdAqt8dkx58ksOqFcARCerXw==
+-----END CERTIFICATE-----
diff --git a/libnm-core/tests/certs/test2_key_and_cert.pem b/libnm-core/tests/certs/test2_key_and_cert.pem
new file mode 100644
index 000000000..a668596ee
--- /dev/null
+++ b/libnm-core/tests/certs/test2_key_and_cert.pem
@@ -0,0 +1,119 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,5FA2D6D6242C26D0
+
+dyNdbh115sczbUEhiaGYJ6fazyvJss5thPFEmkP6aftYlvXY6vPtc++xFCCktiSd
+qFVEyi6oDyV4iGPmX7pCJ0e+pSI6uFNXKFtxh5/+/wXZcOEMCvfu7w2IrvYF2LHY
+qJDljcISSRxeINuYO7TETD5fLLRKj2X9vwwkwVN02b2N5jsrm6Bt//WbatqSB3ln
+FHyQhVKkvdl9Hr1XNmEfgGfZSxxDoPu1DjhtZ5ja2LZj64C2CXdI0oq2wcAVvQNn
+rZeeg9sinQJkz9rwsNaWqlYw4X+YD2JRSwZuvwkWRydYMwgb1XS/jCxtuFF8NXWP
+RBAOAZZUy7onzohsJHVVa05wCKQ4klo+PEfI3vn7BeuHyciCc0eFqGRvz8eFDybH
+ZdPbU/3vGp+mOB7gd27TptttTCQQy9uM5CIyovNSYsAIw1Z583Ea4q8eXgzkgD6D
+isCqkGXMfPbNXU3myQGDnQwWRi2CqX+rXM8PJUhdewLAlmHRz/aYSuql2BRixJKx
+eASzmFBYdAjrvafda5D+xTyJwXEwdq/HlqMK9cY28ZbNrzA2Kor2X23EKC1+VG8k
+B67OsfUhW27j4u6aV5JdLf87OtF3mHFRR+Lzs7i7LYvJ8ACE+jiIi7PboZjK5Oiv
+JqTK0BwDaeNYjkd6jiJh8It/ReMbLk65J3eldOklN0VMPYiqcQnHvSPC2DD1YAy+
+Rv/JVj6TvzvgEAj+hgH6MAAF6u3ARj6+10DlvhUubkOC5RztLKReu8B+427TuuDb
+T03gFpHD6X9IqSiq/QfYFyHFojCVSrv6wDZOcHc1s71kpJ8R14YIVe+DrrZN/0D4
+M631jdNg3JARMZXcXTHrghGIdPmOtrsRyTTRZuGoVup/DW9MRzOzCTMSNCX8T+eq
+13HMSNQEO9lMwy0sYeO5c7sjHY4K1ubZuVE1mvXq4JLz3YxXJIvgp8TUvqDnAsK+
+Fv63bDoTg5Tq63XvnaKc7Lawneyg5ZAMzPN3nM0/1EZcn/2ICI5c4Yepc5t63EI5
+KytuXx86Mcx234enj3uMeuM22POQ1SnKOef6dFzK/CE8J8eUEY/aDhX4eBl/s3nd
+U4+aaFKYz3HTazePayt2SC6rP/KKMmS14q59bOQA1DiWxCvmA2ypRyP87fV5DstH
+I53RD5xp1P38iaO8U/divD0W2dkv748s9DQqYrHPtWALT9esxNU07CgB8Zt070si
+7pzjQ8FDCZ8ygDmwWGNSBz1nA90Cpd6gAFDrep7HAtDE4qgNfokycpaJZkXBei/U
+tC4tWYRbqDEsEbeBHvQRJzzqWzk9e/P4fQoelM3aryKzKLG5z7KvywVifKMLECQ+
+tIpzoRp06nuTA/O+iLFdkCy3JEWszfvvOwTwtIIV6+3s8TU0k9MmzEe3rGL+QqT/
+Tf+9/dN5LK+LWyc99BfmCOrBuFtQmHyEXkfe6EuFYEwj0B2ZfnLCon6cdRujjK7H
+IJslC1B/cBVqG3KCrbBzjeygKfJ5Ijo72oXZJOCFTLeJefZKGGWJCp9nG9h9Wrcf
+fEN/mj3wBvTa90/PYFj9NuaBtrvMF8Rn9XDeYPq2JGL8YkNdPuO8A+2Yko8wcvST
+-----END RSA PRIVATE KEY-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 2 (0x2)
+ Signature Algorithm: md5WithRSAEncryption
+ Issuer: C=US, ST=Massachusetts, L=Westford, O=Red Hat, Inc., OU=Engineering, CN=eaptest/emailAddress=it@it.com
+ Validity
+ Not Before: Nov 9 15:50:14 2007 GMT
+ Not After : Nov 6 15:50:14 2017 GMT
+ Subject: C=US, ST=Massachusetts, O=Red Hat, Inc., OU=Engineering, CN=client/emailAddress=it@it.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (2048 bit)
+ Modulus (2048 bit):
+ 00:b0:8f:4f:1c:93:d4:43:e7:87:b7:22:33:55:a8:
+ 35:a1:c4:01:b0:f1:ed:26:23:96:ab:65:c2:c2:54:
+ db:79:22:03:ad:3f:6f:22:e3:63:3f:f4:21:6d:fa:
+ 88:c8:8f:1a:ce:55:49:7c:98:33:6a:67:8a:8d:d9:
+ 34:b0:c3:42:f4:72:a4:45:43:05:72:5d:0c:d3:42:
+ f8:9c:66:3b:b8:f8:77:ea:f6:b6:94:d7:cc:5d:62:
+ 34:2a:14:48:0a:bc:65:94:f5:7a:63:98:6c:88:4c:
+ 25:d8:95:f1:40:3d:00:d2:fb:43:28:fa:02:fb:2c:
+ 80:b3:e1:33:e7:8c:ce:8a:a0:1b:3d:04:4d:bc:a1:
+ b6:a2:42:8b:8e:f3:5b:4a:72:34:7d:8d:ba:d8:46:
+ 22:35:da:5c:f8:dd:fc:6d:9e:59:22:b7:6b:e7:78:
+ 56:54:9f:4c:d1:e2:4a:23:a3:bc:04:ea:46:6b:70:
+ 8a:fb:fe:8a:73:ca:36:d5:f3:e9:17:e3:22:d5:b3:
+ 70:05:e7:f7:37:b7:21:b5:90:53:27:27:ea:36:9b:
+ 00:ff:35:b0:66:3d:dc:a9:2f:95:d2:21:18:98:4f:
+ 28:07:09:70:20:a8:b1:82:aa:a5:df:ae:0f:e3:36:
+ be:68:8c:9e:80:d3:33:d0:f5:84:17:d9:0f:eb:9d:
+ af:0b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 71:AB:BB:91:B7:04:DE:43:35:36:07:8A:35:CA:BE:5C:3E:EB:B1:09
+ X509v3 Authority Key Identifier:
+ keyid:7E:50:E6:87:E1:EF:27:AC:4B:8C:70:45:C9:97:B5:0D:E6:BF:F0:0D
+ DirName:/C=US/ST=Massachusetts/L=Westford/O=Red Hat, Inc./OU=Engineering/CN=eaptest/emailAddress=it@it.com
+ serial:D0:E7:56:18:B1:00:ED:46
+
+ Signature Algorithm: md5WithRSAEncryption
+ ce:43:6d:f7:f8:4a:66:fd:8a:2c:41:a6:e0:03:0e:60:30:d4:
+ 41:01:ba:46:ba:81:97:64:68:83:25:9c:e1:2c:03:8b:2d:ca:
+ 85:cf:bc:fa:ca:22:c4:59:28:23:8f:ff:50:94:60:1c:90:dd:
+ 75:f4:d4:ea:8c:fa:61:61:08:35:4a:8f:aa:a7:e9:3d:76:e9:
+ 08:28:55:01:c4:03:42:c7:ad:58:bb:ee:94:f7:09:b3:9a:9b:
+ 8b:d0:25:95:18:a6:22:d5:2c:fc:b7:bb:91:0c:7c:03:7f:9b:
+ 85:de:b0:e4:95:a8:73:94:27:0a:11:4e:e3:67:ae:2b:cc:e7:
+ 51:29:10:23:57:5c:3e:e7:ea:47:e0:f0:8f:5b:a2:9f:26:cf:
+ 7f:b5:7c:44:b1:7b:83:67:3c:41:ae:c6:66:64:e0:d2:ef:57:
+ a4:5c:1b:94:11:ce:28:e5:91:51:ef:e1:98:b7:3b:9a:cc:f7:
+ b9:85:76:eb:a8:2b:15:4a:cc:1a:a3:42:fa:be:1c:ce:b8:eb:
+ ee:12:d7:2f:e4:a8:cf:eb:2a:8f:78:e8:91:88:fa:c2:98:75:
+ 6a:4c:92:3f:2e:0d:e1:20:39:36:c6:2c:be:67:30:c3:f3:c3:
+ 65:81:ac:e3:3c:19:6a:21:ee:ea:f5:22:66:74:b2:07:53:7c:
+ 9a:0c:24:a6
+-----BEGIN CERTIFICATE-----
+MIIEtDCCA5ygAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBkjELMAkGA1UEBhMCVVMx
+FjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxETAPBgNVBAcTCFdlc3Rmb3JkMRYwFAYD
+VQQKEw1SZWQgSGF0LCBJbmMuMRQwEgYDVQQLEwtFbmdpbmVlcmluZzEQMA4GA1UE
+AxMHZWFwdGVzdDEYMBYGCSqGSIb3DQEJARYJaXRAaXQuY29tMB4XDTA3MTEwOTE1
+NTAxNFoXDTE3MTEwNjE1NTAxNFowfjELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDU1h
+c3NhY2h1c2V0dHMxFjAUBgNVBAoTDVJlZCBIYXQsIEluYy4xFDASBgNVBAsTC0Vu
+Z2luZWVyaW5nMQ8wDQYDVQQDEwZjbGllbnQxGDAWBgkqhkiG9w0BCQEWCWl0QGl0
+LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALCPTxyT1EPnh7ci
+M1WoNaHEAbDx7SYjlqtlwsJU23kiA60/byLjYz/0IW36iMiPGs5VSXyYM2pnio3Z
+NLDDQvRypEVDBXJdDNNC+JxmO7j4d+r2tpTXzF1iNCoUSAq8ZZT1emOYbIhMJdiV
+8UA9ANL7Qyj6AvssgLPhM+eMzoqgGz0ETbyhtqJCi47zW0pyNH2NuthGIjXaXPjd
+/G2eWSK3a+d4VlSfTNHiSiOjvATqRmtwivv+inPKNtXz6RfjItWzcAXn9ze3IbWQ
+Uycn6jabAP81sGY93KkvldIhGJhPKAcJcCCosYKqpd+uD+M2vmiMnoDTM9D1hBfZ
+D+udrwsCAwEAAaOCASYwggEiMAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9w
+ZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBRxq7uRtwTeQzU2
+B4o1yr5cPuuxCTCBxwYDVR0jBIG/MIG8gBR+UOaH4e8nrEuMcEXJl7UN5r/wDaGB
+mKSBlTCBkjELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxETAP
+BgNVBAcTCFdlc3Rmb3JkMRYwFAYDVQQKEw1SZWQgSGF0LCBJbmMuMRQwEgYDVQQL
+EwtFbmdpbmVlcmluZzEQMA4GA1UEAxMHZWFwdGVzdDEYMBYGCSqGSIb3DQEJARYJ
+aXRAaXQuY29tggkA0OdWGLEA7UYwDQYJKoZIhvcNAQEEBQADggEBAM5Dbff4Smb9
+iixBpuADDmAw1EEBuka6gZdkaIMlnOEsA4styoXPvPrKIsRZKCOP/1CUYByQ3XX0
+1OqM+mFhCDVKj6qn6T126QgoVQHEA0LHrVi77pT3CbOam4vQJZUYpiLVLPy3u5EM
+fAN/m4XesOSVqHOUJwoRTuNnrivM51EpECNXXD7n6kfg8I9bop8mz3+1fESxe4Nn
+PEGuxmZk4NLvV6RcG5QRzijlkVHv4Zi3O5rM97mFduuoKxVKzBqjQvq+HM646+4S
+1y/kqM/rKo946JGI+sKYdWpMkj8uDeEgOTbGLL5nMMPzw2WBrOM8GWoh7ur1ImZ0
+sgdTfJoMJKY=
+-----END CERTIFICATE-----
diff --git a/libnm-core/tests/certs/test_ca_cert.der b/libnm-core/tests/certs/test_ca_cert.der
new file mode 100644
index 000000000..e844f65b2
--- /dev/null
+++ b/libnm-core/tests/certs/test_ca_cert.der
Binary files differ
diff --git a/libnm-core/tests/certs/test_ca_cert.pem b/libnm-core/tests/certs/test_ca_cert.pem
new file mode 100644
index 000000000..faa3fc290
--- /dev/null
+++ b/libnm-core/tests/certs/test_ca_cert.pem
@@ -0,0 +1,27 @@
+-----BEGIN CERTIFICATE-----
+MIIEhjCCA26gAwIBAgIJAOZMXJYmXtbQMA0GCSqGSIb3DQEBBQUAMIGIMQswCQYD
+VQQGEwJVUzESMBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcw
+FQYDVQQKEw5NeSBDb21wYW55IEx0ZDENMAsGA1UECxMEdGVzdDENMAsGA1UEAxME
+dGVzdDEcMBoGCSqGSIb3DQEJARYNdGVzdEB0ZXN0LmNvbTAeFw0wOTAyMDIwMjIx
+NTJaFw0xOTAxMzEwMjIxNTJaMIGIMQswCQYDVQQGEwJVUzESMBAGA1UECBMJQmVy
+a3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5NeSBDb21wYW55IEx0
+ZDENMAsGA1UECxMEdGVzdDENMAsGA1UEAxMEdGVzdDEcMBoGCSqGSIb3DQEJARYN
+dGVzdEB0ZXN0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANZz
+iHfFR6Gqdz5Gq1elSaf7J2tznfialPyMkRoqngSItrM3JWlkfBu3ZIpGSYG8+Z8H
+JjaKh/zkCCH73HcjADCocm/XtgxlOlccDtBvfDqifb2dBikcmcfh0tX0o4JU9L+z
+WP7sVcUkJG7C5811lA5pAsLVooJxrZnrta6XstGvFgTSxI2Y4Jowf0syM5b/AHIQ
++htsVhSyj1DWM9day3QsEMZl55SCxCLTB6ZIJLF6NmTYwdnzWWTQf4k7kcptZJU8
+Fqv60b/ATvvUf7S+ZMGLopFIIlmc1Kkn7VTseIKy4ycYuDpyimQy3Yw4flC00vhl
+hTijH+5dlVOUFrRh0bsCAwEAAaOB8DCB7TAdBgNVHQ4EFgQUUjMuImZ5guVBLo07
+suXM+r6ZM44wgb0GA1UdIwSBtTCBsoAUUjMuImZ5guVBLo07suXM+r6ZM46hgY6k
+gYswgYgxCzAJBgNVBAYTAlVTMRIwEAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcT
+B05ld2J1cnkxFzAVBgNVBAoTDk15IENvbXBhbnkgTHRkMQ0wCwYDVQQLEwR0ZXN0
+MQ0wCwYDVQQDEwR0ZXN0MRwwGgYJKoZIhvcNAQkBFg10ZXN0QHRlc3QuY29tggkA
+5kxcliZe1tAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAZsWzGp9D
+10NWf8ts3A9mhcEb8oDgKNpCOZF9gqr2usZygJjY9MX2n0n81T8XaWDk1wZLlcDW
+hzIalCY8rpE57Dj3MEmdCmYr3BrAy6GVlc/MO7ffTHxogl9ouScSYo8ETTtNMKCg
+zwkDnXjGzmb1e59DIXMVHBBbTmJXJbM8XP9A2azJkVUyE2fSdWksXMP0XklGbW2p
+DksJ+8G1IWkyRhnINV5GZLLNAT5gBA6sUv/iqQKwk8r2dsweMPtLoLWZPAaZErYh
+sthGy00Q0GJkmkJpQl8QIlPq5vylNcMUhvc8tmzwk+rDVUj3jTJWqFwMtnHAaNyC
+FXl9ynWpe5J28w==
+-----END CERTIFICATE-----
diff --git a/libnm-core/tests/certs/test_key_and_cert.pem b/libnm-core/tests/certs/test_key_and_cert.pem
new file mode 100644
index 000000000..c00495d0b
--- /dev/null
+++ b/libnm-core/tests/certs/test_key_and_cert.pem
@@ -0,0 +1,119 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,B29FCA6ECB7C0C48
+
+KuRV4sEVQkY0r0E+E81Se2qpm54HeboUMIJcMVqAt/HIeYwpjEzmXHUywXgayA5k
+r5Uvru95vymFz80q/rl6i4Mt3ckEQ3/VHmBI4pPj/JeRbiDhqTyLqpB5zMgbuti+
+PsEemlbiaCMZFdJk8rJBWADTkirGbXs5ciLwTJyrJXhkBVTqoHtphSWMELxcrnQj
+5bAXZ+rnApWA7LR3yCY1UE0Nj39Yu8lkzDJtbsSXPJVO//OQiGuQRcY6roAUzeS/
+amLdIYqoZm3OF83Ro88XZCIDCG6XjgKoqojtekClVIytB6mHWk+IHhI7DgU/pDBj
+yOskzVRMja9ECnqaVX+bmlmJGZBgcd7+XiebCXNY9IAx/ZQDMbDJDoJusvH6npJR
+PBgag8QBSzwpFyEP/1LrlyVyggZcGuXDWfUiM2rt2UvLm8QYeT5WGfUI+QwW6JRV
+xEz2QwRiPsmj0uK2fXLKHbY0Pv79IMLqgesCAUbndWsi94kjAhpJGa/WfKVb8Dpg
+T+mVa2OT0pgewPWJ3h5f47ag27WDJthsIUHAvNZ03uM23DIqDh6o03/B3/4r1Uab
+HzsLWhUOzbLihO08qcPk/JqtDVCv579mpgvy7bL2ZsZUzefnmg+ah+1bhLguryZu
+Zrt1hTu5WTz27UbYwWNtkxWnWcM9sSF9y+KVwumYhIUGTvg3Jds/jmp/Z5ad8tev
+0RQuWmqnXVD51Y92tOXobJH7JwGbQ4GeRNG/UX7DS9Lvb6rPgmmxvGbXMcjEMapB
+m5DLjCD7Lz4++sfzhCic3/nL8e8fjoYZmCbL/SpYjGjTrfoNaGYaT0De8MxCSjPf
+rNT+ldWFD0oAOTmT0uqOFkeIx3vxczSQUyRfzGOLqtb9mAXk8lvdb8Myb5atfe8f
+FNBL5ocz6Szv2AmKmjZE5P6NKSllyryCYl+H2QU0e3OyY8S9aG2aG8fqeVKaA01S
+uOOjsK6IKMpkit+VFDP7RWvS8p1FTwTVRdbMZzASW8+D98OHsTlOENtQuuFyvNaN
+vPHrbHltTkwDlYVab9UpFr/ZRW3cNJrmcl0hyeCJxk5u8B9UwW6yZmd24hxda2xt
+1QjnxfWlX0i5KTmfWFyPmRYt1WH9rdVaH6wqRbGNbMRT7Lez0E/2+LXjFiiEe0Vh
+ZuryhyhUXpHY8yyHxFY92XT504Z3wPUaJ1tQxGhdziZ7HcqFT8f4oTNJdBNtzqNw
+l63gSTaKUkSB14CBOyR84cqpgSMwZvWZb3RQFYY4GSALWwhnn6PWeRhjWAXPms2v
+tRmfEyDUCyPxDarezvS9kUir3XbvnCkoJOrK/lw4a8ygGBCBqRKOdI0SRUf1Nnjm
+aZBrKrXHv5vP66fyC7cGMTq35+iiHbE//rRDGPrf9vpmw3ki3FlDMyAXOC5yWDco
+0n+cNDyHJDdIW3+3nfZvSgPPMwmTdfNO90X3YczSmMTGjnIuhQMf7FMFmMZOSrqD
+u234vYCjIIlph3aVpbzjOqKg3d4nuP9oouyAgRAr+vShgHRmq0jvsAiGH3Q6RqEj
+DvkM1NgoloMy5RhKF4hIeaQM/UlgoXrcEx0RGCJHykQcQmVa5cf5EwjrO7b+w2Lg
+-----END RSA PRIVATE KEY-----
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: md5WithRSAEncryption
+ Issuer: C=US, ST=Berkshire, L=Newbury, O=My Company Ltd, OU=test, CN=test/emailAddress=test@test.com
+ Validity
+ Not Before: Feb 2 02:22:25 2009 GMT
+ Not After : Jan 31 02:22:25 2019 GMT
+ Subject: C=US, ST=Berkshire, O=My Company Ltd, OU=test-client, CN=test-client/emailAddress=test-client@test.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (2048 bit)
+ Modulus (2048 bit):
+ 00:ce:d2:e9:fb:f4:a4:ce:66:87:cc:8b:2d:d2:c3:
+ b8:fa:be:ea:53:08:95:9e:27:4a:04:78:31:a1:36:
+ d2:e5:42:f5:76:f7:24:71:b8:d3:10:fd:b7:57:86:
+ 68:29:02:1b:e9:93:2b:af:c0:7e:3d:58:16:34:10:
+ 25:85:7e:28:2d:42:fc:34:7f:d6:4f:0a:e7:b6:b9:
+ 40:51:c8:e5:89:60:cd:73:51:63:67:e1:59:36:31:
+ 5e:d0:87:4b:5d:97:8a:42:22:d3:42:f2:83:62:79:
+ 84:45:5b:d8:20:97:e2:d1:34:23:5e:ec:bf:8a:41:
+ 7c:ad:80:50:f3:9b:1c:51:5d:e4:29:1c:c1:c6:7c:
+ a1:00:70:0f:f6:79:77:03:22:f5:4b:ab:76:ca:20:
+ ab:e1:4e:53:6c:86:68:e9:d6:0f:6e:95:4b:b5:b5:
+ cf:d3:6c:d4:73:db:c0:3d:1d:20:20:72:ab:3e:25:
+ bb:3f:cd:5f:2d:77:fd:d7:0b:a8:eb:0c:73:c0:3f:
+ 74:27:17:56:cf:31:9a:a9:ed:c1:39:27:c7:aa:e9:
+ 77:48:f4:6d:56:89:35:5c:79:5b:f6:2f:8c:9f:93:
+ bc:13:1c:d0:74:5f:30:1b:15:43:71:8e:ff:1a:df:
+ 65:65:69:c2:8a:5a:ab:04:4a:80:de:20:29:8d:48:
+ 1c:83
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 34:E9:5C:D8:FC:C7:AF:F7:5D:F4:13:D3:82:1A:CD:52:0F:4A:BB:0B
+ X509v3 Authority Key Identifier:
+ keyid:52:33:2E:22:66:79:82:E5:41:2E:8D:3B:B2:E5:CC:FA:BE:99:33:8E
+ DirName:/C=US/ST=Berkshire/L=Newbury/O=My Company Ltd/OU=test/CN=test/emailAddress=test@test.com
+ serial:E6:4C:5C:96:26:5E:D6:D0
+
+ Signature Algorithm: md5WithRSAEncryption
+ 88:c4:dd:c5:4a:a6:8e:1f:36:62:80:31:6b:2b:85:34:0d:6c:
+ a7:dc:e1:5a:3c:dd:74:57:db:59:be:8b:f2:79:40:2d:bd:9b:
+ e1:ab:0e:03:75:20:75:2f:ea:97:f9:d4:7e:15:75:c2:82:f5:
+ b1:37:e4:8b:24:d4:ef:02:3b:19:6a:56:bb:9f:c3:a5:b4:c4:
+ 39:a0:64:96:5b:c3:a8:19:74:ec:0b:cf:33:df:f3:12:f3:e2:
+ ab:1d:7d:de:21:64:cd:b1:a0:6f:7a:77:84:d4:62:8a:50:e6:
+ 76:5d:af:3a:ef:1a:87:0e:1a:38:c4:f9:0d:2f:14:e0:20:32:
+ 4c:2e:70:d2:71:82:d5:e5:c9:13:2c:4e:b4:c8:63:65:1d:48:
+ e8:c3:56:6d:88:84:57:65:13:1e:42:48:b4:03:25:71:4e:12:
+ 9d:1a:88:65:d5:71:21:3b:0e:be:37:1c:f0:88:6b:45:0c:0e:
+ 6c:e5:60:cb:86:bf:bf:40:30:c4:cf:94:f8:1c:60:d4:1b:df:
+ 88:02:7a:45:7e:d1:c6:f3:07:b9:b1:8f:2a:55:2f:be:77:9f:
+ d1:46:64:05:b7:67:c5:b2:ac:8c:42:8f:6a:51:a4:0d:2b:16:
+ a4:d6:39:a5:f8:25:ed:68:25:13:b5:19:ac:6c:e9:ec:ee:03:
+ 6b:80:38:6e
+-----BEGIN CERTIFICATE-----
+MIIErjCCA5agAwIBAgIBATANBgkqhkiG9w0BAQQFADCBiDELMAkGA1UEBhMCVVMx
+EjAQBgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMO
+TXkgQ29tcGFueSBMdGQxDTALBgNVBAsTBHRlc3QxDTALBgNVBAMTBHRlc3QxHDAa
+BgkqhkiG9w0BCQEWDXRlc3RAdGVzdC5jb20wHhcNMDkwMjAyMDIyMjI1WhcNMTkw
+MTMxMDIyMjI1WjCBizELMAkGA1UEBhMCVVMxEjAQBgNVBAgTCUJlcmtzaGlyZTEX
+MBUGA1UEChMOTXkgQ29tcGFueSBMdGQxFDASBgNVBAsTC3Rlc3QtY2xpZW50MRQw
+EgYDVQQDEwt0ZXN0LWNsaWVudDEjMCEGCSqGSIb3DQEJARYUdGVzdC1jbGllbnRA
+dGVzdC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDO0un79KTO
+ZofMiy3Sw7j6vupTCJWeJ0oEeDGhNtLlQvV29yRxuNMQ/bdXhmgpAhvpkyuvwH49
+WBY0ECWFfigtQvw0f9ZPCue2uUBRyOWJYM1zUWNn4Vk2MV7Qh0tdl4pCItNC8oNi
+eYRFW9ggl+LRNCNe7L+KQXytgFDzmxxRXeQpHMHGfKEAcA/2eXcDIvVLq3bKIKvh
+TlNshmjp1g9ulUu1tc/TbNRz28A9HSAgcqs+Jbs/zV8td/3XC6jrDHPAP3QnF1bP
+MZqp7cE5J8eq6XdI9G1WiTVceVv2L4yfk7wTHNB0XzAbFUNxjv8a32VlacKKWqsE
+SoDeICmNSByDAgMBAAGjggEcMIIBGDAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQf
+Fh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUNOlc2PzH
+r/dd9BPTghrNUg9Kuwswgb0GA1UdIwSBtTCBsoAUUjMuImZ5guVBLo07suXM+r6Z
+M46hgY6kgYswgYgxCzAJBgNVBAYTAlVTMRIwEAYDVQQIEwlCZXJrc2hpcmUxEDAO
+BgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15IENvbXBhbnkgTHRkMQ0wCwYDVQQL
+EwR0ZXN0MQ0wCwYDVQQDEwR0ZXN0MRwwGgYJKoZIhvcNAQkBFg10ZXN0QHRlc3Qu
+Y29tggkA5kxcliZe1tAwDQYJKoZIhvcNAQEEBQADggEBAIjE3cVKpo4fNmKAMWsr
+hTQNbKfc4Vo83XRX21m+i/J5QC29m+GrDgN1IHUv6pf51H4VdcKC9bE35Isk1O8C
+OxlqVrufw6W0xDmgZJZbw6gZdOwLzzPf8xLz4qsdfd4hZM2xoG96d4TUYopQ5nZd
+rzrvGocOGjjE+Q0vFOAgMkwucNJxgtXlyRMsTrTIY2UdSOjDVm2IhFdlEx5CSLQD
+JXFOEp0aiGXVcSE7Dr43HPCIa0UMDmzlYMuGv79AMMTPlPgcYNQb34gCekV+0cbz
+B7mxjypVL753n9FGZAW3Z8WyrIxCj2pRpA0rFqTWOaX4Je1oJRO1Gaxs6ezuA2uA
+OG4=
+-----END CERTIFICATE-----
diff --git a/libnm-core/tests/test-compare.c b/libnm-core/tests/test-compare.c
new file mode 100644
index 000000000..12db9c23b
--- /dev/null
+++ b/libnm-core/tests/test-compare.c
@@ -0,0 +1,248 @@
+/* -*- 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 2007 - 2014 Red Hat, Inc.
+ * Copyright 2007 - 2008 Novell, Inc.
+ */
+
+#include "config.h"
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include "nm-glib-compat.h"
+
+#include "nm-property-compare.h"
+
+#include "nm-test-utils.h"
+
+static void
+compare_ints (void)
+{
+ GVariant *value1, *value2;
+
+ value1 = g_variant_new_int32 (5);
+ value2 = g_variant_new_int32 (5);
+ g_assert (nm_property_compare (value1, value2) == 0);
+
+ g_variant_unref (value2);
+ value2 = g_variant_new_int32 (10);
+ g_assert (nm_property_compare (value1, value2) < 0);
+
+ g_variant_unref (value2);
+ value2 = g_variant_new_int32 (-1);
+ g_assert (nm_property_compare (value1, value2) > 0);
+
+ g_variant_unref (value1);
+ g_variant_unref (value2);
+}
+
+static void
+compare_strings (void)
+{
+ GVariant *value1, *value2;
+ const char *str1 = "hello";
+ const char *str2 = "world";
+
+ value1 = g_variant_new_string (str1);
+ value2 = g_variant_new_string (str1);
+ g_assert (nm_property_compare (value1, value2) == 0);
+
+ g_variant_unref (value2);
+ value2 = g_variant_new_string (str2);
+ g_assert (nm_property_compare (value1, value2) < 0);
+
+ g_assert (nm_property_compare (value2, value1) > 0);
+
+ g_variant_unref (value1);
+ g_variant_unref (value2);
+}
+
+static void
+compare_strv (void)
+{
+ GVariant *value1, *value2;
+ const char * const strv1[] = { "foo", "bar", "baz", NULL };
+ const char * const strv2[] = { "foo", "bar", "bar", NULL };
+ const char * const strv3[] = { "foo", "bar", NULL };
+ const char * const strv4[] = { "foo", "bar", "baz", "bam", NULL };
+
+ value1 = g_variant_new_strv (strv1, -1);
+ value2 = g_variant_new_strv (strv1, -1);
+ g_assert (nm_property_compare (value1, value2) == 0);
+
+ g_variant_unref (value2);
+ value2 = g_variant_new_strv (strv2, -1);
+ g_assert (nm_property_compare (value1, value2) != 0);
+
+ g_variant_unref (value2);
+ value2 = g_variant_new_strv (strv3, -1);
+ g_assert (nm_property_compare (value1, value2) != 0);
+
+ g_variant_unref (value2);
+ value2 = g_variant_new_strv (strv4, -1);
+ g_assert (nm_property_compare (value1, value2) != 0);
+
+ g_variant_unref (value1);
+ g_variant_unref (value2);
+}
+
+static void
+compare_arrays (void)
+{
+ GVariant *value1, *value2;
+ guint32 array[] = { 0, 1, 2, 3, 4 };
+
+ value1 = g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
+ array, G_N_ELEMENTS (array),
+ sizeof (guint32));
+ value2 = g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
+ array, G_N_ELEMENTS (array),
+ sizeof (guint32));
+
+ g_assert (nm_property_compare (value1, value2) == 0);
+
+ g_variant_unref (value2);
+ value2 = g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
+ array + 1, G_N_ELEMENTS (array) - 1,
+ sizeof (guint32));
+ g_assert (nm_property_compare (value1, value2) != 0);
+
+ array[0] = 7;
+ g_variant_unref (value2);
+ value2 = g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
+ array, G_N_ELEMENTS (array),
+ sizeof (guint32));
+ g_assert (nm_property_compare (value1, value2) != 0);
+
+ g_variant_unref (value1);
+ g_variant_unref (value2);
+}
+
+static void
+compare_str_hash (void)
+{
+ GVariant *value1, *value2;
+ GVariantBuilder builder;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
+ g_variant_builder_add (&builder, "{ss}", "key1", "hello");
+ g_variant_builder_add (&builder, "{ss}", "key2", "world");
+ g_variant_builder_add (&builder, "{ss}", "key3", "!");
+ value1 = g_variant_builder_end (&builder);
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
+ g_variant_builder_add (&builder, "{ss}", "key3", "!");
+ g_variant_builder_add (&builder, "{ss}", "key2", "world");
+ g_variant_builder_add (&builder, "{ss}", "key1", "hello");
+ value2 = g_variant_builder_end (&builder);
+
+ g_assert (nm_property_compare (value1, value2) == 0);
+
+ g_variant_unref (value2);
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
+ g_variant_builder_add (&builder, "{ss}", "key1", "hello");
+ g_variant_builder_add (&builder, "{ss}", "key3", "!");
+ value2 = g_variant_builder_end (&builder);
+
+ g_assert (nm_property_compare (value1, value2) != 0);
+ g_assert (nm_property_compare (value2, value1) != 0);
+
+ g_variant_unref (value2);
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
+ g_variant_builder_add (&builder, "{ss}", "key1", "hello");
+ g_variant_builder_add (&builder, "{ss}", "key2", "moon");
+ g_variant_builder_add (&builder, "{ss}", "key3", "!");
+ value2 = g_variant_builder_end (&builder);
+
+ g_assert (nm_property_compare (value1, value2) != 0);
+
+ g_variant_unref (value1);
+ g_variant_unref (value2);
+}
+
+static void
+compare_ip6_addresses (void)
+{
+ GVariant *value1, *value2;
+ struct in6_addr addr1;
+ struct in6_addr addr2;
+ struct in6_addr addr3;
+ guint32 prefix1 = 64;
+ guint32 prefix2 = 64;
+ guint32 prefix3 = 0;
+
+ inet_pton (AF_INET6, "1:2:3:4:5:6:7:8", &addr1);
+ inet_pton (AF_INET6, "ffff:2:3:4:5:6:7:8", &addr2);
+ inet_pton (AF_INET6, "::", &addr3);
+
+ value1 = g_variant_new ("(@ayu@ay)",
+ g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+ (guint8 *) addr1.s6_addr, 16, 1),
+ prefix1,
+ g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+ (guint8 *) addr3.s6_addr, 16, 1));
+
+ value2 = g_variant_new ("(@ayu@ay)",
+ g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+ (guint8 *) addr1.s6_addr, 16, 1),
+ prefix1,
+ g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+ (guint8 *) addr3.s6_addr, 16, 1));
+
+ g_assert (nm_property_compare (value1, value2) == 0);
+
+ g_variant_unref (value2);
+ value2 = g_variant_new ("(@ayu@ay)",
+ g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+ (guint8 *) addr2.s6_addr, 16, 1),
+ prefix2,
+ g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+ (guint8 *) addr3.s6_addr, 16, 1));
+
+ g_assert (nm_property_compare (value1, value2) != 0);
+
+ g_variant_unref (value2);
+ value2 = g_variant_new ("(@ayu@ay)",
+ g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+ (guint8 *) addr3.s6_addr, 16, 1),
+ prefix3,
+ g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+ (guint8 *) addr3.s6_addr, 16, 1));
+
+ g_assert (nm_property_compare (value1, value2) != 0);
+
+ g_variant_unref (value1);
+ g_variant_unref (value2);
+}
+
+NMTST_DEFINE ();
+
+int
+main (int argc, char *argv[])
+{
+ nmtst_init (&argc, &argv, TRUE);
+
+ g_test_add_func ("/libnm/compare/ints", compare_ints);
+ g_test_add_func ("/libnm/compare/strings", compare_strings);
+ g_test_add_func ("/libnm/compare/strv", compare_strv);
+ g_test_add_func ("/libnm/compare/arrays", compare_arrays);
+ g_test_add_func ("/libnm/compare/str_hash", compare_str_hash);
+ g_test_add_func ("/libnm/compare/ip6_addresses", compare_ip6_addresses);
+
+ return g_test_run ();
+}
diff --git a/libnm-core/tests/test-crypto.c b/libnm-core/tests/test-crypto.c
new file mode 100644
index 000000000..1c8ae4773
--- /dev/null
+++ b/libnm-core/tests/test-crypto.c
@@ -0,0 +1,501 @@
+/* -*- 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 "config.h"
+
+#include <glib.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <glib/gi18n.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "crypto.h"
+#include "nm-utils.h"
+#include "nm-errors.h"
+#include "nm-core-internal.h"
+
+#include "nm-test-utils.h"
+
+#if 0
+static const char *pem_rsa_key_begin = "-----BEGIN RSA PRIVATE KEY-----";
+static const char *pem_rsa_key_end = "-----END RSA PRIVATE KEY-----";
+
+static const char *pem_dsa_key_begin = "-----BEGIN DSA PRIVATE KEY-----";
+static const char *pem_dsa_key_end = "-----END DSA PRIVATE KEY-----";
+
+static void
+dump_key_to_pem (const char *key, gsize key_len, int key_type)
+{
+ char *b64 = NULL;
+ GString *str = NULL;
+ const char *start_tag;
+ const char *end_tag;
+ char *p;
+
+ switch (key_type) {
+ case NM_CRYPTO_KEY_TYPE_RSA:
+ start_tag = pem_rsa_key_begin;
+ end_tag = pem_rsa_key_end;
+ break;
+ case NM_CRYPTO_KEY_TYPE_DSA:
+ start_tag = pem_dsa_key_begin;
+ end_tag = pem_dsa_key_end;
+ break;
+ default:
+ g_warning ("Unknown key type %d", key_type);
+ return;
+ }
+
+ b64 = g_base64_encode ((const unsigned char *) key, key_len);
+ if (!b64) {
+ g_warning ("Couldn't base64 encode the key.");
+ goto out;
+ }
+
+ str = g_string_new (NULL);
+
+ g_string_append (str, start_tag);
+ g_string_append_c (str, '\n');
+
+ for (p = b64; p < (b64 + strlen (b64)); p += 64) {
+ g_string_append_len (str, p, strnlen (p, 64));
+ g_string_append_c (str, '\n');
+ }
+
+ g_string_append (str, end_tag);
+ g_string_append_c (str, '\n');
+
+ g_message ("Decrypted private key:\n\n%s", str->str);
+
+out:
+ g_free (b64);
+ if (str)
+ g_string_free (str, TRUE);
+}
+#endif
+
+static void
+test_cert (gconstpointer test_data)
+{
+ char *path;
+ GByteArray *array;
+ NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+ GError *error = NULL;
+
+ 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);
+ 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,
+ const char *decrypted_path,
+ int expected_error)
+{
+ NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN;
+ gboolean is_encrypted = FALSE;
+ GByteArray *array, *decrypted;
+ 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);
+ /* Even if the password is wrong, we should determine the key type */
+ g_assert_cmpint (key_type, ==, NM_CRYPTO_KEY_TYPE_RSA);
+
+ if (expected_error != -1) {
+ g_assert (array == NULL);
+ g_assert_error (error, NM_CRYPTO_ERROR, expected_error);
+ g_clear_error (&error);
+ return;
+ }
+
+ if (password == NULL) {
+ g_assert (array == NULL);
+ g_assert_no_error (error);
+ return;
+ }
+
+ 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);
+
+ g_byte_array_free (decrypted, TRUE);
+ }
+
+ g_byte_array_free (array, TRUE);
+}
+
+static void
+test_load_pkcs12 (const char *path,
+ const char *password,
+ int expected_error)
+{
+ NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+ gboolean is_encrypted = FALSE;
+ GError *error = NULL;
+
+ g_assert (nm_utils_file_is_private_key (path, NULL));
+
+ format = 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);
+ g_clear_error (&error);
+ } else {
+ g_assert_no_error (error);
+ g_assert_cmpint (format, ==, NM_CRYPTO_FILE_FORMAT_PKCS12);
+ g_assert (is_encrypted);
+ }
+}
+
+static void
+test_load_pkcs12_no_password (const char *path)
+{
+ NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+ gboolean is_encrypted = FALSE;
+ GError *error = NULL;
+
+ 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);
+ g_assert_no_error (error);
+ g_assert_cmpint (format, ==, NM_CRYPTO_FILE_FORMAT_PKCS12);
+ g_assert (is_encrypted);
+}
+
+static void
+test_is_pkcs12 (const char *path, gboolean expect_fail)
+{
+ gboolean is_pkcs12;
+ GError *error = NULL;
+
+ is_pkcs12 = crypto_is_pkcs12_file (path, &error);
+
+ if (expect_fail) {
+ g_assert_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_INVALID_DATA);
+ g_assert (!is_pkcs12);
+ } else {
+ g_assert_no_error (error);
+ g_assert (is_pkcs12);
+ }
+}
+
+static void
+test_load_pkcs8 (const char *path,
+ const char *password,
+ int expected_error)
+{
+ NMCryptoFileFormat format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
+ gboolean is_encrypted = FALSE;
+ GError *error = NULL;
+
+ g_assert (nm_utils_file_is_private_key (path, NULL));
+
+ format = 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);
+ g_clear_error (&error);
+ } else {
+ g_assert_no_error (error);
+ g_assert_cmpint (format, ==, NM_CRYPTO_FILE_FORMAT_RAW_KEY);
+ g_assert (is_encrypted);
+ }
+}
+
+static void
+test_encrypt_private_key (const char *path,
+ const char *password)
+{
+ NMCryptoKeyType key_type = NM_CRYPTO_KEY_TYPE_UNKNOWN;
+ GByteArray *array, *encrypted, *re_decrypted;
+ GError *error = NULL;
+
+ array = crypto_decrypt_openssl_private_key (path, password, &key_type, &error);
+ g_assert_no_error (error);
+ g_assert (array != NULL);
+ 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);
+
+ /* 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);
+ 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);
+}
+
+static void
+test_key (gconstpointer test_data)
+{
+ char **parts, *path, *password, *decrypted_path;
+ int len;
+
+ parts = g_strsplit ((const char *) test_data, ", ", -1);
+ len = g_strv_length (parts);
+ if (len != 2 && len != 3)
+ g_error ("wrong number of arguments (<key file>, <password>, [<decrypted key file>])");
+
+ path = g_build_filename (TEST_CERT_DIR, parts[0], NULL);
+ password = parts[1];
+ decrypted_path = parts[2] ? g_build_filename (TEST_CERT_DIR, parts[2], NULL) : NULL;
+
+ test_is_pkcs12 (path, TRUE);
+ test_load_private_key (path, password, decrypted_path, -1);
+ test_load_private_key (path, "blahblahblah", NULL, NM_CRYPTO_ERROR_DECRYPTION_FAILED);
+ test_load_private_key (path, NULL, NULL, -1);
+ test_encrypt_private_key (path, password);
+
+ g_free (path);
+ g_free (decrypted_path);
+ g_strfreev (parts);
+}
+
+static void
+test_key_decrypted (gconstpointer test_data)
+{
+ const char *file = (const char *) test_data;
+ gboolean is_encrypted = FALSE;
+ char *path;
+
+ path = g_build_filename (TEST_CERT_DIR, file, NULL);
+
+ g_assert (nm_utils_file_is_private_key (path, &is_encrypted));
+ g_assert (!is_encrypted);
+
+ g_free (path);
+}
+
+static void
+test_pkcs12 (gconstpointer test_data)
+{
+ char **parts, *path, *password;
+
+ parts = g_strsplit ((const char *) test_data, ", ", -1);
+ if (g_strv_length (parts) != 2)
+ g_error ("wrong number of arguments (<file>, <password>)");
+
+ path = g_build_filename (TEST_CERT_DIR, parts[0], NULL);
+ password = parts[1];
+
+ test_is_pkcs12 (path, FALSE);
+ test_load_pkcs12 (path, password, -1);
+ test_load_pkcs12 (path, "blahblahblah", NM_CRYPTO_ERROR_DECRYPTION_FAILED);
+ test_load_pkcs12_no_password (path);
+
+ g_free (path);
+ g_strfreev (parts);
+}
+
+static void
+test_pkcs8 (gconstpointer test_data)
+{
+ char **parts, *path, *password;
+
+ parts = g_strsplit ((const char *) test_data, ", ", -1);
+ if (g_strv_length (parts) != 2)
+ g_error ("wrong number of arguments (<file>, <password>)");
+
+ path = g_build_filename (TEST_CERT_DIR, parts[0], NULL);
+ password = parts[1];
+
+ test_is_pkcs12 (path, TRUE);
+ test_load_pkcs8 (path, password, -1);
+ /* Until gnutls and NSS grow support for all the ciphers that openssl
+ * can use with PKCS#8, we can't actually verify the password. So we
+ * expect a bad password to work for the time being.
+ */
+ test_load_pkcs8 (path, "blahblahblah", -1);
+
+ g_free (path);
+ g_strfreev (parts);
+}
+
+#define SALT "sodium chloride"
+#define SHORT_PASSWORD "short"
+#define LONG_PASSWORD "this is a longer password than the short one"
+#define SHORT_DIGEST 16
+#define LONG_DIGEST 57
+
+struct {
+ const char *salt, *password;
+ gsize digest_size;
+ const char *result;
+} md5_tests[] = {
+ { NULL, SHORT_PASSWORD, SHORT_DIGEST,
+ "4f09daa9d95bcb166a302407a0e0babe" },
+ { NULL, SHORT_PASSWORD, LONG_DIGEST,
+ "4f09daa9d95bcb166a302407a0e0babeb7d62e5baf706830d007c253f0fe7584ad7e92dc00a599ec277293c298ae70ee3904c348e23be61c91" },
+ { SALT, SHORT_PASSWORD, SHORT_DIGEST,
+ "774771f7292210233b5724991d1f9894" },
+ { SALT, SHORT_PASSWORD, LONG_DIGEST,
+ "774771f7292210233b5724991d1f98941a6ffdb45e4dc7fa04b1fa6aceed379c1ade0577bc8f261d109942ed5736921c052664d72e0d5bade9" },
+ { NULL, LONG_PASSWORD, SHORT_DIGEST,
+ "e9c03517f81ff29bb777dac21fb1699c" },
+ { NULL, LONG_PASSWORD, LONG_DIGEST,
+ "e9c03517f81ff29bb777dac21fb1699c50968c7ccd8db4f0a59d00ffd87b05876d45f25a927d51a8400c35af60fbd64584349a8b7435d62fd9" },
+ { SALT, LONG_PASSWORD, SHORT_DIGEST,
+ "4e5c076e2f85f5e03994acbf3a9e10d6" },
+ { SALT, LONG_PASSWORD, LONG_DIGEST,
+ "4e5c076e2f85f5e03994acbf3a9e10d61a6969c9fdf47ae8b1f7e2725b3767b05cc974bfcb5344b630c91761e015e09d7794b5065662533bc9" },
+ { NULL, "", SHORT_DIGEST,
+ "d41d8cd98f00b204e9800998ecf8427e" },
+ { SALT, "", SHORT_DIGEST,
+ "7df1e0494c977195005d82a1809685e4" },
+};
+
+static void
+test_md5 (void)
+{
+ char digest[LONG_DIGEST], *hex;
+ int i;
+
+ 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);
+
+ hex = nm_utils_bin2hexstr (digest, md5_tests[i].digest_size, -1);
+ g_assert_cmpstr (hex, ==, md5_tests[i].result);
+ g_free (hex);
+ }
+}
+
+NMTST_DEFINE ();
+
+int
+main (int argc, char **argv)
+{
+ GError *error = NULL;
+ int ret;
+
+ nmtst_init (&argc, &argv, TRUE);
+
+ if (!crypto_init (&error))
+ FAIL ("crypto-init", "failed to initialize crypto: %s", error->message);
+
+ g_test_add_data_func ("/libnm/crypto/cert/pem",
+ "test_ca_cert.pem",
+ test_cert);
+ g_test_add_data_func ("/libnm/crypto/cert/pem-2",
+ "test2_ca_cert.pem",
+ test_cert);
+ g_test_add_data_func ("/libnm/crypto/cert/der",
+ "test_ca_cert.der",
+ test_cert);
+ g_test_add_data_func ("/libnm/crypto/cert/pem-no-ending-newline",
+ "ca-no-ending-newline.pem",
+ test_cert);
+ g_test_add_data_func ("/libnm/crypto/cert/pem-combined",
+ "test_key_and_cert.pem",
+ test_cert);
+ g_test_add_data_func ("/libnm/crypto/cert/pem-combined-2",
+ "test2_key_and_cert.pem",
+ test_cert);
+
+ g_test_add_data_func ("/libnm/crypto/key/padding-6",
+ "test_key_and_cert.pem, test, test-key-only-decrypted.der",
+ test_key);
+ g_test_add_data_func ("/libnm/crypto/key/key-only",
+ "test-key-only.pem, test, test-key-only-decrypted.der",
+ test_key);
+ 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",
+ test_key);
+ g_test_add_data_func ("/libnm/crypto/key/decrypted",
+ "test-key-only-decrypted.pem",
+ test_key_decrypted);
+
+ g_test_add_data_func ("/libnm/crypto/PKCS#12/1",
+ "test-cert.p12, test",
+ test_pkcs12);
+ g_test_add_data_func ("/libnm/crypto/PKCS#12/2",
+ "test2-cert.p12, 12345testing",
+ test_pkcs12);
+
+ g_test_add_data_func ("/libnm/crypto/PKCS#8",
+ "pkcs8-enc-key.pem, 1234567890",
+ test_pkcs8);
+
+ g_test_add_func ("/libnm/crypto/md5", test_md5);
+
+ ret = g_test_run ();
+
+ return ret;
+}
+
diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c
new file mode 100644
index 000000000..d309c8005
--- /dev/null
+++ b/libnm-core/tests/test-general.c
@@ -0,0 +1,3961 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2008 - 2011 Red Hat, Inc.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <string.h>
+
+#include <nm-utils.h>
+
+#include "nm-setting-private.h"
+#include "nm-utils.h"
+#include "nm-core-internal.h"
+
+#include "nm-setting-8021x.h"
+#include "nm-setting-adsl.h"
+#include "nm-setting-bluetooth.h"
+#include "nm-setting-bond.h"
+#include "nm-setting-bridge.h"
+#include "nm-setting-bridge-port.h"
+#include "nm-setting-cdma.h"
+#include "nm-setting-connection.h"
+#include "nm-setting-generic.h"
+#include "nm-setting-gsm.h"
+#include "nm-setting-infiniband.h"
+#include "nm-setting-ip4-config.h"
+#include "nm-setting-ip6-config.h"
+#include "nm-setting-olpc-mesh.h"
+#include "nm-setting-ppp.h"
+#include "nm-setting-pppoe.h"
+#include "nm-setting-serial.h"
+#include "nm-setting-team.h"
+#include "nm-setting-team-port.h"
+#include "nm-setting-vlan.h"
+#include "nm-setting-vpn.h"
+#include "nm-setting-wimax.h"
+#include "nm-setting-wired.h"
+#include "nm-setting-wireless.h"
+#include "nm-setting-wireless-security.h"
+#include "nm-simple-connection.h"
+
+#include "nm-test-utils.h"
+
+static void
+vpn_check_func (const char *key, const char *value, gpointer user_data)
+{
+ const char *test = user_data;
+
+ if (!strcmp (key, "foobar1")) {
+ ASSERT (strcmp (value, "blahblah1") == 0,
+ test, "unexpected vpn item '%s' / '%s'", key, value);
+ return;
+ }
+
+ if (!strcmp (key, "foobar2")) {
+ ASSERT (strcmp (value, "blahblah2") == 0,
+ test, "unexpected vpn item '%s' / '%s'", key, value);
+ return;
+ }
+
+ if (!strcmp (key, "foobar3")) {
+ ASSERT (strcmp (value, "blahblah3") == 0,
+ test, "unexpected vpn item '%s' / '%s'", key, value);
+ return;
+ }
+
+ if (!strcmp (key, "foobar4")) {
+ ASSERT (strcmp (value, "blahblah4") == 0,
+ test, "unexpected vpn item '%s' / '%s'", key, value);
+ return;
+ }
+
+ ASSERT (FALSE, test, "unexpected vpn item '%s'", key);
+}
+
+static void
+vpn_check_empty_func (const char *key, const char *value, gpointer user_data)
+{
+ const char *test = user_data;
+
+ /* We don't expect any values */
+ ASSERT (FALSE, test, "unexpected vpn item '%s'", key);
+}
+
+static void
+test_setting_vpn_items (void)
+{
+ NMSettingVpn *s_vpn;
+
+ s_vpn = (NMSettingVpn *) nm_setting_vpn_new ();
+ ASSERT (s_vpn != NULL,
+ "vpn-items",
+ "error creating vpn setting");
+
+ nm_setting_vpn_add_data_item (s_vpn, "foobar1", "blahblah1");
+ nm_setting_vpn_add_data_item (s_vpn, "foobar2", "blahblah2");
+ nm_setting_vpn_add_data_item (s_vpn, "foobar3", "blahblah3");
+ nm_setting_vpn_add_data_item (s_vpn, "foobar4", "blahblah4");
+
+ /* Ensure that added values are all present */
+ nm_setting_vpn_foreach_data_item (s_vpn, vpn_check_func, "vpn-data");
+ nm_setting_vpn_remove_data_item (s_vpn, "foobar1");
+ nm_setting_vpn_remove_data_item (s_vpn, "foobar2");
+ nm_setting_vpn_remove_data_item (s_vpn, "foobar3");
+ nm_setting_vpn_remove_data_item (s_vpn, "foobar4");
+
+ nm_setting_vpn_add_secret (s_vpn, "foobar1", "blahblah1");
+ nm_setting_vpn_add_secret (s_vpn, "foobar2", "blahblah2");
+ nm_setting_vpn_add_secret (s_vpn, "foobar3", "blahblah3");
+ nm_setting_vpn_add_secret (s_vpn, "foobar4", "blahblah4");
+
+ /* Ensure that added values are all present */
+ nm_setting_vpn_foreach_secret (s_vpn, vpn_check_func, "vpn-secrets");
+ nm_setting_vpn_remove_secret (s_vpn, "foobar1");
+ nm_setting_vpn_remove_secret (s_vpn, "foobar2");
+ nm_setting_vpn_remove_secret (s_vpn, "foobar3");
+ nm_setting_vpn_remove_secret (s_vpn, "foobar4");
+
+ /* Try to add some blank values and make sure they are rejected */
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*key != NULL*");
+ nm_setting_vpn_add_data_item (s_vpn, NULL, NULL);
+ g_test_assert_expected_messages ();
+
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*strlen (key) > 0*");
+ nm_setting_vpn_add_data_item (s_vpn, "", "");
+ g_test_assert_expected_messages ();
+
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*item != NULL*");
+ nm_setting_vpn_add_data_item (s_vpn, "foobar1", NULL);
+ g_test_assert_expected_messages ();
+
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*strlen (item) > 0*");
+ nm_setting_vpn_add_data_item (s_vpn, "foobar1", "");
+ g_test_assert_expected_messages ();
+
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*key != NULL*");
+ nm_setting_vpn_add_data_item (s_vpn, NULL, "blahblah1");
+ g_test_assert_expected_messages ();
+
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*strlen (key) > 0*");
+ nm_setting_vpn_add_data_item (s_vpn, "", "blahblah1");
+ g_test_assert_expected_messages ();
+
+ nm_setting_vpn_foreach_data_item (s_vpn, vpn_check_empty_func, "vpn-data-empty");
+
+ /* Try to add some blank secrets and make sure they are rejected */
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*key != NULL*");
+ nm_setting_vpn_add_secret (s_vpn, NULL, NULL);
+ g_test_assert_expected_messages ();
+
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*strlen (key) > 0*");
+ nm_setting_vpn_add_secret (s_vpn, "", "");
+ g_test_assert_expected_messages ();
+
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*secret != NULL*");
+ nm_setting_vpn_add_secret (s_vpn, "foobar1", NULL);
+ g_test_assert_expected_messages ();
+
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*strlen (secret) > 0*");
+ nm_setting_vpn_add_secret (s_vpn, "foobar1", "");
+ g_test_assert_expected_messages ();
+
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*key != NULL*");
+ nm_setting_vpn_add_secret (s_vpn, NULL, "blahblah1");
+ g_test_assert_expected_messages ();
+
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*strlen (key) > 0*");
+ nm_setting_vpn_add_secret (s_vpn, "", "blahblah1");
+ g_test_assert_expected_messages ();
+
+ nm_setting_vpn_foreach_secret (s_vpn, vpn_check_empty_func, "vpn-secrets-empty");
+
+ g_object_unref (s_vpn);
+}
+
+static void
+test_setting_vpn_update_secrets (void)
+{
+ NMConnection *connection;
+ NMSettingVpn *s_vpn;
+ GVariantBuilder settings_builder, vpn_builder, secrets_builder;
+ GVariant *settings;
+ gboolean success;
+ GError *error = NULL;
+ const char *tmp;
+ const char *key1 = "foobar";
+ const char *key2 = "blahblah";
+ const char *val1 = "value1";
+ const char *val2 = "value2";
+
+ connection = nm_simple_connection_new ();
+ ASSERT (connection != NULL,
+ "vpn-update-secrets",
+ "error creating connection");
+
+ s_vpn = (NMSettingVpn *) nm_setting_vpn_new ();
+ ASSERT (s_vpn != NULL,
+ "vpn-update-secrets",
+ "error creating vpn setting");
+ nm_connection_add_setting (connection, NM_SETTING (s_vpn));
+
+ g_variant_builder_init (&settings_builder, NM_VARIANT_TYPE_CONNECTION);
+ g_variant_builder_init (&vpn_builder, NM_VARIANT_TYPE_SETTING);
+ g_variant_builder_init (&secrets_builder, G_VARIANT_TYPE ("a{ss}"));
+
+ g_variant_builder_add (&secrets_builder, "{ss}", key1, val1);
+ g_variant_builder_add (&secrets_builder, "{ss}", key2, val2);
+
+ g_variant_builder_add (&vpn_builder, "{sv}",
+ NM_SETTING_VPN_SECRETS,
+ g_variant_builder_end (&secrets_builder));
+ g_variant_builder_add (&settings_builder, "{sa{sv}}",
+ NM_SETTING_VPN_SETTING_NAME,
+ &vpn_builder);
+ settings = g_variant_builder_end (&settings_builder);
+
+ success = nm_connection_update_secrets (connection, NM_SETTING_VPN_SETTING_NAME, settings, &error);
+ ASSERT (success == TRUE,
+ "vpn-update-secrets", "failed to update VPN secrets: %s", error->message);
+
+ /* Read the secrets back out */
+ tmp = nm_setting_vpn_get_secret (s_vpn, key1);
+ ASSERT (tmp != NULL,
+ "vpn-update-secrets", "unexpected failure getting key #1");
+ ASSERT (strcmp (tmp, val1) == 0,
+ "vpn-update-secrets", "unexpected key #1 value");
+
+ tmp = nm_setting_vpn_get_secret (s_vpn, key2);
+ ASSERT (tmp != NULL,
+ "vpn-update-secrets", "unexpected failure getting key #2");
+ ASSERT (strcmp (tmp, val2) == 0,
+ "vpn-update-secrets", "unexpected key #2 value");
+
+ g_variant_unref (settings);
+ g_object_unref (connection);
+}
+
+#define TO_DEL_NUM 50
+typedef struct {
+ NMSettingVpn *s_vpn;
+ char *to_del[TO_DEL_NUM];
+ guint called;
+} IterInfo;
+
+static void
+del_iter_func (const char *key, const char *value, gpointer user_data)
+{
+ IterInfo *info = user_data;
+ int i;
+
+ /* Record how many times this function gets called; it should get called
+ * exactly as many times as there are keys in the hash table, regardless
+ * of what keys we delete from the table.
+ */
+ info->called++;
+
+ /* During the iteration, remove a bunch of stuff from the table */
+ if (info->called == 1) {
+ for (i = 0; i < TO_DEL_NUM; i++)
+ nm_setting_vpn_remove_data_item (info->s_vpn, info->to_del[i]);
+ }
+}
+
+static void
+test_setting_vpn_modify_during_foreach (void)
+{
+ NMSettingVpn *s_vpn;
+ IterInfo info;
+ char *key, *val;
+ int i, u = 0;
+
+ s_vpn = (NMSettingVpn *) nm_setting_vpn_new ();
+ g_assert (s_vpn);
+
+ for (i = 0; i < TO_DEL_NUM * 2; i++) {
+ key = g_strdup_printf ("adsfasdfadf%d", i);
+ val = g_strdup_printf ("42263236236awt%d", i);
+ nm_setting_vpn_add_data_item (s_vpn, key, val);
+
+ /* Cache some keys to delete */
+ if (i % 2)
+ info.to_del[u++] = g_strdup (key);
+
+ g_free (key);
+ g_free (val);
+ }
+
+ /* Iterate over current table keys */
+ info.s_vpn = s_vpn;
+ info.called = 0;
+ nm_setting_vpn_foreach_data_item (s_vpn, del_iter_func, &info);
+
+ /* Make sure all the things we removed during iteration are really gone */
+ for (i = 0; i < TO_DEL_NUM; i++) {
+ g_assert_cmpstr (nm_setting_vpn_get_data_item (s_vpn, info.to_del[i]), ==, NULL);
+ g_free (info.to_del[i]);
+ }
+
+ /* And make sure the foreach callback was called the same number of times
+ * as there were keys in the table at the beginning of the foreach.
+ */
+ g_assert_cmpint (info.called, ==, TO_DEL_NUM * 2);
+
+ g_object_unref (s_vpn);
+}
+
+static void
+test_setting_ip4_config_labels (void)
+{
+ NMSettingIPConfig *s_ip4;
+ NMIPAddress *addr;
+ GVariant *label;
+ GPtrArray *addrs;
+ char **labels;
+ NMConnection *conn;
+ GVariant *dict, *dict2, *setting_dict, *value;
+ GError *error = NULL;
+
+ s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
+ g_object_set (G_OBJECT (s_ip4),
+ NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
+ NULL);
+
+ /* addr 1 */
+ addr = nm_ip_address_new (AF_INET, "1.2.3.4", 24, &error);
+ g_assert_no_error (error);
+
+ nm_setting_ip_config_add_address (s_ip4, addr);
+ nm_ip_address_unref (addr);
+ nmtst_assert_setting_verifies (NM_SETTING (s_ip4));
+
+ addr = nm_setting_ip_config_get_address (s_ip4, 0);
+ label = nm_ip_address_get_attribute (addr, "label");
+ g_assert (label == NULL);
+
+ /* The 'address-labels' property should be omitted from the serialization if
+ * there are no non-NULL labels.
+ */
+ conn = nmtst_create_minimal_connection ("label test", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
+ nm_connection_add_setting (conn, nm_setting_duplicate (NM_SETTING (s_ip4)));
+ dict = nm_connection_to_dbus (conn, NM_CONNECTION_SERIALIZE_ALL);
+ g_object_unref (conn);
+
+ setting_dict = g_variant_lookup_value (dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
+ g_assert (setting_dict != NULL);
+
+ value = g_variant_lookup_value (setting_dict, "address-labels", NULL);
+ g_assert (value == NULL);
+
+ g_variant_unref (setting_dict);
+ g_variant_unref (dict);
+
+ /* Now back to constructing the original s_ip4... */
+
+ /* addr 2 */
+ addr = nm_ip_address_new (AF_INET, "2.3.4.5", 24, &error);
+ g_assert_no_error (error);
+ nm_ip_address_set_attribute (addr, "label", g_variant_new_string ("eth0:1"));
+
+ nm_setting_ip_config_add_address (s_ip4, addr);
+ nm_ip_address_unref (addr);
+ nmtst_assert_setting_verifies (NM_SETTING (s_ip4));
+
+ addr = nm_setting_ip_config_get_address (s_ip4, 1);
+ label = nm_ip_address_get_attribute (addr, "label");
+ g_assert (label != NULL);
+ g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1");
+
+ /* addr 3 */
+ addr = nm_ip_address_new (AF_INET, "3.4.5.6", 24, &error);
+ g_assert_no_error (error);
+ nm_ip_address_set_attribute (addr, "label", NULL);
+
+ nm_setting_ip_config_add_address (s_ip4, addr);
+ nm_ip_address_unref (addr);
+ nmtst_assert_setting_verifies (NM_SETTING (s_ip4));
+
+ addr = nm_setting_ip_config_get_address (s_ip4, 2);
+ label = nm_ip_address_get_attribute (addr, "label");
+ g_assert (label == NULL);
+
+ /* Remove addr 1 and re-verify remaining addresses */
+ nm_setting_ip_config_remove_address (s_ip4, 0);
+ nmtst_assert_setting_verifies (NM_SETTING (s_ip4));
+
+ addr = nm_setting_ip_config_get_address (s_ip4, 0);
+ g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "2.3.4.5");
+ label = nm_ip_address_get_attribute (addr, "label");
+ g_assert (label != NULL);
+ g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1");
+
+ addr = nm_setting_ip_config_get_address (s_ip4, 1);
+ g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "3.4.5.6");
+ label = nm_ip_address_get_attribute (addr, "label");
+ g_assert (label == NULL);
+
+ /* If we serialize as the daemon, the labels should appear in the D-Bus
+ * serialization under both 'address-labels' and 'address-data'.
+ */
+ conn = nmtst_create_minimal_connection ("label test", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
+ nm_connection_add_setting (conn, NM_SETTING (s_ip4));
+ _nm_utils_is_manager_process = TRUE;
+ dict = nm_connection_to_dbus (conn, NM_CONNECTION_SERIALIZE_ALL);
+ _nm_utils_is_manager_process = FALSE;
+ g_object_unref (conn);
+
+ setting_dict = g_variant_lookup_value (dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
+ g_assert (setting_dict != NULL);
+
+ value = g_variant_lookup_value (setting_dict, "address-labels", G_VARIANT_TYPE_STRING_ARRAY);
+ g_assert (value != NULL);
+ g_variant_get (value, "^as", &labels);
+ g_assert_cmpint (g_strv_length (labels), ==, 2);
+ g_assert_cmpstr (labels[0], ==, "eth0:1");
+ g_assert_cmpstr (labels[1], ==, "");
+ g_variant_unref (value);
+ g_strfreev (labels);
+
+ value = g_variant_lookup_value (setting_dict, "address-data", G_VARIANT_TYPE ("aa{sv}"));
+ addrs = nm_utils_ip_addresses_from_variant (value, AF_INET);
+ g_variant_unref (value);
+ g_assert (addrs != NULL);
+ g_assert_cmpint (addrs->len, ==, 2);
+ addr = addrs->pdata[0];
+ label = nm_ip_address_get_attribute (addr, "label");
+ g_assert (label != NULL);
+ g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1");
+ addr = addrs->pdata[1];
+ label = nm_ip_address_get_attribute (addr, "label");
+ g_assert (label == NULL);
+ g_ptr_array_unref (addrs);
+
+ g_variant_unref (setting_dict);
+
+ /* We should be able to deserialize the labels from either 'address-labels'
+ * or 'address-data'.
+ */
+ dict2 = g_variant_ref (dict);
+
+ NMTST_VARIANT_EDITOR (dict,
+ NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP4_CONFIG_SETTING_NAME,
+ "address-data");
+ );
+ conn = nm_simple_connection_new_from_dbus (dict, &error);
+ g_assert_no_error (error);
+ g_variant_unref (dict);
+
+ s_ip4 = nm_connection_get_setting_ip4_config (conn);
+
+ addr = nm_setting_ip_config_get_address (s_ip4, 0);
+ g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "2.3.4.5");
+ label = nm_ip_address_get_attribute (addr, "label");
+ g_assert (label != NULL);
+ g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1");
+
+ addr = nm_setting_ip_config_get_address (s_ip4, 1);
+ g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "3.4.5.6");
+ label = nm_ip_address_get_attribute (addr, "label");
+ g_assert (label == NULL);
+
+ g_object_unref (conn);
+
+ NMTST_VARIANT_EDITOR (dict2,
+ NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP4_CONFIG_SETTING_NAME,
+ "address-labels");
+ );
+ conn = nm_simple_connection_new_from_dbus (dict2, &error);
+ g_assert_no_error (error);
+ g_variant_unref (dict2);
+
+ s_ip4 = nm_connection_get_setting_ip4_config (conn);
+
+ addr = nm_setting_ip_config_get_address (s_ip4, 0);
+ g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "2.3.4.5");
+ label = nm_ip_address_get_attribute (addr, "label");
+ g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1");
+
+ addr = nm_setting_ip_config_get_address (s_ip4, 1);
+ g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "3.4.5.6");
+ label = nm_ip_address_get_attribute (addr, "label");
+ g_assert (label == NULL);
+
+ /* Test explicit property assignment */
+ g_object_get (G_OBJECT (s_ip4),
+ NM_SETTING_IP_CONFIG_ADDRESSES, &addrs,
+ NULL);
+
+ nm_setting_ip_config_clear_addresses (s_ip4);
+ g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, 0);
+
+ g_object_set (G_OBJECT (s_ip4),
+ NM_SETTING_IP_CONFIG_ADDRESSES, addrs,
+ NULL);
+ g_ptr_array_unref (addrs);
+ nmtst_assert_setting_verifies (NM_SETTING (s_ip4));
+ g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, 2);
+
+ addr = nm_setting_ip_config_get_address (s_ip4, 0);
+ g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "2.3.4.5");
+ label = nm_ip_address_get_attribute (addr, "label");
+ g_assert (label != NULL);
+ g_assert_cmpstr (g_variant_get_string (label, NULL), ==, "eth0:1");
+
+ addr = nm_setting_ip_config_get_address (s_ip4, 1);
+ g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "3.4.5.6");
+ label = nm_ip_address_get_attribute (addr, "label");
+ g_assert (label == NULL);
+
+ g_object_unref (conn);
+}
+
+static void
+test_setting_ip4_config_address_data (void)
+{
+ NMSettingIPConfig *s_ip4;
+ NMIPAddress *addr;
+ GPtrArray *addrs;
+ NMConnection *conn;
+ GVariant *dict, *setting_dict, *value;
+ GError *error = NULL;
+
+ s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
+ g_object_set (G_OBJECT (s_ip4),
+ NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
+ NULL);
+
+ /* addr 1 */
+ addr = nm_ip_address_new (AF_INET, "1.2.3.4", 24, &error);
+ g_assert_no_error (error);
+ nm_ip_address_set_attribute (addr, "one", g_variant_new_string ("foo"));
+ nm_ip_address_set_attribute (addr, "two", g_variant_new_int32 (42));
+
+ nm_setting_ip_config_add_address (s_ip4, addr);
+ nm_ip_address_unref (addr);
+ nmtst_assert_setting_verifies (NM_SETTING (s_ip4));
+
+ /* addr 2 */
+ addr = nm_ip_address_new (AF_INET, "2.3.4.5", 24, &error);
+ g_assert_no_error (error);
+
+ nm_setting_ip_config_add_address (s_ip4, addr);
+ nm_ip_address_unref (addr);
+ nmtst_assert_setting_verifies (NM_SETTING (s_ip4));
+
+ /* The client-side D-Bus serialization should include the attributes in
+ * "address-data", and should not have an "addresses" property.
+ */
+ conn = nmtst_create_minimal_connection ("address-data test", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
+ nm_connection_add_setting (conn, NM_SETTING (s_ip4));
+ dict = nm_connection_to_dbus (conn, NM_CONNECTION_SERIALIZE_ALL);
+
+ setting_dict = g_variant_lookup_value (dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
+ g_assert (setting_dict != NULL);
+
+ value = g_variant_lookup_value (setting_dict, "addresses", NULL);
+ g_assert (value == NULL);
+
+ value = g_variant_lookup_value (setting_dict, "address-data", G_VARIANT_TYPE ("aa{sv}"));
+ addrs = nm_utils_ip_addresses_from_variant (value, AF_INET);
+ g_variant_unref (value);
+ g_assert (addrs != NULL);
+ g_assert_cmpint (addrs->len, ==, 2);
+
+ addr = addrs->pdata[0];
+ g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "1.2.3.4");
+ value = nm_ip_address_get_attribute (addr, "one");
+ g_assert (value != NULL);
+ g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "foo");
+ value = nm_ip_address_get_attribute (addr, "two");
+ g_assert (value != NULL);
+ g_assert_cmpint (g_variant_get_int32 (value), ==, 42);
+
+ g_ptr_array_unref (addrs);
+ g_variant_unref (setting_dict);
+ g_variant_unref (dict);
+
+ /* The daemon-side serialization should include both 'addresses' and 'address-data' */
+ _nm_utils_is_manager_process = TRUE;
+ dict = nm_connection_to_dbus (conn, NM_CONNECTION_SERIALIZE_ALL);
+ _nm_utils_is_manager_process = FALSE;
+
+ setting_dict = g_variant_lookup_value (dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
+ g_assert (setting_dict != NULL);
+
+ value = g_variant_lookup_value (setting_dict, "addresses", G_VARIANT_TYPE ("aau"));
+ g_assert (value != NULL);
+ g_variant_unref (value);
+
+ value = g_variant_lookup_value (setting_dict, "address-data", G_VARIANT_TYPE ("aa{sv}"));
+ g_assert (value != NULL);
+ g_variant_unref (value);
+
+ g_variant_unref (setting_dict);
+ g_object_unref (conn);
+
+ /* When we reserialize that dictionary as a client, 'address-data' will be preferred. */
+ conn = nm_simple_connection_new_from_dbus (dict, &error);
+ g_assert_no_error (error);
+
+ s_ip4 = nm_connection_get_setting_ip4_config (conn);
+
+ addr = nm_setting_ip_config_get_address (s_ip4, 0);
+ g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "1.2.3.4");
+ value = nm_ip_address_get_attribute (addr, "one");
+ g_assert (value != NULL);
+ g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "foo");
+ value = nm_ip_address_get_attribute (addr, "two");
+ g_assert (value != NULL);
+ g_assert_cmpint (g_variant_get_int32 (value), ==, 42);
+
+ /* But on the server side, 'addresses' will have precedence. */
+ _nm_utils_is_manager_process = TRUE;
+ conn = nm_simple_connection_new_from_dbus (dict, &error);
+ _nm_utils_is_manager_process = FALSE;
+ g_assert_no_error (error);
+ g_variant_unref (dict);
+
+ s_ip4 = nm_connection_get_setting_ip4_config (conn);
+
+ addr = nm_setting_ip_config_get_address (s_ip4, 0);
+ g_assert_cmpstr (nm_ip_address_get_address (addr), ==, "1.2.3.4");
+ value = nm_ip_address_get_attribute (addr, "one");
+ g_assert (value == NULL);
+ value = nm_ip_address_get_attribute (addr, "two");
+ g_assert (value == NULL);
+
+ g_object_unref (conn);
+}
+
+static void
+test_setting_gsm_apn_spaces (void)
+{
+ NMSettingGsm *s_gsm;
+ const char *tmp;
+
+ s_gsm = (NMSettingGsm *) nm_setting_gsm_new ();
+ ASSERT (s_gsm != NULL,
+ "gsm-apn-spaces",
+ "error creating GSM setting");
+
+ /* Trailing space */
+ g_object_set (s_gsm, NM_SETTING_GSM_APN, "foobar ", NULL);
+ tmp = nm_setting_gsm_get_apn (s_gsm);
+ ASSERT (tmp != NULL,
+ "gsm-apn-spaces", "empty APN");
+ ASSERT (strcmp (tmp, "foobar") == 0,
+ "gsm-apn-spaces", "unexpected APN");
+
+ /* Leading space */
+ g_object_set (s_gsm, NM_SETTING_GSM_APN, " foobar", NULL);
+ tmp = nm_setting_gsm_get_apn (s_gsm);
+ ASSERT (tmp != NULL,
+ "gsm-apn-spaces", "empty APN");
+ ASSERT (strcmp (tmp, "foobar") == 0,
+ "gsm-apn-spaces", "unexpected APN");
+}
+
+static void
+test_setting_gsm_apn_bad_chars (void)
+{
+ NMSettingGsm *s_gsm;
+
+ s_gsm = (NMSettingGsm *) nm_setting_gsm_new ();
+ ASSERT (s_gsm != NULL,
+ "gsm-apn-bad-chars",
+ "error creating GSM setting");
+
+ g_object_set (s_gsm, NM_SETTING_GSM_NUMBER, "*99#", NULL);
+
+ /* Make sure a valid APN works */
+ g_object_set (s_gsm, NM_SETTING_GSM_APN, "foobar123.-baz", NULL);
+ ASSERT (nm_setting_verify (NM_SETTING (s_gsm), NULL, NULL) == TRUE,
+ "gsm-apn-bad-chars", "unexpectedly invalid GSM setting");
+
+ /* Random invalid chars */
+ g_object_set (s_gsm, NM_SETTING_GSM_APN, "@#%$@#%@#%", NULL);
+ ASSERT (nm_setting_verify (NM_SETTING (s_gsm), NULL, NULL) == FALSE,
+ "gsm-apn-bad-chars", "unexpectedly valid GSM setting");
+
+ /* Spaces */
+ g_object_set (s_gsm, NM_SETTING_GSM_APN, "foobar baz", NULL);
+ ASSERT (nm_setting_verify (NM_SETTING (s_gsm), NULL, NULL) == FALSE,
+ "gsm-apn-bad-chars", "unexpectedly valid GSM setting");
+
+ /* 0 characters long */
+ g_object_set (s_gsm, NM_SETTING_GSM_APN, "", NULL);
+ ASSERT (nm_setting_verify (NM_SETTING (s_gsm), NULL, NULL) == FALSE,
+ "gsm-apn-bad-chars", "unexpectedly valid GSM setting");
+
+ /* 65-character long */
+ g_object_set (s_gsm, NM_SETTING_GSM_APN, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl1", NULL);
+ ASSERT (nm_setting_verify (NM_SETTING (s_gsm), NULL, NULL) == FALSE,
+ "gsm-apn-bad-chars", "unexpectedly valid GSM setting");
+}
+
+static void
+test_setting_gsm_apn_underscore (void)
+{
+ NMSettingGsm *s_gsm;
+
+ s_gsm = (NMSettingGsm *) nm_setting_gsm_new ();
+ g_assert (s_gsm);
+
+ g_object_set (s_gsm, NM_SETTING_GSM_NUMBER, "*99#", NULL);
+
+ /* 65-character long */
+ g_object_set (s_gsm, NM_SETTING_GSM_APN, "foobar_baz", NULL);
+ nmtst_assert_setting_verifies (NM_SETTING (s_gsm));
+}
+
+static void
+test_setting_gsm_without_number (void)
+{
+ NMSettingGsm *s_gsm;
+
+ s_gsm = (NMSettingGsm *) nm_setting_gsm_new ();
+ g_assert (s_gsm);
+
+ g_object_set (s_gsm, NM_SETTING_GSM_NUMBER, NULL, NULL);
+ nmtst_assert_setting_verifies (NM_SETTING (s_gsm));
+
+ g_object_set (s_gsm, NM_SETTING_GSM_NUMBER, "", NULL);
+ nmtst_assert_setting_verify_fails (NM_SETTING (s_gsm), NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_PROPERTY);
+}
+
+static NMSettingWirelessSecurity *
+make_test_wsec_setting (const char *detail)
+{
+ NMSettingWirelessSecurity *s_wsec;
+
+ s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+ ASSERT (s_wsec != NULL, detail, "error creating setting");
+
+ g_object_set (s_wsec,
+ NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk",
+ NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, "foobarbaz",
+ NM_SETTING_WIRELESS_SECURITY_PSK, "random psk",
+ NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS, NM_SETTING_SECRET_FLAG_NOT_SAVED,
+ NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, "aaaaaaaaaa",
+ NULL);
+
+ return s_wsec;
+}
+
+#define ASSERT_CONTAINS(vardict, key, test_name, msg) \
+ { \
+ GVariant *value; \
+ value = g_variant_lookup_value (vardict, key, NULL); \
+ ASSERT (value != NULL, test_name, msg); \
+ g_variant_unref (value); \
+ }
+
+#define ASSERT_NOT_CONTAINS(vardict, key, test_name, msg) \
+ { \
+ GVariant *value; \
+ value = g_variant_lookup_value (vardict, key, NULL); \
+ ASSERT (value == NULL, test_name, msg); \
+ }
+
+static void
+test_setting_to_dbus_all (void)
+{
+ NMSettingWirelessSecurity *s_wsec;
+ GVariant *dict;
+
+ s_wsec = make_test_wsec_setting ("setting-to-dbus-all");
+
+ dict = _nm_setting_to_dbus (NM_SETTING (s_wsec), NULL, NM_CONNECTION_SERIALIZE_ALL);
+
+ /* Make sure all keys are there */
+ ASSERT_CONTAINS (dict, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
+ "setting-to-dbus-all", "unexpectedly missing " NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
+ ASSERT_CONTAINS (dict, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME,
+ "setting-to-dbus-all", "unexpectedly missing " NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME);
+ ASSERT_CONTAINS (dict, NM_SETTING_WIRELESS_SECURITY_PSK,
+ "setting-to-dbus-all", "unexpectedly missing " NM_SETTING_WIRELESS_SECURITY_PSK);
+ ASSERT_CONTAINS (dict, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0,
+ "setting-to-dbus-all", "unexpectedly missing " NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
+
+ g_variant_unref (dict);
+ g_object_unref (s_wsec);
+}
+
+static void
+test_setting_to_dbus_no_secrets (void)
+{
+ NMSettingWirelessSecurity *s_wsec;
+ GVariant *dict;
+
+ s_wsec = make_test_wsec_setting ("setting-to-dbus-no-secrets");
+
+ dict = _nm_setting_to_dbus (NM_SETTING (s_wsec), NULL, NM_CONNECTION_SERIALIZE_NO_SECRETS);
+
+ /* Make sure non-secret keys are there */
+ ASSERT_CONTAINS (dict, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
+ "setting-to-dbus-no-secrets", "unexpectedly missing " NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
+ ASSERT_CONTAINS (dict, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME,
+ "setting-to-dbus-no-secrets", "unexpectedly missing " NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME);
+
+ /* Make sure secrets are not there */
+ ASSERT_NOT_CONTAINS (dict, NM_SETTING_WIRELESS_SECURITY_PSK,
+ "setting-to-dbus-no-secrets", "unexpectedly present " NM_SETTING_WIRELESS_SECURITY_PSK);
+ ASSERT_NOT_CONTAINS (dict, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0,
+ "setting-to-dbus-no-secrets", "unexpectedly present " NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
+
+ g_variant_unref (dict);
+ g_object_unref (s_wsec);
+}
+
+static void
+test_setting_to_dbus_only_secrets (void)
+{
+ NMSettingWirelessSecurity *s_wsec;
+ GVariant *dict;
+
+ s_wsec = make_test_wsec_setting ("setting-to-dbus-only-secrets");
+
+ dict = _nm_setting_to_dbus (NM_SETTING (s_wsec), NULL, NM_CONNECTION_SERIALIZE_ONLY_SECRETS);
+
+ /* Make sure non-secret keys are not there */
+ ASSERT_NOT_CONTAINS (dict, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
+ "setting-to-dbus-only-secrets", "unexpectedly present " NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
+ ASSERT_NOT_CONTAINS (dict, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME,
+ "setting-to-dbus-only-secrets", "unexpectedly present " NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME);
+
+ /* Make sure secrets are there */
+ ASSERT_CONTAINS (dict, NM_SETTING_WIRELESS_SECURITY_PSK,
+ "setting-to-dbus-only-secrets", "unexpectedly missing " NM_SETTING_WIRELESS_SECURITY_PSK);
+ ASSERT_CONTAINS (dict, NM_SETTING_WIRELESS_SECURITY_WEP_KEY0,
+ "setting-to-dbus-only-secrets", "unexpectedly missing " NM_SETTING_WIRELESS_SECURITY_WEP_KEY0);
+
+ g_variant_unref (dict);
+ g_object_unref (s_wsec);
+}
+
+static void
+test_setting_to_dbus_transform (void)
+{
+ NMSetting *s_wired;
+ GVariant *dict, *val;
+ const char *test_mac_address = "11:22:33:44:55:66";
+ const guint8 *dbus_mac_address;
+ guint8 cmp_mac_address[ETH_ALEN];
+ gsize len;
+
+ s_wired = nm_setting_wired_new ();
+ g_object_set (s_wired,
+ NM_SETTING_WIRED_MAC_ADDRESS, test_mac_address,
+ NULL);
+
+ g_assert_cmpstr (nm_setting_wired_get_mac_address (NM_SETTING_WIRED (s_wired)), ==, test_mac_address);
+
+ dict = _nm_setting_to_dbus (s_wired, NULL, NM_CONNECTION_SERIALIZE_ALL);
+ g_assert (dict != NULL);
+
+ val = g_variant_lookup_value (dict, NM_SETTING_WIRED_MAC_ADDRESS, G_VARIANT_TYPE_BYTESTRING);
+ g_assert (val != NULL);
+
+ dbus_mac_address = g_variant_get_fixed_array (val, &len, 1);
+ g_assert_cmpint (len, ==, ETH_ALEN);
+
+ nm_utils_hwaddr_aton (test_mac_address, cmp_mac_address, ETH_ALEN);
+ g_assert (memcmp (dbus_mac_address, cmp_mac_address, ETH_ALEN) == 0);
+
+ g_variant_unref (val);
+ g_variant_unref (dict);
+ g_object_unref (s_wired);
+}
+
+static void
+test_setting_to_dbus_enum (void)
+{
+ NMSetting *s_ip6, *s_wsec, *s_serial;
+ GVariant *dict, *val;
+
+ /* enum */
+ s_ip6 = nm_setting_ip6_config_new ();
+ g_object_set (s_ip6,
+ NM_SETTING_IP6_CONFIG_IP6_PRIVACY, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR,
+ NULL);
+
+ dict = _nm_setting_to_dbus (s_ip6, NULL, NM_CONNECTION_SERIALIZE_ALL);
+ g_assert (dict != NULL);
+
+ val = g_variant_lookup_value (dict, NM_SETTING_IP6_CONFIG_IP6_PRIVACY, G_VARIANT_TYPE_INT32);
+ g_assert (val != NULL);
+ g_assert_cmpint (g_variant_get_int32 (val), ==, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR);
+ g_variant_unref (val);
+
+ g_variant_unref (dict);
+ g_object_unref (s_ip6);
+
+ /* flags (and a transformed enum) */
+ s_wsec = nm_setting_wireless_security_new ();
+ g_object_set (s_wsec,
+ NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, NM_WEP_KEY_TYPE_KEY,
+ NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, (NM_SETTING_SECRET_FLAG_AGENT_OWNED |
+ NM_SETTING_SECRET_FLAG_NOT_SAVED),
+ NULL);
+
+ dict = _nm_setting_to_dbus (s_wsec, NULL, NM_CONNECTION_SERIALIZE_ALL);
+ g_assert (dict != NULL);
+
+ val = g_variant_lookup_value (dict, NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, G_VARIANT_TYPE_UINT32);
+ g_assert (val != NULL);
+ g_assert_cmpint (g_variant_get_uint32 (val), ==, NM_WEP_KEY_TYPE_KEY);
+ g_variant_unref (val);
+
+ val = g_variant_lookup_value (dict, NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, G_VARIANT_TYPE_UINT32);
+ g_assert (val != NULL);
+ g_assert_cmpint (g_variant_get_uint32 (val), ==, (NM_SETTING_SECRET_FLAG_AGENT_OWNED |
+ NM_SETTING_SECRET_FLAG_NOT_SAVED));
+ g_variant_unref (val);
+
+ g_variant_unref (dict);
+ g_object_unref (s_wsec);
+
+ /* another transformed enum */
+ s_serial = nm_setting_serial_new ();
+ g_object_set (s_serial,
+ NM_SETTING_SERIAL_PARITY, NM_SETTING_SERIAL_PARITY_ODD,
+ NULL);
+
+ dict = _nm_setting_to_dbus (s_serial, NULL, NM_CONNECTION_SERIALIZE_ALL);
+ g_assert (dict != NULL);
+
+ val = g_variant_lookup_value (dict, NM_SETTING_SERIAL_PARITY, G_VARIANT_TYPE_BYTE);
+ g_assert (val != NULL);
+ g_assert_cmpint (g_variant_get_byte (val), ==, 'o');
+ g_variant_unref (val);
+
+ g_variant_unref (dict);
+ g_object_unref (s_serial);
+}
+
+static void
+test_connection_to_dbus_setting_name (void)
+{
+ NMConnection *connection;
+ NMSettingWirelessSecurity *s_wsec;
+ GVariant *dict;
+
+ connection = nm_simple_connection_new ();
+ s_wsec = make_test_wsec_setting ("connection-to-dbus-setting-name");
+ nm_connection_add_setting (connection, NM_SETTING (s_wsec));
+
+ dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL);
+
+ /* Make sure the keys of the first level dict are setting names, not
+ * the GType name of the setting objects.
+ */
+ ASSERT_CONTAINS (dict, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+ "connection-to-dbus-setting-name", "unexpectedly missing " NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
+
+ g_variant_unref (dict);
+ g_object_unref (connection);
+}
+
+static void
+test_connection_to_dbus_deprecated_props (void)
+{
+ NMConnection *connection;
+ NMSetting *s_wireless;
+ GBytes *ssid;
+ NMSettingWirelessSecurity *s_wsec;
+ GVariant *dict, *wireless_dict, *sec_val;
+
+ connection = nmtst_create_minimal_connection ("test-connection-to-dbus-deprecated-props",
+ NULL,
+ NM_SETTING_WIRELESS_SETTING_NAME,
+ NULL);
+
+ s_wireless = nm_setting_wireless_new ();
+ ssid = g_bytes_new ("1234567", 7);
+ g_object_set (s_wireless,
+ NM_SETTING_WIRELESS_SSID, ssid,
+ NULL);
+ g_bytes_unref (ssid);
+ nm_connection_add_setting (connection, s_wireless);
+
+ /* Serialization should not have an 802-11-wireless.security property */
+ dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL);
+ g_assert (dict != NULL);
+
+ wireless_dict = g_variant_lookup_value (dict, NM_SETTING_WIRELESS_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
+ g_assert (wireless_dict != NULL);
+
+ sec_val = g_variant_lookup_value (wireless_dict, "security", NULL);
+ g_assert (sec_val == NULL);
+
+ g_variant_unref (wireless_dict);
+ g_variant_unref (dict);
+
+ /* Now add an NMSettingWirelessSecurity and try again */
+ s_wsec = make_test_wsec_setting ("test-connection-to-dbus-deprecated-props");
+ nm_connection_add_setting (connection, NM_SETTING (s_wsec));
+
+ dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL);
+ g_assert (dict != NULL);
+
+ wireless_dict = g_variant_lookup_value (dict, NM_SETTING_WIRELESS_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
+ g_assert (wireless_dict != NULL);
+
+ sec_val = g_variant_lookup_value (wireless_dict, "security", NULL);
+ g_assert (g_variant_is_of_type (sec_val, G_VARIANT_TYPE_STRING));
+ g_assert_cmpstr (g_variant_get_string (sec_val, NULL), ==, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
+
+ g_variant_unref (sec_val);
+ g_variant_unref (wireless_dict);
+ g_variant_unref (dict);
+ g_object_unref (connection);
+}
+
+static void
+test_setting_new_from_dbus (void)
+{
+ NMSettingWirelessSecurity *s_wsec;
+ GVariant *dict;
+
+ s_wsec = make_test_wsec_setting ("setting-new-from-dbus");
+ dict = _nm_setting_to_dbus (NM_SETTING (s_wsec), NULL, NM_CONNECTION_SERIALIZE_ALL);
+ g_object_unref (s_wsec);
+
+ s_wsec = (NMSettingWirelessSecurity *) _nm_setting_new_from_dbus (NM_TYPE_SETTING_WIRELESS_SECURITY, dict, NULL, NULL);
+ g_variant_unref (dict);
+
+ g_assert (s_wsec);
+ g_assert_cmpstr (nm_setting_wireless_security_get_key_mgmt (s_wsec), ==, "wpa-psk");
+ g_assert_cmpstr (nm_setting_wireless_security_get_leap_username (s_wsec), ==, "foobarbaz");
+ g_assert_cmpstr (nm_setting_wireless_security_get_psk (s_wsec), ==, "random psk");
+ g_object_unref (s_wsec);
+}
+
+static void
+test_setting_new_from_dbus_transform (void)
+{
+ NMSetting *s_wired;
+ GVariant *dict;
+ GVariantBuilder builder;
+ const char *test_mac_address = "11:22:33:44:55:66";
+ guint8 dbus_mac_address[ETH_ALEN];
+ GError *error = NULL;
+
+ nm_utils_hwaddr_aton (test_mac_address, dbus_mac_address, ETH_ALEN);
+
+ g_variant_builder_init (&builder, NM_VARIANT_TYPE_SETTING);
+ g_variant_builder_add (&builder, "{sv}",
+ NM_SETTING_WIRED_MAC_ADDRESS,
+ g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+ dbus_mac_address, ETH_ALEN, 1));
+ dict = g_variant_builder_end (&builder);
+
+ s_wired = _nm_setting_new_from_dbus (NM_TYPE_SETTING_WIRED, dict, NULL, &error);
+ g_assert_no_error (error);
+
+ g_assert_cmpstr (nm_setting_wired_get_mac_address (NM_SETTING_WIRED (s_wired)), ==, test_mac_address);
+
+ g_variant_unref (dict);
+ g_object_unref (s_wired);
+}
+
+static void
+test_setting_new_from_dbus_enum (void)
+{
+ NMSettingIP6Config *s_ip6;
+ NMSettingWirelessSecurity *s_wsec;
+ NMSettingSerial *s_serial;
+ GVariant *dict;
+ GVariantBuilder builder;
+ GError *error = NULL;
+
+ /* enum */
+ g_variant_builder_init (&builder, NM_VARIANT_TYPE_SETTING);
+ g_variant_builder_add (&builder, "{sv}",
+ NM_SETTING_IP6_CONFIG_IP6_PRIVACY,
+ g_variant_new_int32 (NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR));
+ dict = g_variant_builder_end (&builder);
+
+ s_ip6 = (NMSettingIP6Config *) _nm_setting_new_from_dbus (NM_TYPE_SETTING_IP6_CONFIG, dict, NULL, &error);
+ g_assert_no_error (error);
+
+ g_assert_cmpint (nm_setting_ip6_config_get_ip6_privacy (s_ip6), ==, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR);
+
+ g_variant_unref (dict);
+ g_object_unref (s_ip6);
+
+ /* flags (and a transformed enum) */
+ g_variant_builder_init (&builder, NM_VARIANT_TYPE_SETTING);
+ g_variant_builder_add (&builder, "{sv}",
+ NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE,
+ g_variant_new_uint32 (NM_WEP_KEY_TYPE_KEY));
+ g_variant_builder_add (&builder, "{sv}",
+ NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS,
+ g_variant_new_uint32 (NM_SETTING_SECRET_FLAG_AGENT_OWNED |
+ NM_SETTING_SECRET_FLAG_NOT_SAVED));
+ dict = g_variant_builder_end (&builder);
+
+ s_wsec = (NMSettingWirelessSecurity *) _nm_setting_new_from_dbus (NM_TYPE_SETTING_WIRELESS_SECURITY, dict, NULL, &error);
+ g_assert_no_error (error);
+
+ g_assert_cmpint (nm_setting_wireless_security_get_wep_key_type (s_wsec), ==, NM_WEP_KEY_TYPE_KEY);
+ g_assert_cmpint (nm_setting_wireless_security_get_wep_key_flags (s_wsec), ==, (NM_SETTING_SECRET_FLAG_AGENT_OWNED |
+ NM_SETTING_SECRET_FLAG_NOT_SAVED));
+
+ g_variant_unref (dict);
+ g_object_unref (s_wsec);
+
+ /* another transformed enum */
+ g_variant_builder_init (&builder, NM_VARIANT_TYPE_SETTING);
+ g_variant_builder_add (&builder, "{sv}",
+ NM_SETTING_SERIAL_PARITY,
+ g_variant_new_byte ('E'));
+ dict = g_variant_builder_end (&builder);
+
+ s_serial = (NMSettingSerial *) _nm_setting_new_from_dbus (NM_TYPE_SETTING_SERIAL, dict, NULL, &error);
+ g_assert_no_error (error);
+
+ g_assert_cmpint (nm_setting_serial_get_parity (s_serial), ==, NM_SETTING_SERIAL_PARITY_EVEN);
+
+ g_variant_unref (dict);
+ g_object_unref (s_serial);
+}
+
+static NMConnection *
+new_test_connection (void)
+{
+ NMConnection *connection;
+ NMSetting *setting;
+ char *uuid;
+ guint64 timestamp = time (NULL);
+
+ connection = nm_simple_connection_new ();
+
+ setting = nm_setting_connection_new ();
+ uuid = nm_utils_uuid_generate ();
+ g_object_set (G_OBJECT (setting),
+ NM_SETTING_CONNECTION_ID, "foobar",
+ NM_SETTING_CONNECTION_UUID, uuid,
+ NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
+ NM_SETTING_CONNECTION_TIMESTAMP, timestamp,
+ NULL);
+ g_free (uuid);
+ nm_connection_add_setting (connection, setting);
+
+ setting = nm_setting_wired_new ();
+ g_object_set (G_OBJECT (setting),
+ NM_SETTING_WIRED_MTU, 1592,
+ NULL);
+ nm_connection_add_setting (connection, setting);
+
+ setting = nm_setting_ip4_config_new ();
+ g_object_set (G_OBJECT (setting),
+ NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
+ NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, "eyeofthetiger",
+ NULL);
+ nm_connection_add_setting (connection, setting);
+
+ return connection;
+}
+
+static GVariant *
+new_connection_dict (char **out_uuid,
+ const char **out_expected_id,
+ const char **out_expected_ip6_method)
+{
+ GVariantBuilder conn_builder, setting_builder;
+
+ g_variant_builder_init (&conn_builder, NM_VARIANT_TYPE_CONNECTION);
+
+ *out_uuid = nm_utils_uuid_generate ();
+ *out_expected_id = "My happy connection";
+ *out_expected_ip6_method = NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL;
+
+ /* Connection setting */
+ g_variant_builder_init (&setting_builder, NM_VARIANT_TYPE_SETTING);
+ g_variant_builder_add (&setting_builder, "{sv}",
+ NM_SETTING_NAME,
+ g_variant_new_string (NM_SETTING_CONNECTION_SETTING_NAME));
+ g_variant_builder_add (&setting_builder, "{sv}",
+ NM_SETTING_CONNECTION_ID,
+ g_variant_new_string (*out_expected_id));
+ g_variant_builder_add (&setting_builder, "{sv}",
+ NM_SETTING_CONNECTION_UUID,
+ g_variant_new_string (*out_uuid));
+ g_variant_builder_add (&setting_builder, "{sv}",
+ NM_SETTING_CONNECTION_TYPE,
+ g_variant_new_string (NM_SETTING_WIRED_SETTING_NAME));
+
+ g_variant_builder_add (&conn_builder, "{sa{sv}}",
+ NM_SETTING_CONNECTION_SETTING_NAME,
+ &setting_builder);
+
+ /* Wired setting */
+ g_variant_builder_init (&setting_builder, NM_VARIANT_TYPE_SETTING);
+ g_variant_builder_add (&conn_builder, "{sa{sv}}",
+ NM_SETTING_WIRED_SETTING_NAME,
+ &setting_builder);
+
+ /* IP6 */
+ g_variant_builder_init (&setting_builder, NM_VARIANT_TYPE_SETTING);
+ g_variant_builder_add (&setting_builder, "{sv}",
+ NM_SETTING_IP_CONFIG_METHOD,
+ g_variant_new_string (*out_expected_ip6_method));
+ g_variant_builder_add (&conn_builder, "{sa{sv}}",
+ NM_SETTING_IP6_CONFIG_SETTING_NAME,
+ &setting_builder);
+
+ return g_variant_builder_end (&conn_builder);
+}
+
+static void
+test_connection_replace_settings (void)
+{
+ NMConnection *connection;
+ GVariant *new_settings;
+ GError *error = NULL;
+ gboolean success;
+ NMSettingConnection *s_con;
+ NMSettingIPConfig *s_ip6;
+ char *uuid = NULL;
+ const char *expected_id = NULL, *expected_method = NULL;
+
+ connection = new_test_connection ();
+
+ new_settings = new_connection_dict (&uuid, &expected_id, &expected_method);
+ g_assert (new_settings);
+
+ /* Replace settings and test */
+ success = nm_connection_replace_settings (connection, new_settings, &error);
+ g_assert_no_error (error);
+ g_assert (success);
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
+ g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
+ g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, uuid);
+
+ g_assert (nm_connection_get_setting_wired (connection));
+ g_assert (!nm_connection_get_setting_ip4_config (connection));
+
+ s_ip6 = nm_connection_get_setting_ip6_config (connection);
+ g_assert (s_ip6);
+ g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, expected_method);
+
+ g_free (uuid);
+ g_variant_unref (new_settings);
+ g_object_unref (connection);
+}
+
+static void
+test_connection_replace_settings_from_connection (void)
+{
+ NMConnection *connection, *replacement;
+ NMSettingConnection *s_con;
+ NMSetting *setting;
+ GBytes *ssid;
+ char *uuid = NULL;
+ const char *expected_id = "Awesome connection";
+
+ connection = new_test_connection ();
+ g_assert (connection);
+
+ replacement = nm_simple_connection_new ();
+ g_assert (replacement);
+
+ /* New connection setting */
+ setting = nm_setting_connection_new ();
+ g_assert (setting);
+
+ uuid = nm_utils_uuid_generate ();
+ g_object_set (setting,
+ NM_SETTING_CONNECTION_ID, expected_id,
+ NM_SETTING_CONNECTION_UUID, uuid,
+ NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME,
+ NULL);
+ nm_connection_add_setting (replacement, setting);
+
+ /* New wifi setting */
+ setting = nm_setting_wireless_new ();
+ g_assert (setting);
+
+ ssid = g_bytes_new ("1234567", 7);
+ g_object_set (setting,
+ NM_SETTING_WIRELESS_SSID, ssid,
+ NM_SETTING_WIRELESS_MODE, "infrastructure",
+ NULL);
+ g_bytes_unref (ssid);
+ nm_connection_add_setting (replacement, setting);
+
+ /* Replace settings and test */
+ nm_connection_replace_settings_from_connection (connection, replacement);
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
+ g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
+ g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, uuid);
+
+ g_assert (!nm_connection_get_setting_wired (connection));
+ g_assert (!nm_connection_get_setting_ip6_config (connection));
+ g_assert (nm_connection_get_setting_wireless (connection));
+
+ g_free (uuid);
+ g_object_unref (replacement);
+ g_object_unref (connection);
+}
+
+static void
+test_connection_replace_settings_bad (void)
+{
+ NMConnection *connection, *new_connection;
+ GVariant *new_settings;
+ GVariantBuilder builder, setting_builder;
+ GError *error = NULL;
+ gboolean success;
+ NMSettingConnection *s_con;
+
+ new_connection = new_test_connection ();
+ g_assert (nm_connection_verify (new_connection, NULL));
+ s_con = nm_connection_get_setting_connection (new_connection);
+ g_object_set (s_con,
+ NM_SETTING_CONNECTION_UUID, NULL,
+ NM_SETTING_CONNECTION_ID, "bad-connection",
+ NULL);
+ g_assert (!nm_connection_verify (new_connection, NULL));
+
+ /* nm_connection_replace_settings_from_connection() should succeed */
+ connection = new_test_connection ();
+ nm_connection_replace_settings_from_connection (connection, new_connection);
+ g_assert_cmpstr (nm_connection_get_id (connection), ==, "bad-connection");
+ g_assert (!nm_connection_verify (connection, NULL));
+ g_object_unref (connection);
+
+ /* nm_connection_replace_settings() should succeed */
+ new_settings = nm_connection_to_dbus (new_connection, NM_CONNECTION_SERIALIZE_ALL);
+ g_assert (new_settings != NULL);
+
+ connection = new_test_connection ();
+ success = nm_connection_replace_settings (connection, new_settings, &error);
+ g_assert_no_error (error);
+ g_assert (success);
+
+ g_assert_cmpstr (nm_connection_get_id (connection), ==, "bad-connection");
+ g_assert (!nm_connection_verify (connection, NULL));
+ g_object_unref (connection);
+ g_variant_unref (new_settings);
+
+ /* But given an invalid dict, it should fail */
+ g_variant_builder_init (&builder, NM_VARIANT_TYPE_CONNECTION);
+ g_variant_builder_init (&setting_builder, NM_VARIANT_TYPE_SETTING);
+ g_variant_builder_add (&builder, "{sa{sv}}",
+ "ip-over-avian-carrier",
+ &setting_builder);
+ new_settings = g_variant_builder_end (&builder);
+
+ connection = new_test_connection ();
+ success = nm_connection_replace_settings (connection, new_settings, &error);
+ g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING);
+ g_assert (!success);
+
+ g_assert (nm_connection_verify (connection, NULL));
+ g_object_unref (connection);
+
+ g_variant_unref (new_settings);
+ g_object_unref (new_connection);
+}
+
+static void
+test_connection_new_from_dbus (void)
+{
+ NMConnection *connection;
+ GVariant *new_settings;
+ GError *error = NULL;
+ NMSettingConnection *s_con;
+ NMSettingIPConfig *s_ip6;
+ char *uuid = NULL;
+ const char *expected_id = NULL, *expected_method = NULL;
+
+ new_settings = new_connection_dict (&uuid, &expected_id, &expected_method);
+ g_assert (new_settings);
+
+ /* Replace settings and test */
+ connection = nm_simple_connection_new_from_dbus (new_settings, &error);
+ g_assert_no_error (error);
+ g_assert (connection);
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
+ g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
+ g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, uuid);
+
+ g_assert (nm_connection_get_setting_wired (connection));
+ g_assert (nm_connection_get_setting_ip4_config (connection));
+
+ s_ip6 = nm_connection_get_setting_ip6_config (connection);
+ g_assert (s_ip6);
+ g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, expected_method);
+
+ g_free (uuid);
+ g_variant_unref (new_settings);
+ g_object_unref (connection);
+}
+
+static void
+check_permission (NMSettingConnection *s_con,
+ guint32 idx,
+ const char *expected_uname,
+ const char *tag)
+{
+ gboolean success;
+ const char *ptype = NULL, *pitem = NULL, *detail = NULL;
+
+ success = nm_setting_connection_get_permission (s_con, 0, &ptype, &pitem, &detail);
+ ASSERT (success == TRUE, tag, "unexpected failure getting added permission");
+
+ /* Permission type */
+ ASSERT (ptype != NULL, tag, "unexpected failure getting permission type");
+ ASSERT (strcmp (ptype, "user") == 0, tag, "retrieved unexpected permission type");
+
+ /* Permission item */
+ ASSERT (pitem != NULL, tag, "unexpected failure getting permission item");
+ ASSERT (strcmp (pitem, expected_uname) == 0, tag, "retrieved unexpected permission item");
+
+ ASSERT (detail == NULL, tag, "unexpected success getting permission detail");
+}
+
+#define TEST_UNAME "asdfasfasdf"
+
+static void
+test_setting_connection_permissions_helpers (void)
+{
+ NMSettingConnection *s_con;
+ gboolean success;
+ char buf[9] = { 0x61, 0x62, 0x63, 0xff, 0xfe, 0xfd, 0x23, 0x01, 0x00 };
+ char **perms;
+ const char *expected_perm = "user:" TEST_UNAME ":";
+
+ s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
+
+ /* Ensure a bad [type] is rejected */
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*strcmp (ptype, \"user\") == 0*");
+ success = nm_setting_connection_add_permission (s_con, "foobar", "blah", NULL);
+ g_test_assert_expected_messages ();
+ ASSERT (success == FALSE,
+ "setting-connection-permissions-helpers", "unexpected success adding bad permission type #1");
+
+ /* Ensure a bad [type] is rejected */
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*ptype*");
+ success = nm_setting_connection_add_permission (s_con, NULL, "blah", NULL);
+ g_test_assert_expected_messages ();
+ ASSERT (success == FALSE,
+ "setting-connection-permissions-helpers", "unexpected success adding bad permission type #2");
+
+ /* Ensure a bad [item] is rejected */
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*uname*");
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*p != NULL*");
+ success = nm_setting_connection_add_permission (s_con, "user", NULL, NULL);
+ g_test_assert_expected_messages ();
+ ASSERT (success == FALSE,
+ "setting-connection-permissions-helpers", "unexpected success adding bad permission item #1");
+
+ /* Ensure a bad [item] is rejected */
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*uname[0] != '\\0'*");
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*p != NULL*");
+ success = nm_setting_connection_add_permission (s_con, "user", "", NULL);
+ g_test_assert_expected_messages ();
+ ASSERT (success == FALSE,
+ "setting-connection-permissions-helpers", "unexpected success adding bad permission item #2");
+
+ /* Ensure an [item] with ':' is rejected */
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*strchr (uname, ':')*");
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*p != NULL*");
+ success = nm_setting_connection_add_permission (s_con, "user", "ad:asdf", NULL);
+ g_test_assert_expected_messages ();
+ ASSERT (success == FALSE,
+ "setting-connection-permissions-helpers", "unexpected success adding bad permission item #3");
+
+ /* Ensure a non-UTF-8 [item] is rejected */
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*g_utf8_validate (uname, -1, NULL)*");
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*p != NULL*");
+ success = nm_setting_connection_add_permission (s_con, "user", buf, NULL);
+ g_test_assert_expected_messages ();
+ ASSERT (success == FALSE,
+ "setting-connection-permissions-helpers", "unexpected success adding bad permission item #4");
+
+ /* Ensure a non-NULL [detail] is rejected */
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*detail == NULL*");
+ success = nm_setting_connection_add_permission (s_con, "user", "dafasdf", "asdf");
+ g_test_assert_expected_messages ();
+ ASSERT (success == FALSE,
+ "setting-connection-permissions-helpers", "unexpected success adding bad detail");
+
+ /* Ensure a valid call results in success */
+ success = nm_setting_connection_add_permission (s_con, "user", TEST_UNAME, NULL);
+ ASSERT (success == TRUE,
+ "setting-connection-permissions-helpers", "unexpected failure adding valid user permisson");
+
+ ASSERT (nm_setting_connection_get_num_permissions (s_con) == 1,
+ "setting-connection-permissions-helpers", "unexpected failure getting number of permissions");
+
+ check_permission (s_con, 0, TEST_UNAME, "setting-connection-permissions-helpers");
+
+ /* Check the actual GObject property just to be paranoid */
+ g_object_get (G_OBJECT (s_con), NM_SETTING_CONNECTION_PERMISSIONS, &perms, NULL);
+ ASSERT (perms != NULL,
+ "setting-connection-permissions-helpers", "unexpected failure getting permissions");
+ ASSERT (g_strv_length (perms) == 1,
+ "setting-connection-permissions-helpers", "unexpected failure getting number of permissions");
+ ASSERT (strcmp (perms[0], expected_perm) == 0,
+ "setting-connection-permissions-helpers", "unexpected permission property data");
+ g_strfreev (perms);
+
+ /* Now remove that permission and ensure we have 0 permissions */
+ nm_setting_connection_remove_permission (s_con, 0);
+ ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
+ "setting-connection-permissions-helpers", "unexpected failure removing permission");
+
+ g_object_unref (s_con);
+}
+
+static void
+add_permission_property (NMSettingConnection *s_con,
+ const char *ptype,
+ const char *pitem,
+ int pitem_len,
+ const char *detail)
+{
+ GString *str;
+ char *perms[2];
+
+ str = g_string_sized_new (50);
+ if (ptype)
+ g_string_append (str, ptype);
+ g_string_append_c (str, ':');
+
+ if (pitem) {
+ if (pitem_len >= 0)
+ g_string_append_len (str, pitem, pitem_len);
+ else
+ g_string_append (str, pitem);
+ }
+
+ g_string_append_c (str, ':');
+
+ if (detail)
+ g_string_append (str, detail);
+
+ perms[0] = str->str;
+ perms[1] = NULL;
+ g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_PERMISSIONS, perms, NULL);
+
+ g_string_free (str, TRUE);
+}
+
+static void
+test_setting_connection_permissions_property (void)
+{
+ NMSettingConnection *s_con;
+ gboolean success;
+ char buf[9] = { 0x61, 0x62, 0x63, 0xff, 0xfe, 0xfd, 0x23, 0x01, 0x00 };
+
+ s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
+
+ /* Ensure a bad [type] is rejected */
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*strncmp (str, PERM_USER_PREFIX, strlen (PERM_USER_PREFIX)) == 0*");
+ add_permission_property (s_con, "foobar", "blah", -1, NULL);
+ g_test_assert_expected_messages ();
+ ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
+ "setting-connection-permissions-property", "unexpected success adding bad permission type #1");
+
+ /* Ensure a bad [type] is rejected */
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*strncmp (str, PERM_USER_PREFIX, strlen (PERM_USER_PREFIX)) == 0*");
+ add_permission_property (s_con, NULL, "blah", -1, NULL);
+ g_test_assert_expected_messages ();
+ ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
+ "setting-connection-permissions-property", "unexpected success adding bad permission type #2");
+
+ /* Ensure a bad [item] is rejected */
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*last_colon > str*");
+ add_permission_property (s_con, "user", NULL, -1, NULL);
+ g_test_assert_expected_messages ();
+ ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
+ "setting-connection-permissions-property", "unexpected success adding bad permission item #1");
+
+ /* Ensure a bad [item] is rejected */
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*last_colon > str*");
+ add_permission_property (s_con, "user", "", -1, NULL);
+ g_test_assert_expected_messages ();
+ ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
+ "setting-connection-permissions-property", "unexpected success adding bad permission item #2");
+
+ /* Ensure an [item] with ':' in the middle is rejected */
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*str[i] != ':'*");
+ add_permission_property (s_con, "user", "ad:asdf", -1, NULL);
+ g_test_assert_expected_messages ();
+ ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
+ "setting-connection-permissions-property", "unexpected success adding bad permission item #3");
+
+ /* Ensure an [item] with ':' at the end is rejected */
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*str[i] != ':'*");
+ add_permission_property (s_con, "user", "adasdfaf:", -1, NULL);
+ g_test_assert_expected_messages ();
+ ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
+ "setting-connection-permissions-property", "unexpected success adding bad permission item #4");
+
+ /* Ensure a non-UTF-8 [item] is rejected */
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*g_utf8_validate (str, -1, NULL)*");
+ add_permission_property (s_con, "user", buf, (int) sizeof (buf), NULL);
+ g_test_assert_expected_messages ();
+ ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
+ "setting-connection-permissions-property", "unexpected success adding bad permission item #5");
+
+ /* Ensure a non-NULL [detail] is rejected */
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*(last_colon + 1) == '\\0'*");
+ add_permission_property (s_con, "user", "dafasdf", -1, "asdf");
+ g_test_assert_expected_messages ();
+ ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
+ "setting-connection-permissions-property", "unexpected success adding bad detail");
+
+ /* Ensure a valid call results in success */
+ success = nm_setting_connection_add_permission (s_con, "user", TEST_UNAME, NULL);
+ ASSERT (nm_setting_connection_get_num_permissions (s_con) == 1,
+ "setting-connection-permissions-property", "unexpected failure adding valid user permisson");
+
+ check_permission (s_con, 0, TEST_UNAME, "setting-connection-permissions-property");
+
+ /* Now remove that permission and ensure we have 0 permissions */
+ nm_setting_connection_remove_permission (s_con, 0);
+ ASSERT (nm_setting_connection_get_num_permissions (s_con) == 0,
+ "setting-connection-permissions-property", "unexpected failure removing permission");
+
+ g_object_unref (s_con);
+}
+
+static void
+test_connection_compare_same (void)
+{
+ NMConnection *a, *b;
+
+ a = new_test_connection ();
+ b = nm_simple_connection_new_clone (a);
+ g_assert (nm_connection_compare (a, b, NM_SETTING_COMPARE_FLAG_EXACT));
+ g_object_unref (a);
+ g_object_unref (b);
+}
+
+static void
+test_connection_compare_key_only_in_a (void)
+{
+ NMConnection *a, *b;
+ NMSettingConnection *s_con;
+
+ a = new_test_connection ();
+ b = nm_simple_connection_new_clone (a);
+ s_con = (NMSettingConnection *) nm_connection_get_setting (b, NM_TYPE_SETTING_CONNECTION);
+ g_assert (s_con);
+ g_object_set (s_con, NM_SETTING_CONNECTION_TIMESTAMP, (guint64) 0, NULL);
+
+ g_assert (!nm_connection_compare (a, b, NM_SETTING_COMPARE_FLAG_EXACT));
+ g_object_unref (a);
+ g_object_unref (b);
+}
+
+static void
+test_connection_compare_setting_only_in_a (void)
+{
+ NMConnection *a, *b;
+
+ a = new_test_connection ();
+ b = nm_simple_connection_new_clone (a);
+ nm_connection_remove_setting (b, NM_TYPE_SETTING_IP4_CONFIG);
+ g_assert (!nm_connection_compare (a, b, NM_SETTING_COMPARE_FLAG_EXACT));
+ g_object_unref (a);
+ g_object_unref (b);
+}
+
+static void
+test_connection_compare_key_only_in_b (void)
+{
+ NMConnection *a, *b;
+ NMSettingConnection *s_con;
+
+ a = new_test_connection ();
+ b = nm_simple_connection_new_clone (a);
+ s_con = (NMSettingConnection *) nm_connection_get_setting (b, NM_TYPE_SETTING_CONNECTION);
+ g_assert (s_con);
+ g_object_set (s_con, NM_SETTING_CONNECTION_TIMESTAMP, (guint64) 0, NULL);
+
+ g_assert (!nm_connection_compare (a, b, NM_SETTING_COMPARE_FLAG_EXACT));
+ g_object_unref (a);
+ g_object_unref (b);
+}
+
+static void
+test_connection_compare_setting_only_in_b (void)
+{
+ NMConnection *a, *b;
+
+ a = new_test_connection ();
+ b = nm_simple_connection_new_clone (a);
+ nm_connection_remove_setting (a, NM_TYPE_SETTING_IP4_CONFIG);
+ g_assert (!nm_connection_compare (a, b, NM_SETTING_COMPARE_FLAG_EXACT));
+ g_object_unref (a);
+ g_object_unref (b);
+}
+
+typedef struct {
+ const char *key_name;
+ guint32 result;
+} DiffKey;
+
+typedef struct {
+ const char *name;
+ DiffKey keys[30];
+} DiffSetting;
+
+#define ARRAY_LEN(a) (sizeof (a) / sizeof (a[0]))
+
+static void
+ensure_diffs (GHashTable *diffs, const DiffSetting *check, gsize n_check)
+{
+ guint i;
+
+ g_assert (g_hash_table_size (diffs) == n_check);
+
+ /* Loop through the settings */
+ for (i = 0; i < n_check; i++) {
+ GHashTable *setting_hash;
+ guint z = 0;
+
+ setting_hash = g_hash_table_lookup (diffs, check[i].name);
+ g_assert (setting_hash);
+
+ /* Get the number of keys to check */
+ while (check[i].keys[z].key_name)
+ z++;
+ g_assert (g_hash_table_size (setting_hash) == z);
+
+ /* Now compare the actual keys */
+ for (z = 0; check[i].keys[z].key_name; z++) {
+ NMSettingDiffResult result;
+
+ result = GPOINTER_TO_UINT (g_hash_table_lookup (setting_hash, check[i].keys[z].key_name));
+ g_assert (result == check[i].keys[z].result);
+ }
+ }
+}
+
+static void
+test_connection_diff_a_only (void)
+{
+ NMConnection *connection;
+ GHashTable *out_diffs = NULL;
+ gboolean same;
+ const DiffSetting settings[] = {
+ { NM_SETTING_CONNECTION_SETTING_NAME, {
+ { NM_SETTING_CONNECTION_ID, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_CONNECTION_UUID, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_CONNECTION_INTERFACE_NAME, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_CONNECTION_TYPE, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_CONNECTION_TIMESTAMP, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_CONNECTION_AUTOCONNECT, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, 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 },
+ { NM_SETTING_CONNECTION_MASTER, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_CONNECTION_SLAVE_TYPE, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_CONNECTION_SECONDARIES, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, NM_SETTING_DIFF_RESULT_IN_A },
+ { NULL, NM_SETTING_DIFF_RESULT_UNKNOWN }
+ } },
+ { NM_SETTING_WIRED_SETTING_NAME, {
+ { NM_SETTING_WIRED_PORT, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_WIRED_SPEED, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_WIRED_DUPLEX, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_WIRED_AUTO_NEGOTIATE, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_WIRED_MAC_ADDRESS, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_WIRED_CLONED_MAC_ADDRESS, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_WIRED_MTU, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_WIRED_S390_SUBCHANNELS, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_WIRED_S390_NETTYPE, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_WIRED_S390_OPTIONS, NM_SETTING_DIFF_RESULT_IN_A },
+ { NULL, NM_SETTING_DIFF_RESULT_UNKNOWN },
+ } },
+ { NM_SETTING_IP4_CONFIG_SETTING_NAME, {
+ { NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_IP_CONFIG_DNS, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_IP_CONFIG_DNS_SEARCH, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_IP_CONFIG_ADDRESSES, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_IP_CONFIG_GATEWAY, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_IP_CONFIG_ROUTES, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_IP_CONFIG_ROUTE_METRIC, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_IP_CONFIG_NEVER_DEFAULT, NM_SETTING_DIFF_RESULT_IN_A },
+ { NM_SETTING_IP_CONFIG_MAY_FAIL, NM_SETTING_DIFF_RESULT_IN_A },
+ { NULL, NM_SETTING_DIFF_RESULT_UNKNOWN },
+ } },
+ };
+
+ connection = new_test_connection ();
+
+ same = nm_connection_diff (connection, NULL, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs);
+ g_assert (same == FALSE);
+ g_assert (out_diffs != NULL);
+ g_assert (g_hash_table_size (out_diffs) > 0);
+
+ ensure_diffs (out_diffs, settings, ARRAY_LEN (settings));
+
+ g_hash_table_destroy (out_diffs);
+ g_object_unref (connection);
+}
+
+static void
+test_connection_diff_same (void)
+{
+ NMConnection *a, *b;
+ GHashTable *out_diffs = NULL;
+ gboolean same;
+
+ a = new_test_connection ();
+ b = nm_simple_connection_new_clone (a);
+
+ same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs);
+ g_assert (same == TRUE);
+ g_assert (out_diffs == NULL);
+ g_object_unref (a);
+ g_object_unref (b);
+}
+
+static void
+test_connection_diff_different (void)
+{
+ NMConnection *a, *b;
+ GHashTable *out_diffs = NULL;
+ NMSettingIPConfig *s_ip4;
+ gboolean same;
+ const DiffSetting settings[] = {
+ { NM_SETTING_IP4_CONFIG_SETTING_NAME, {
+ { NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_DIFF_RESULT_IN_A | NM_SETTING_DIFF_RESULT_IN_B },
+ { NULL, NM_SETTING_DIFF_RESULT_UNKNOWN },
+ } },
+ };
+
+ a = new_test_connection ();
+ b = nm_simple_connection_new_clone (a);
+ s_ip4 = nm_connection_get_setting_ip4_config (a);
+ g_assert (s_ip4);
+ g_object_set (G_OBJECT (s_ip4),
+ NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
+ NULL);
+
+ same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs);
+ g_assert (same == FALSE);
+ g_assert (out_diffs != NULL);
+ g_assert (g_hash_table_size (out_diffs) > 0);
+
+ ensure_diffs (out_diffs, settings, ARRAY_LEN (settings));
+
+ g_hash_table_destroy (out_diffs);
+ g_object_unref (a);
+ g_object_unref (b);
+}
+
+static void
+test_connection_diff_no_secrets (void)
+{
+ NMConnection *a, *b;
+ GHashTable *out_diffs = NULL;
+ NMSetting *s_pppoe;
+ gboolean same;
+ const DiffSetting settings[] = {
+ { NM_SETTING_PPPOE_SETTING_NAME, {
+ { NM_SETTING_PPPOE_PASSWORD, NM_SETTING_DIFF_RESULT_IN_B },
+ { NULL, NM_SETTING_DIFF_RESULT_UNKNOWN },
+ } },
+ };
+
+ a = new_test_connection ();
+ s_pppoe = nm_setting_pppoe_new ();
+ g_object_set (G_OBJECT (s_pppoe),
+ NM_SETTING_PPPOE_USERNAME, "thomas",
+ NULL);
+ nm_connection_add_setting (a, s_pppoe);
+
+ b = nm_simple_connection_new_clone (a);
+
+ /* Add a secret to B */
+ s_pppoe = NM_SETTING (nm_connection_get_setting_pppoe (b));
+ g_assert (s_pppoe);
+ g_object_set (G_OBJECT (s_pppoe),
+ NM_SETTING_PPPOE_PASSWORD, "secretpassword",
+ NULL);
+
+ /* Make sure the diff returns no results as secrets are ignored */
+ same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, &out_diffs);
+ g_assert (same == TRUE);
+ g_assert (out_diffs == NULL);
+
+ /* Now make sure the diff returns results if secrets are not ignored */
+ same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_EXACT, &out_diffs);
+ g_assert (same == FALSE);
+ g_assert (out_diffs != NULL);
+ g_assert (g_hash_table_size (out_diffs) > 0);
+
+ ensure_diffs (out_diffs, settings, ARRAY_LEN (settings));
+
+ g_hash_table_destroy (out_diffs);
+ g_object_unref (a);
+ g_object_unref (b);
+}
+
+static void
+test_connection_diff_inferrable (void)
+{
+ NMConnection *a, *b;
+ GHashTable *out_diffs = NULL;
+ gboolean same;
+ NMSettingConnection *s_con;
+ NMSettingWired *s_wired;
+ NMSettingIPConfig *s_ip4;
+ char *uuid;
+ const DiffSetting settings[] = {
+ { NM_SETTING_CONNECTION_SETTING_NAME, {
+ { NM_SETTING_CONNECTION_INTERFACE_NAME, NM_SETTING_DIFF_RESULT_IN_A },
+ { NULL, NM_SETTING_DIFF_RESULT_UNKNOWN },
+ } },
+ };
+
+ a = new_test_connection ();
+ b = nm_simple_connection_new_clone (a);
+
+ /* Change the UUID, wired MTU, and set ignore-auto-dns */
+ s_con = nm_connection_get_setting_connection (a);
+ g_assert (s_con);
+ uuid = nm_utils_uuid_generate ();
+ g_object_set (G_OBJECT (s_con),
+ NM_SETTING_CONNECTION_UUID, uuid,
+ NM_SETTING_CONNECTION_ID, "really neat connection",
+ NULL);
+ g_free (uuid);
+
+ s_wired = nm_connection_get_setting_wired (a);
+ g_assert (s_wired);
+ g_object_set (G_OBJECT (s_wired), NM_SETTING_WIRED_MTU, 300, NULL);
+
+ s_ip4 = nm_connection_get_setting_ip4_config (a);
+ g_assert (s_ip4);
+ g_object_set (G_OBJECT (s_ip4), NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, TRUE, NULL);
+
+ /* Make sure the diff returns no results as secrets are ignored */
+ same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_INFERRABLE, &out_diffs);
+ g_assert (same == TRUE);
+ g_assert (out_diffs == NULL);
+
+ /* And change a INFERRABLE property to ensure that it shows up in the diff results */
+ g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_INTERFACE_NAME, "usb0", NULL);
+
+ /* Make sure the diff returns no results as secrets are ignored */
+ same = nm_connection_diff (a, b, NM_SETTING_COMPARE_FLAG_INFERRABLE, &out_diffs);
+ g_assert (same == FALSE);
+ g_assert (out_diffs != NULL);
+ g_assert (g_hash_table_size (out_diffs) > 0);
+
+ ensure_diffs (out_diffs, settings, ARRAY_LEN (settings));
+
+ g_hash_table_destroy (out_diffs);
+ g_object_unref (a);
+ g_object_unref (b);
+}
+
+static void
+add_generic_settings (NMConnection *connection, const char *ctype)
+{
+ NMSetting *setting;
+ char *uuid;
+
+ uuid = nm_utils_uuid_generate ();
+
+ setting = nm_setting_connection_new ();
+ g_object_set (setting,
+ NM_SETTING_CONNECTION_ID, "asdfasdfadf",
+ NM_SETTING_CONNECTION_TYPE, ctype,
+ NM_SETTING_CONNECTION_UUID, uuid,
+ NULL);
+ nm_connection_add_setting (connection, setting);
+
+ g_free (uuid);
+
+ setting = nm_setting_ip4_config_new ();
+ g_object_set (setting, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
+ nm_connection_add_setting (connection, setting);
+
+ setting = nm_setting_ip6_config_new ();
+ g_object_set (setting, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, NULL);
+ nm_connection_add_setting (connection, setting);
+}
+
+static void
+test_connection_good_base_types (void)
+{
+ NMConnection *connection;
+ NMSetting *setting;
+ gboolean success;
+ GError *error = NULL;
+ GBytes *ssid;
+ const char *bdaddr = "11:22:33:44:55:66";
+
+ /* Try a basic wired connection */
+ connection = nm_simple_connection_new ();
+ add_generic_settings (connection, NM_SETTING_WIRED_SETTING_NAME);
+ setting = nm_setting_wired_new ();
+ nm_connection_add_setting (connection, setting);
+
+ success = nm_connection_verify (connection, &error);
+ g_assert_no_error (error);
+ g_assert (success);
+ g_object_unref (connection);
+
+ /* Try a wired PPPoE connection */
+ connection = nm_simple_connection_new ();
+ add_generic_settings (connection, NM_SETTING_PPPOE_SETTING_NAME);
+ setting = nm_setting_pppoe_new ();
+ g_object_set (setting, NM_SETTING_PPPOE_USERNAME, "bob smith", NULL);
+ nm_connection_add_setting (connection, setting);
+
+ success = nm_connection_verify (connection, &error);
+ g_assert_no_error (error);
+ g_assert (success);
+ g_object_unref (connection);
+
+ /* Wifi connection */
+ connection = nm_simple_connection_new ();
+ add_generic_settings (connection, NM_SETTING_WIRELESS_SETTING_NAME);
+
+ setting = nm_setting_wireless_new ();
+ ssid = g_bytes_new ("1234567", 7);
+ g_object_set (setting,
+ NM_SETTING_WIRELESS_SSID, ssid,
+ NM_SETTING_WIRELESS_MODE, "infrastructure",
+ NULL);
+ g_bytes_unref (ssid);
+ nm_connection_add_setting (connection, setting);
+
+ success = nm_connection_verify (connection, &error);
+ g_assert_no_error (error);
+ g_assert (success);
+ g_object_unref (connection);
+
+ /* Bluetooth connection */
+ connection = nm_simple_connection_new ();
+ add_generic_settings (connection, NM_SETTING_BLUETOOTH_SETTING_NAME);
+
+ setting = nm_setting_bluetooth_new ();
+ g_object_set (setting,
+ NM_SETTING_BLUETOOTH_BDADDR, bdaddr,
+ NM_SETTING_CONNECTION_TYPE, NM_SETTING_BLUETOOTH_TYPE_PANU,
+ NULL);
+ nm_connection_add_setting (connection, setting);
+
+ success = nm_connection_verify (connection, &error);
+ g_assert_no_error (error);
+ g_assert (success);
+ g_object_unref (connection);
+
+ /* WiMAX connection */
+ connection = nm_simple_connection_new ();
+ add_generic_settings (connection, NM_SETTING_WIMAX_SETTING_NAME);
+ setting = nm_setting_wimax_new ();
+ g_object_set (setting, NM_SETTING_WIMAX_NETWORK_NAME, "CLEAR", NULL);
+ nm_connection_add_setting (connection, setting);
+
+ success = nm_connection_verify (connection, &error);
+ g_assert_no_error (error);
+ g_assert (success);
+ g_object_unref (connection);
+
+ /* GSM connection */
+ connection = nm_simple_connection_new ();
+ add_generic_settings (connection, NM_SETTING_GSM_SETTING_NAME);
+
+ setting = nm_setting_gsm_new ();
+ g_object_set (setting,
+ NM_SETTING_GSM_NUMBER, "*99#",
+ NM_SETTING_GSM_APN, "metered.billing.sucks",
+ NULL);
+ nm_connection_add_setting (connection, setting);
+
+ /* CDMA connection */
+ connection = nm_simple_connection_new ();
+ add_generic_settings (connection, NM_SETTING_CDMA_SETTING_NAME);
+
+ setting = nm_setting_cdma_new ();
+ g_object_set (setting,
+ NM_SETTING_CDMA_NUMBER, "#777",
+ NM_SETTING_CDMA_USERNAME, "foobar@vzw.com",
+ NULL);
+ nm_connection_add_setting (connection, setting);
+
+ success = nm_connection_verify (connection, &error);
+ g_assert_no_error (error);
+ g_assert (success);
+ g_object_unref (connection);
+}
+
+static void
+test_connection_bad_base_types (void)
+{
+ NMConnection *connection;
+ NMSetting *setting;
+ gboolean success;
+ GError *error = NULL;
+
+ /* Test various non-base connection types to make sure they are rejected;
+ * using a fake 'wired' connection so the rest of it verifies
+ */
+
+ /* Connection setting */
+ connection = nm_simple_connection_new ();
+ add_generic_settings (connection, NM_SETTING_CONNECTION_SETTING_NAME);
+ setting = nm_setting_wired_new ();
+ nm_connection_add_setting (connection, setting);
+
+ success = nm_connection_verify (connection, &error);
+ g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
+ g_assert (g_str_has_prefix (error->message, "connection.type: "));
+ g_assert (success == FALSE);
+ g_object_unref (connection);
+ g_clear_error (&error);
+
+ /* PPP setting */
+ connection = nm_simple_connection_new ();
+ add_generic_settings (connection, NM_SETTING_PPP_SETTING_NAME);
+ setting = nm_setting_wired_new ();
+ nm_connection_add_setting (connection, setting);
+ setting = nm_setting_ppp_new ();
+ nm_connection_add_setting (connection, setting);
+
+ success = nm_connection_verify (connection, &error);
+ g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
+ g_assert (g_str_has_prefix (error->message, "connection.type: "));
+ g_assert (success == FALSE);
+ g_object_unref (connection);
+ g_clear_error (&error);
+
+ /* Serial setting */
+ connection = nm_simple_connection_new ();
+ add_generic_settings (connection, NM_SETTING_SERIAL_SETTING_NAME);
+ setting = nm_setting_wired_new ();
+ nm_connection_add_setting (connection, setting);
+ setting = nm_setting_serial_new ();
+ nm_connection_add_setting (connection, setting);
+
+ success = nm_connection_verify (connection, &error);
+ g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
+ g_assert (g_str_has_prefix (error->message, "connection.type: "));
+ g_assert (success == FALSE);
+ g_object_unref (connection);
+ g_clear_error (&error);
+
+ /* IP4 setting */
+ connection = nm_simple_connection_new ();
+ add_generic_settings (connection, NM_SETTING_IP4_CONFIG_SETTING_NAME);
+ setting = nm_setting_wired_new ();
+ nm_connection_add_setting (connection, setting);
+
+ success = nm_connection_verify (connection, &error);
+ g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
+ g_assert (g_str_has_prefix (error->message, "connection.type: "));
+ g_assert (success == FALSE);
+ g_object_unref (connection);
+ g_clear_error (&error);
+
+ /* IP6 setting */
+ connection = nm_simple_connection_new ();
+ add_generic_settings (connection, NM_SETTING_IP6_CONFIG_SETTING_NAME);
+ setting = nm_setting_wired_new ();
+ nm_connection_add_setting (connection, setting);
+
+ success = nm_connection_verify (connection, &error);
+ g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
+ g_assert (g_str_has_prefix (error->message, "connection.type: "));
+ g_assert (success == FALSE);
+ g_object_unref (connection);
+ g_clear_error (&error);
+}
+
+static void
+test_setting_compare_id (void)
+{
+ NMSetting *old, *new;
+ gboolean success;
+
+ old = nm_setting_connection_new ();
+ g_object_set (old,
+ NM_SETTING_CONNECTION_ID, "really awesome cool connection",
+ NM_SETTING_CONNECTION_UUID, "fbbd59d5-acab-4e30-8f86-258d272617e7",
+ NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
+ NULL);
+
+ new = nm_setting_duplicate (old);
+ g_object_set (new, NM_SETTING_CONNECTION_ID, "some different connection id", NULL);
+
+ /* First make sure they are different */
+ success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT);
+ g_assert (success == FALSE);
+
+ success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_IGNORE_ID);
+ g_assert (success);
+}
+
+static void
+test_setting_compare_timestamp (void)
+{
+ NMSetting *old, *new;
+ gboolean success;
+
+ old = nm_setting_connection_new ();
+ g_object_set (old,
+ NM_SETTING_CONNECTION_ID, "ignore timestamp connection",
+ NM_SETTING_CONNECTION_UUID, "b047a198-0e0a-4f0e-a653-eea09bb35e40",
+ NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
+ NM_SETTING_CONNECTION_TIMESTAMP, (guint64) 1234567890,
+ NULL);
+
+ new = nm_setting_duplicate (old);
+ g_object_set (new, NM_SETTING_CONNECTION_TIMESTAMP, (guint64) 1416316539, NULL);
+
+ /* First make sure they are different */
+ success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT);
+ g_assert (success == FALSE);
+
+ success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP);
+ g_assert (success);
+}
+
+typedef struct {
+ NMSettingSecretFlags secret_flags;
+ NMSettingCompareFlags comp_flags;
+ gboolean remove_secret;
+} TestDataCompareSecrets;
+
+static TestDataCompareSecrets *
+test_data_compare_secrets_new (NMSettingSecretFlags secret_flags,
+ NMSettingCompareFlags comp_flags,
+ gboolean remove_secret)
+{
+ TestDataCompareSecrets *data = g_new0 (TestDataCompareSecrets, 1);
+
+ data->secret_flags = secret_flags;
+ data->comp_flags = comp_flags;
+ data->remove_secret = remove_secret;
+ return data;
+}
+
+static void
+test_setting_compare_secrets (gconstpointer test_data)
+{
+ const TestDataCompareSecrets *data = test_data;
+ NMSetting *old, *new;
+ gboolean success;
+
+ /* Make sure that a connection with transient/unsaved secrets compares
+ * successfully to the same connection without those secrets.
+ */
+
+ old = nm_setting_wireless_security_new ();
+ g_object_set (old,
+ NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk",
+ NM_SETTING_WIRELESS_SECURITY_PSK, "really cool psk",
+ NULL);
+ nm_setting_set_secret_flags (old, NM_SETTING_WIRELESS_SECURITY_PSK, data->secret_flags, NULL);
+
+ /* Clear the PSK from the duplicated setting */
+ new = nm_setting_duplicate (old);
+ if (data->remove_secret) {
+ g_object_set (new, NM_SETTING_WIRELESS_SECURITY_PSK, NULL, NULL);
+
+ success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT);
+ g_assert (success == FALSE);
+ }
+
+ success = nm_setting_compare (old, new, data->comp_flags);
+ g_assert (success);
+}
+
+static void
+test_setting_compare_vpn_secrets (gconstpointer test_data)
+{
+ const TestDataCompareSecrets *data = test_data;
+ NMSetting *old, *new;
+ gboolean success;
+
+ /* Make sure that a connection with transient/unsaved secrets compares
+ * successfully to the same connection without those secrets.
+ */
+
+ old = nm_setting_vpn_new ();
+ nm_setting_vpn_add_secret (NM_SETTING_VPN (old), "foobarbaz", "really secret password");
+ nm_setting_vpn_add_secret (NM_SETTING_VPN (old), "asdfasdfasdf", "really adfasdfasdfasdf");
+ nm_setting_vpn_add_secret (NM_SETTING_VPN (old), "0123456778", "abcdefghijklmnpqrstuvqxyz");
+ nm_setting_vpn_add_secret (NM_SETTING_VPN (old), "borkbork", "yet another really secret password");
+ nm_setting_set_secret_flags (old, "borkbork", data->secret_flags, NULL);
+
+ /* Clear "borkbork" from the duplicated setting */
+ new = nm_setting_duplicate (old);
+ if (data->remove_secret) {
+ nm_setting_vpn_remove_secret (NM_SETTING_VPN (new), "borkbork");
+
+ /* First make sure they are different */
+ success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT);
+ g_assert (success == FALSE);
+ }
+
+ success = nm_setting_compare (old, new, data->comp_flags);
+ g_assert (success);
+}
+
+static void
+test_hwaddr_aton_ether_normal (void)
+{
+ guint8 buf[100];
+ guint8 expected[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
+
+ g_assert (nm_utils_hwaddr_aton ("00:11:22:33:44:55", buf, ETH_ALEN) != NULL);
+ g_assert (memcmp (buf, expected, sizeof (expected)) == 0);
+}
+
+static void
+test_hwaddr_aton_ib_normal (void)
+{
+ guint8 buf[100];
+ const char *source = "00:11:22:33:44:55:66:77:88:99:01:12:23:34:45:56:67:78:89:90";
+ guint8 expected[INFINIBAND_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
+ 0x77, 0x88, 0x99, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89,
+ 0x90 };
+
+ g_assert (nm_utils_hwaddr_aton (source, buf, INFINIBAND_ALEN) != NULL);
+ g_assert (memcmp (buf, expected, sizeof (expected)) == 0);
+}
+
+static void
+test_hwaddr_aton_no_leading_zeros (void)
+{
+ guint8 buf[100];
+ guint8 expected[ETH_ALEN] = { 0x00, 0x1A, 0x2B, 0x03, 0x44, 0x05 };
+
+ g_assert (nm_utils_hwaddr_aton ("0:1a:2B:3:44:5", buf, ETH_ALEN) != NULL);
+ g_assert (memcmp (buf, expected, sizeof (expected)) == 0);
+}
+
+static void
+test_hwaddr_aton_malformed (void)
+{
+ guint8 buf[100];
+
+ g_assert (nm_utils_hwaddr_aton ("0:1a:2B:3:a@%%", buf, ETH_ALEN) == NULL);
+}
+
+static void
+test_hwaddr_equal (void)
+{
+ const char *string = "00:1a:2b:03:44:05";
+ const char *upper_string = "00:1A:2B:03:44:05";
+ const char *bad_string = "0:1a:2b:3:44:5";
+ const guint8 binary[ETH_ALEN] = { 0x00, 0x1A, 0x2B, 0x03, 0x44, 0x05 };
+ const char *other_string = "1a:2b:03:44:05:00";
+ const guint8 other_binary[ETH_ALEN] = { 0x1A, 0x2B, 0x03, 0x44, 0x05, 0x00 };
+ const char *long_string = "00:1a:2b:03:44:05:06:07";
+ const guint8 long_binary[8] = { 0x00, 0x1A, 0x2B, 0x03, 0x44, 0x05, 0x06, 0x07 };
+ const char *null_string = "00:00:00:00:00:00";
+ const guint8 null_binary[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+
+ g_assert (nm_utils_hwaddr_matches (string, -1, string, -1));
+ g_assert (nm_utils_hwaddr_matches (string, -1, upper_string, -1));
+ g_assert (nm_utils_hwaddr_matches (string, -1, bad_string, -1));
+ g_assert (nm_utils_hwaddr_matches (string, -1, binary, sizeof (binary)));
+ g_assert (!nm_utils_hwaddr_matches (string, -1, other_string, -1));
+ g_assert (!nm_utils_hwaddr_matches (string, -1, other_binary, sizeof (other_binary)));
+ g_assert (!nm_utils_hwaddr_matches (string, -1, long_string, -1));
+ g_assert (!nm_utils_hwaddr_matches (string, -1, long_binary, sizeof (long_binary)));
+ g_assert (!nm_utils_hwaddr_matches (string, -1, null_string, -1));
+ g_assert (!nm_utils_hwaddr_matches (string, -1, null_binary, sizeof (null_binary)));
+ g_assert (!nm_utils_hwaddr_matches (string, -1, NULL, ETH_ALEN));
+
+ g_assert (nm_utils_hwaddr_matches (binary, sizeof (binary), string, -1));
+ g_assert (nm_utils_hwaddr_matches (binary, sizeof (binary), upper_string, -1));
+ g_assert (nm_utils_hwaddr_matches (binary, sizeof (binary), bad_string, -1));
+ g_assert (nm_utils_hwaddr_matches (binary, sizeof (binary), binary, sizeof (binary)));
+ g_assert (!nm_utils_hwaddr_matches (binary, sizeof (binary), other_string, -1));
+ g_assert (!nm_utils_hwaddr_matches (binary, sizeof (binary), other_binary, sizeof (other_binary)));
+ g_assert (!nm_utils_hwaddr_matches (binary, sizeof (binary), long_string, -1));
+ g_assert (!nm_utils_hwaddr_matches (binary, sizeof (binary), long_binary, sizeof (long_binary)));
+ g_assert (!nm_utils_hwaddr_matches (binary, sizeof (binary), null_string, -1));
+ g_assert (!nm_utils_hwaddr_matches (binary, sizeof (binary), null_binary, sizeof (null_binary)));
+ g_assert (!nm_utils_hwaddr_matches (binary, sizeof (binary), NULL, ETH_ALEN));
+
+ g_assert (!nm_utils_hwaddr_matches (null_string, -1, string, -1));
+ g_assert (!nm_utils_hwaddr_matches (null_string, -1, upper_string, -1));
+ g_assert (!nm_utils_hwaddr_matches (null_string, -1, bad_string, -1));
+ g_assert (!nm_utils_hwaddr_matches (null_string, -1, binary, sizeof (binary)));
+ g_assert (!nm_utils_hwaddr_matches (null_string, -1, other_string, -1));
+ g_assert (!nm_utils_hwaddr_matches (null_string, -1, other_binary, sizeof (other_binary)));
+ g_assert (!nm_utils_hwaddr_matches (null_string, -1, long_string, -1));
+ g_assert (!nm_utils_hwaddr_matches (null_string, -1, long_binary, sizeof (long_binary)));
+ g_assert (nm_utils_hwaddr_matches (null_string, -1, null_string, -1));
+ g_assert (nm_utils_hwaddr_matches (null_string, -1, null_binary, sizeof (null_binary)));
+ g_assert (nm_utils_hwaddr_matches (null_string, -1, NULL, ETH_ALEN));
+
+ g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), string, -1));
+ g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), upper_string, -1));
+ g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), bad_string, -1));
+ g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), binary, sizeof (binary)));
+ g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), other_string, -1));
+ g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), other_binary, sizeof (other_binary)));
+ g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), long_string, -1));
+ g_assert (!nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), long_binary, sizeof (long_binary)));
+ g_assert (nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), null_string, -1));
+ g_assert (nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), null_binary, sizeof (null_binary)));
+ g_assert (nm_utils_hwaddr_matches (null_binary, sizeof (null_binary), NULL, ETH_ALEN));
+}
+
+static void
+test_hwaddr_canonical (void)
+{
+ const char *string = "00:1A:2B:03:44:05";
+ const char *lower_string = "00:1a:2b:03:44:05";
+ const char *short_string = "0:1a:2b:3:44:5";
+ const char *hyphen_string = "00-1a-2b-03-44-05";
+ const char *invalid_string = "00:1A:2B";
+ char *canonical;
+
+ canonical = nm_utils_hwaddr_canonical (string, ETH_ALEN);
+ g_assert_cmpstr (canonical, ==, string);
+ g_free (canonical);
+
+ canonical = nm_utils_hwaddr_canonical (lower_string, ETH_ALEN);
+ g_assert_cmpstr (canonical, ==, string);
+ g_free (canonical);
+
+ canonical = nm_utils_hwaddr_canonical (short_string, ETH_ALEN);
+ g_assert_cmpstr (canonical, ==, string);
+ g_free (canonical);
+
+ canonical = nm_utils_hwaddr_canonical (hyphen_string, ETH_ALEN);
+ g_assert_cmpstr (canonical, ==, string);
+ g_free (canonical);
+
+ canonical = nm_utils_hwaddr_canonical (invalid_string, ETH_ALEN);
+ g_assert_cmpstr (canonical, ==, NULL);
+
+ canonical = nm_utils_hwaddr_canonical (invalid_string, -1);
+ g_assert_cmpstr (canonical, ==, invalid_string);
+ g_free (canonical);
+}
+
+static void
+test_connection_changed_cb (NMConnection *connection, gboolean *data)
+{
+ *data = TRUE;
+}
+
+static void
+test_ip4_prefix_to_netmask (void)
+{
+ int i;
+
+ for (i = 0; i<=32; i++) {
+ guint32 netmask = nm_utils_ip4_prefix_to_netmask (i);
+ int plen = nm_utils_ip4_netmask_to_prefix (netmask);
+
+ g_assert_cmpint (i, ==, plen);
+ {
+ guint32 msk = 0x80000000;
+ guint32 netmask2 = 0;
+ guint32 prefix = i;
+ while (prefix > 0) {
+ netmask2 |= msk;
+ msk >>= 1;
+ prefix--;
+ }
+ g_assert_cmpint (netmask, ==, (guint32) htonl (netmask2));
+ }
+ }
+}
+
+static void
+test_ip4_netmask_to_prefix (void)
+{
+ int i, j;
+
+ GRand *rand = g_rand_new ();
+
+ g_rand_set_seed (rand, 1);
+
+ for (i = 2; i<=32; i++) {
+ guint32 netmask = nm_utils_ip4_prefix_to_netmask (i);
+ guint32 netmask_lowest_bit = netmask & ~nm_utils_ip4_prefix_to_netmask (i-1);
+
+ g_assert_cmpint (i, ==, nm_utils_ip4_netmask_to_prefix (netmask));
+
+ for (j = 0; j < 2*i; j++) {
+ guint32 r = g_rand_int (rand);
+ guint32 netmask_holey;
+ guint32 prefix_holey;
+
+ netmask_holey = (netmask & r) | netmask_lowest_bit;
+
+ if (netmask_holey == netmask)
+ continue;
+
+ /* create an invalid netmask with holes and check that the function
+ * returns the longest prefix. */
+ prefix_holey = nm_utils_ip4_netmask_to_prefix (netmask_holey);
+
+ g_assert_cmpint (i, ==, prefix_holey);
+ }
+ }
+
+ g_rand_free (rand);
+}
+
+#define ASSERT_CHANGED(statement) \
+{ \
+ changed = FALSE; \
+ statement; \
+ g_assert (changed); \
+}
+
+#define ASSERT_UNCHANGED(statement) \
+{ \
+ changed = FALSE; \
+ statement; \
+ g_assert (!changed); \
+}
+
+static void
+test_connection_changed_signal (void)
+{
+ NMConnection *connection;
+ gboolean changed = FALSE;
+
+ connection = new_test_connection ();
+ g_signal_connect (connection,
+ NM_CONNECTION_CHANGED,
+ (GCallback) test_connection_changed_cb,
+ &changed);
+
+ /* Add new setting */
+ ASSERT_CHANGED (nm_connection_add_setting (connection, nm_setting_vlan_new ()));
+
+ /* Remove existing setting */
+ ASSERT_CHANGED (nm_connection_remove_setting (connection, NM_TYPE_SETTING_VLAN));
+
+ /* Remove non-existing setting */
+ ASSERT_UNCHANGED (nm_connection_remove_setting (connection, NM_TYPE_SETTING_VLAN));
+
+ g_object_unref (connection);
+}
+
+static void
+test_setting_connection_changed_signal (void)
+{
+ NMConnection *connection;
+ gboolean changed = FALSE;
+ NMSettingConnection *s_con;
+ char *uuid;
+
+ connection = nm_simple_connection_new ();
+ g_signal_connect (connection,
+ NM_CONNECTION_CHANGED,
+ (GCallback) test_connection_changed_cb,
+ &changed);
+
+ s_con = (NMSettingConnection *) nm_setting_connection_new ();
+ nm_connection_add_setting (connection, NM_SETTING (s_con));
+
+ ASSERT_CHANGED (g_object_set (s_con, NM_SETTING_CONNECTION_ID, "adfadfasdfaf", NULL));
+
+ ASSERT_CHANGED (nm_setting_connection_add_permission (s_con, "user", "billsmith", NULL));
+ ASSERT_CHANGED (nm_setting_connection_remove_permission (s_con, 0));
+
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*iter != NULL*");
+ ASSERT_UNCHANGED (nm_setting_connection_remove_permission (s_con, 1));
+ g_test_assert_expected_messages ();
+
+ uuid = nm_utils_uuid_generate ();
+ ASSERT_CHANGED (nm_setting_connection_add_secondary (s_con, uuid));
+ ASSERT_CHANGED (nm_setting_connection_remove_secondary (s_con, 0));
+
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
+ ASSERT_UNCHANGED (nm_setting_connection_remove_secondary (s_con, 1));
+ g_test_assert_expected_messages ();
+
+ g_object_unref (connection);
+}
+
+static void
+test_setting_bond_changed_signal (void)
+{
+ NMConnection *connection;
+ gboolean changed = FALSE;
+ NMSettingBond *s_bond;
+
+ connection = nm_simple_connection_new ();
+ g_signal_connect (connection,
+ NM_CONNECTION_CHANGED,
+ (GCallback) test_connection_changed_cb,
+ &changed);
+
+ s_bond = (NMSettingBond *) nm_setting_bond_new ();
+ nm_connection_add_setting (connection, NM_SETTING (s_bond));
+
+ ASSERT_CHANGED (nm_setting_bond_add_option (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY, "10"));
+ ASSERT_CHANGED (nm_setting_bond_remove_option (s_bond, NM_SETTING_BOND_OPTION_DOWNDELAY));
+ ASSERT_UNCHANGED (nm_setting_bond_remove_option (s_bond, NM_SETTING_BOND_OPTION_UPDELAY));
+
+ g_object_unref (connection);
+}
+
+static void
+test_setting_ip4_changed_signal (void)
+{
+ NMConnection *connection;
+ gboolean changed = FALSE;
+ NMSettingIPConfig *s_ip4;
+ NMIPAddress *addr;
+ NMIPRoute *route;
+ GError *error = NULL;
+
+ connection = nm_simple_connection_new ();
+ g_signal_connect (connection,
+ NM_CONNECTION_CHANGED,
+ (GCallback) test_connection_changed_cb,
+ &changed);
+
+ s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
+ nm_connection_add_setting (connection, NM_SETTING (s_ip4));
+
+ ASSERT_CHANGED (nm_setting_ip_config_add_dns (s_ip4, "11.22.0.0"));
+ ASSERT_CHANGED (nm_setting_ip_config_remove_dns (s_ip4, 0));
+
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*i < priv->dns->len*");
+ ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns (s_ip4, 1));
+ g_test_assert_expected_messages ();
+
+ nm_setting_ip_config_add_dns (s_ip4, "33.44.0.0");
+ ASSERT_CHANGED (nm_setting_ip_config_clear_dns (s_ip4));
+
+ ASSERT_CHANGED (nm_setting_ip_config_add_dns_search (s_ip4, "foobar.com"));
+ ASSERT_CHANGED (nm_setting_ip_config_remove_dns_search (s_ip4, 0));
+
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*i < priv->dns_search->len*");
+ ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns_search (s_ip4, 1));
+ g_test_assert_expected_messages ();
+
+ ASSERT_CHANGED (nm_setting_ip_config_add_dns_search (s_ip4, "foobar.com"));
+ ASSERT_CHANGED (nm_setting_ip_config_clear_dns_searches (s_ip4));
+
+ addr = nm_ip_address_new (AF_INET, "22.33.0.0", 24, &error);
+ g_assert_no_error (error);
+ ASSERT_CHANGED (nm_setting_ip_config_add_address (s_ip4, addr));
+ ASSERT_CHANGED (nm_setting_ip_config_remove_address (s_ip4, 0));
+
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*i < priv->addresses->len*");
+ ASSERT_UNCHANGED (nm_setting_ip_config_remove_address (s_ip4, 1));
+ g_test_assert_expected_messages ();
+
+ nm_setting_ip_config_add_address (s_ip4, addr);
+ ASSERT_CHANGED (nm_setting_ip_config_clear_addresses (s_ip4));
+
+ route = nm_ip_route_new (AF_INET, "22.33.0.0", 24, NULL, 0, &error);
+ g_assert_no_error (error);
+
+ ASSERT_CHANGED (nm_setting_ip_config_add_route (s_ip4, route));
+ ASSERT_CHANGED (nm_setting_ip_config_remove_route (s_ip4, 0));
+
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*i < priv->routes->len*");
+ ASSERT_UNCHANGED (nm_setting_ip_config_remove_route (s_ip4, 1));
+ g_test_assert_expected_messages ();
+
+ nm_setting_ip_config_add_route (s_ip4, route);
+ ASSERT_CHANGED (nm_setting_ip_config_clear_routes (s_ip4));
+
+ nm_ip_address_unref (addr);
+ nm_ip_route_unref (route);
+ g_object_unref (connection);
+}
+
+static void
+test_setting_ip6_changed_signal (void)
+{
+ NMConnection *connection;
+ gboolean changed = FALSE;
+ NMSettingIPConfig *s_ip6;
+ NMIPAddress *addr;
+ NMIPRoute *route;
+ GError *error = NULL;
+
+ connection = nm_simple_connection_new ();
+ g_signal_connect (connection,
+ NM_CONNECTION_CHANGED,
+ (GCallback) test_connection_changed_cb,
+ &changed);
+
+ s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
+ nm_connection_add_setting (connection, NM_SETTING (s_ip6));
+
+ ASSERT_CHANGED (nm_setting_ip_config_add_dns (s_ip6, "1:2:3::4:5:6"));
+ ASSERT_CHANGED (nm_setting_ip_config_remove_dns (s_ip6, 0));
+
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*i < priv->dns->len*");
+ ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns (s_ip6, 1));
+ g_test_assert_expected_messages ();
+
+ nm_setting_ip_config_add_dns (s_ip6, "1:2:3::4:5:6");
+ ASSERT_CHANGED (nm_setting_ip_config_clear_dns (s_ip6));
+
+ ASSERT_CHANGED (nm_setting_ip_config_add_dns_search (s_ip6, "foobar.com"));
+ ASSERT_CHANGED (nm_setting_ip_config_remove_dns_search (s_ip6, 0));
+
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*i < priv->dns_search->len*");
+ ASSERT_UNCHANGED (nm_setting_ip_config_remove_dns_search (s_ip6, 1));
+ g_test_assert_expected_messages ();
+
+ nm_setting_ip_config_add_dns_search (s_ip6, "foobar.com");
+ ASSERT_CHANGED (nm_setting_ip_config_clear_dns_searches (s_ip6));
+
+ addr = nm_ip_address_new (AF_INET6, "1:2:3::4:5:6", 64, &error);
+ g_assert_no_error (error);
+
+ ASSERT_CHANGED (nm_setting_ip_config_add_address (s_ip6, addr));
+ ASSERT_CHANGED (nm_setting_ip_config_remove_address (s_ip6, 0));
+
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*i < priv->addresses->len*");
+ ASSERT_UNCHANGED (nm_setting_ip_config_remove_address (s_ip6, 1));
+ g_test_assert_expected_messages ();
+
+ nm_setting_ip_config_add_address (s_ip6, addr);
+ ASSERT_CHANGED (nm_setting_ip_config_clear_addresses (s_ip6));
+
+ route = nm_ip_route_new (AF_INET6, "1:2:3::4:5:6", 128, NULL, 0, &error);
+ g_assert_no_error (error);
+
+ ASSERT_CHANGED (nm_setting_ip_config_add_route (s_ip6, route));
+ ASSERT_CHANGED (nm_setting_ip_config_remove_route (s_ip6, 0));
+
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*i < priv->routes->len*");
+ ASSERT_UNCHANGED (nm_setting_ip_config_remove_route (s_ip6, 1));
+ g_test_assert_expected_messages ();
+
+ nm_setting_ip_config_add_route (s_ip6, route);
+ ASSERT_CHANGED (nm_setting_ip_config_clear_routes (s_ip6));
+
+ nm_ip_address_unref (addr);
+ nm_ip_route_unref (route);
+ g_object_unref (connection);
+}
+
+static void
+test_setting_vlan_changed_signal (void)
+{
+ NMConnection *connection;
+ gboolean changed = FALSE;
+ NMSettingVlan *s_vlan;
+
+ connection = nm_simple_connection_new ();
+ g_signal_connect (connection,
+ NM_CONNECTION_CHANGED,
+ (GCallback) test_connection_changed_cb,
+ &changed);
+
+ s_vlan = (NMSettingVlan *) nm_setting_vlan_new ();
+ nm_connection_add_setting (connection, NM_SETTING (s_vlan));
+
+ ASSERT_CHANGED (nm_setting_vlan_add_priority (s_vlan, NM_VLAN_INGRESS_MAP, 1, 3));
+ ASSERT_CHANGED (nm_setting_vlan_remove_priority (s_vlan, NM_VLAN_INGRESS_MAP, 0));
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*idx < g_slist_length (list)*");
+ ASSERT_UNCHANGED (nm_setting_vlan_remove_priority (s_vlan, NM_VLAN_INGRESS_MAP, 1));
+ g_test_assert_expected_messages ();
+ ASSERT_CHANGED (nm_setting_vlan_add_priority_str (s_vlan, NM_VLAN_INGRESS_MAP, "1:3"));
+ ASSERT_CHANGED (nm_setting_vlan_clear_priorities (s_vlan, NM_VLAN_INGRESS_MAP));
+
+ ASSERT_CHANGED (nm_setting_vlan_add_priority (s_vlan, NM_VLAN_EGRESS_MAP, 1, 3));
+ ASSERT_CHANGED (nm_setting_vlan_remove_priority (s_vlan, NM_VLAN_EGRESS_MAP, 0));
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*idx < g_slist_length (list)*");
+ ASSERT_UNCHANGED (nm_setting_vlan_remove_priority (s_vlan, NM_VLAN_EGRESS_MAP, 1));
+ g_test_assert_expected_messages ();
+ ASSERT_CHANGED (nm_setting_vlan_add_priority_str (s_vlan, NM_VLAN_EGRESS_MAP, "1:3"));
+ ASSERT_CHANGED (nm_setting_vlan_clear_priorities (s_vlan, NM_VLAN_EGRESS_MAP));
+
+ g_object_unref (connection);
+}
+
+static void
+test_setting_vpn_changed_signal (void)
+{
+ NMConnection *connection;
+ gboolean changed = FALSE;
+ NMSettingVpn *s_vpn;
+
+ connection = nm_simple_connection_new ();
+ g_signal_connect (connection,
+ NM_CONNECTION_CHANGED,
+ (GCallback) test_connection_changed_cb,
+ &changed);
+
+ s_vpn = (NMSettingVpn *) nm_setting_vpn_new ();
+ nm_connection_add_setting (connection, NM_SETTING (s_vpn));
+
+ ASSERT_CHANGED (nm_setting_vpn_add_data_item (s_vpn, "foobar", "baz"));
+ ASSERT_CHANGED (nm_setting_vpn_remove_data_item (s_vpn, "foobar"));
+ ASSERT_UNCHANGED (nm_setting_vpn_remove_data_item (s_vpn, "not added"));
+
+ ASSERT_CHANGED (nm_setting_vpn_add_secret (s_vpn, "foobar", "baz"));
+ ASSERT_CHANGED (nm_setting_vpn_remove_secret (s_vpn, "foobar"));
+ ASSERT_UNCHANGED (nm_setting_vpn_remove_secret (s_vpn, "not added"));
+
+ g_object_unref (connection);
+}
+
+static void
+test_setting_wired_changed_signal (void)
+{
+ NMConnection *connection;
+ gboolean changed = FALSE;
+ NMSettingWired *s_wired;
+
+ connection = nm_simple_connection_new ();
+ g_signal_connect (connection,
+ NM_CONNECTION_CHANGED,
+ (GCallback) test_connection_changed_cb,
+ &changed);
+
+ s_wired = (NMSettingWired *) nm_setting_wired_new ();
+ nm_connection_add_setting (connection, NM_SETTING (s_wired));
+
+ ASSERT_CHANGED (nm_setting_wired_add_s390_option (s_wired, "portno", "1"));
+ ASSERT_CHANGED (nm_setting_wired_remove_s390_option (s_wired, "portno"));
+ ASSERT_UNCHANGED (nm_setting_wired_remove_s390_option (s_wired, "layer2"));
+
+ g_object_unref (connection);
+}
+
+static void
+test_setting_wireless_changed_signal (void)
+{
+ NMConnection *connection;
+ gboolean changed = FALSE;
+ NMSettingWireless *s_wifi;
+
+ connection = nm_simple_connection_new ();
+ g_signal_connect (connection,
+ NM_CONNECTION_CHANGED,
+ (GCallback) test_connection_changed_cb,
+ &changed);
+
+ s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
+ nm_connection_add_setting (connection, NM_SETTING (s_wifi));
+
+ ASSERT_CHANGED (nm_setting_wireless_add_seen_bssid (s_wifi, "00:11:22:33:44:55"));
+
+ g_object_unref (connection);
+}
+
+static void
+test_setting_wireless_security_changed_signal (void)
+{
+ NMConnection *connection;
+ gboolean changed = FALSE;
+ NMSettingWirelessSecurity *s_wsec;
+
+ connection = nm_simple_connection_new ();
+ g_signal_connect (connection,
+ NM_CONNECTION_CHANGED,
+ (GCallback) test_connection_changed_cb,
+ &changed);
+
+ s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+ nm_connection_add_setting (connection, NM_SETTING (s_wsec));
+
+ /* Protos */
+ ASSERT_CHANGED (nm_setting_wireless_security_add_proto (s_wsec, "wpa"));
+ ASSERT_CHANGED (nm_setting_wireless_security_remove_proto (s_wsec, 0));
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
+ ASSERT_UNCHANGED (nm_setting_wireless_security_remove_proto (s_wsec, 1));
+ g_test_assert_expected_messages ();
+
+ nm_setting_wireless_security_add_proto (s_wsec, "wep");
+ ASSERT_CHANGED (nm_setting_wireless_security_clear_protos (s_wsec));
+
+ /* Pairwise ciphers */
+ ASSERT_CHANGED (nm_setting_wireless_security_add_pairwise (s_wsec, "tkip"));
+ ASSERT_CHANGED (nm_setting_wireless_security_remove_pairwise (s_wsec, 0));
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
+ ASSERT_UNCHANGED (nm_setting_wireless_security_remove_pairwise (s_wsec, 1));
+ g_test_assert_expected_messages ();
+
+ nm_setting_wireless_security_add_pairwise (s_wsec, "tkip");
+ ASSERT_CHANGED (nm_setting_wireless_security_clear_pairwise (s_wsec));
+
+ /* Group ciphers */
+ ASSERT_CHANGED (nm_setting_wireless_security_add_group (s_wsec, "ccmp"));
+ ASSERT_CHANGED (nm_setting_wireless_security_remove_group (s_wsec, 0));
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
+ ASSERT_UNCHANGED (nm_setting_wireless_security_remove_group (s_wsec, 1));
+ g_test_assert_expected_messages ();
+
+ nm_setting_wireless_security_add_group (s_wsec, "tkip");
+ ASSERT_CHANGED (nm_setting_wireless_security_clear_groups (s_wsec));
+
+ /* WEP key secret flags */
+ ASSERT_CHANGED (g_assert (nm_setting_set_secret_flags (NM_SETTING (s_wsec), "wep-key0", NM_SETTING_SECRET_FLAG_AGENT_OWNED, NULL)));
+ ASSERT_CHANGED (g_assert (nm_setting_set_secret_flags (NM_SETTING (s_wsec), "wep-key1", NM_SETTING_SECRET_FLAG_AGENT_OWNED, NULL)));
+ ASSERT_CHANGED (g_assert (nm_setting_set_secret_flags (NM_SETTING (s_wsec), "wep-key2", NM_SETTING_SECRET_FLAG_AGENT_OWNED, NULL)));
+ ASSERT_CHANGED (g_assert (nm_setting_set_secret_flags (NM_SETTING (s_wsec), "wep-key3", NM_SETTING_SECRET_FLAG_AGENT_OWNED, NULL)));
+
+ g_object_unref (connection);
+}
+
+static void
+test_setting_802_1x_changed_signal (void)
+{
+ NMConnection *connection;
+ gboolean changed = FALSE;
+ NMSetting8021x *s_8021x;
+
+ connection = nm_simple_connection_new ();
+ g_signal_connect (connection,
+ NM_CONNECTION_CHANGED,
+ (GCallback) test_connection_changed_cb,
+ &changed);
+
+ s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
+ nm_connection_add_setting (connection, NM_SETTING (s_8021x));
+
+ /* EAP methods */
+ ASSERT_CHANGED (nm_setting_802_1x_add_eap_method (s_8021x, "tls"));
+ ASSERT_CHANGED (nm_setting_802_1x_remove_eap_method (s_8021x, 0));
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
+ ASSERT_UNCHANGED (nm_setting_802_1x_remove_eap_method (s_8021x, 1));
+ g_test_assert_expected_messages ();
+
+ nm_setting_802_1x_add_eap_method (s_8021x, "ttls");
+ ASSERT_CHANGED (nm_setting_802_1x_clear_eap_methods (s_8021x));
+
+ /* alternate subject matches */
+ ASSERT_CHANGED (nm_setting_802_1x_add_altsubject_match (s_8021x, "EMAIL:server@example.com"));
+ ASSERT_CHANGED (nm_setting_802_1x_remove_altsubject_match (s_8021x, 0));
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
+ ASSERT_UNCHANGED (nm_setting_802_1x_remove_altsubject_match (s_8021x, 1));
+ g_test_assert_expected_messages ();
+
+ nm_setting_802_1x_add_altsubject_match (s_8021x, "EMAIL:server@example.com");
+ ASSERT_CHANGED (nm_setting_802_1x_clear_altsubject_matches (s_8021x));
+
+ /* phase2 alternate subject matches */
+ ASSERT_CHANGED (nm_setting_802_1x_add_phase2_altsubject_match (s_8021x, "EMAIL:server@example.com"));
+ ASSERT_CHANGED (nm_setting_802_1x_remove_phase2_altsubject_match (s_8021x, 0));
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL, "*elt != NULL*");
+ ASSERT_UNCHANGED (nm_setting_802_1x_remove_phase2_altsubject_match (s_8021x, 1));
+ g_test_assert_expected_messages ();
+
+ nm_setting_802_1x_add_phase2_altsubject_match (s_8021x, "EMAIL:server@example.com");
+ ASSERT_CHANGED (nm_setting_802_1x_clear_phase2_altsubject_matches (s_8021x));
+
+ g_object_unref (connection);
+}
+
+static void
+test_setting_old_uuid (void)
+{
+ NMSetting *setting;
+
+ /* NetworkManager-0.9.4.0 generated 40-character UUIDs with no dashes,
+ * like this one. Test that we maintain compatibility. */
+ const char *uuid = "f43bec2cdd60e5da381ebb1eb1fa39f3cc52660c";
+
+ setting = nm_setting_connection_new ();
+ g_object_set (G_OBJECT (setting),
+ NM_SETTING_CONNECTION_ID, "uuidtest",
+ NM_SETTING_CONNECTION_UUID, uuid,
+ NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
+ NULL);
+
+ nmtst_assert_setting_verifies (NM_SETTING (setting));
+}
+
+/******************************************************************************/
+
+static void
+test_connection_normalize_uuid (void)
+{
+ gs_unref_object NMConnection *con = NULL;
+
+ con = nmtst_create_minimal_connection ("test1", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL);
+
+ nmtst_assert_connection_verifies_and_normalizable (con);
+
+ g_object_set (nm_connection_get_setting_connection (con),
+ NM_SETTING_CONNECTION_UUID, NULL,
+ NULL);
+ nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
+}
+
+/******************************************************************************/
+
+/*
+ * Test normalization of interface-name
+ */
+static void
+test_connection_normalize_virtual_iface_name (void)
+{
+ NMConnection *con = NULL;
+ NMSettingConnection *s_con;
+ NMSettingVlan *s_vlan;
+ GVariant *connection_dict, *setting_dict, *var;
+ GError *error = NULL;
+ const char *IFACE_NAME = "iface";
+ const char *IFACE_VIRT = "iface-X";
+
+ con = nmtst_create_minimal_connection ("test1",
+ "22001632-bbb4-4616-b277-363dce3dfb5b",
+ NM_SETTING_VLAN_SETTING_NAME,
+ &s_con);
+
+ nm_connection_add_setting (con,
+ g_object_new (NM_TYPE_SETTING_IP4_CONFIG,
+ NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
+ NULL));
+
+ nm_connection_add_setting (con,
+ g_object_new (NM_TYPE_SETTING_IP6_CONFIG,
+ NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO,
+ NULL));
+
+ s_vlan = nm_connection_get_setting_vlan (con);
+
+ g_object_set (G_OBJECT (s_vlan),
+ NM_SETTING_VLAN_PARENT, "eth0",
+ NULL);
+
+ g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_INTERFACE_NAME, IFACE_NAME, NULL);
+
+ g_assert_cmpstr (nm_connection_get_interface_name (con), ==, IFACE_NAME);
+
+ connection_dict = nm_connection_to_dbus (con, NM_CONNECTION_SERIALIZE_ALL);
+ g_object_unref (con);
+
+ /* Serialized form should include vlan.interface-name as well. */
+ setting_dict = g_variant_lookup_value (connection_dict, NM_SETTING_VLAN_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
+ g_assert (setting_dict != NULL);
+ var = g_variant_lookup_value (setting_dict, "interface-name", NULL);
+ g_assert (var != NULL);
+ g_assert (g_variant_is_of_type (var, G_VARIANT_TYPE_STRING));
+ g_assert_cmpstr (g_variant_get_string (var, NULL), ==, IFACE_NAME);
+
+ g_variant_unref (setting_dict);
+ g_variant_unref (var);
+
+ /* If vlan.interface-name is invalid, deserialization will fail. */
+ NMTST_VARIANT_EDITOR (connection_dict,
+ NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_VLAN_SETTING_NAME,
+ "interface-name",
+ "s",
+ ":::this-is-not-a-valid-interface-name:::");
+ );
+
+ con = nm_simple_connection_new_from_dbus (connection_dict, &error);
+ g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
+ g_clear_error (&error);
+
+ /* If vlan.interface-name is valid, but doesn't match, it will be ignored. */
+ NMTST_VARIANT_EDITOR (connection_dict,
+ NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_VLAN_SETTING_NAME,
+ "interface-name",
+ "s",
+ IFACE_VIRT);
+ );
+
+ con = nm_simple_connection_new_from_dbus (connection_dict, &error);
+ g_assert_no_error (error);
+
+ g_assert_cmpstr (nm_connection_get_interface_name (con), ==, IFACE_NAME);
+ s_con = nm_connection_get_setting_connection (con);
+ g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, IFACE_NAME);
+ g_object_unref (con);
+
+ /* But removing connection.interface-name should result in vlan.connection-name
+ * being "promoted".
+ */
+ NMTST_VARIANT_EDITOR (connection_dict,
+ NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_CONNECTION_SETTING_NAME,
+ NM_SETTING_CONNECTION_INTERFACE_NAME);
+ );
+
+ con = nm_simple_connection_new_from_dbus (connection_dict, &error);
+ g_assert_no_error (error);
+
+ g_assert_cmpstr (nm_connection_get_interface_name (con), ==, IFACE_VIRT);
+ s_con = nm_connection_get_setting_connection (con);
+ g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, IFACE_VIRT);
+ g_object_unref (con);
+
+ g_variant_unref (connection_dict);
+}
+
+static void
+_test_connection_normalize_type_normalizable_setting (const char *type,
+ void (*prepare_normalizable_fcn) (NMConnection *con))
+{
+ NMSettingConnection *s_con;
+ NMSetting *s_base;
+ GType base_type;
+ gs_unref_object NMConnection *con = NULL;
+ gs_free char *id = g_strdup_printf ("%s[%s]", G_STRFUNC, type);
+
+ base_type = nm_setting_lookup_type (type);
+ g_assert (base_type != G_TYPE_INVALID);
+ g_assert (_nm_setting_type_is_base_type (base_type));
+
+ con = nmtst_create_minimal_connection (id, NULL, NULL, &s_con);
+
+ nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
+
+ g_object_set (s_con, NM_SETTING_CONNECTION_TYPE, type, NULL);
+
+ if (prepare_normalizable_fcn)
+ prepare_normalizable_fcn (con);
+
+ g_assert (!nm_connection_get_setting_by_name (con, type));
+ nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_SETTING);
+
+ s_base = nm_connection_get_setting_by_name (con, type);
+ g_assert (s_base);
+ g_assert (G_OBJECT_TYPE (s_base) == base_type);
+}
+
+static void
+_test_connection_normalize_type_unnormalizable_setting (const char *type)
+{
+ NMSettingConnection *s_con;
+ GType base_type;
+ gs_unref_object NMConnection *con = NULL;
+ gs_free char *id = g_strdup_printf ("%s[%s]", G_STRFUNC, type);
+
+ base_type = nm_setting_lookup_type (type);
+ g_assert (base_type != G_TYPE_INVALID);
+ g_assert (_nm_setting_type_is_base_type (base_type));
+
+ con = nmtst_create_minimal_connection (id, NULL, NULL, &s_con);
+
+ nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
+
+ g_object_set (s_con, NM_SETTING_CONNECTION_TYPE, type, NULL);
+
+ nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_SETTING);
+}
+
+static void
+_test_connection_normalize_type_normalizable_type (const char *type,
+ NMSetting *(*add_setting_fcn) (NMConnection *con))
+{
+ NMSettingConnection *s_con;
+ NMSetting *s_base;
+ GType base_type;
+ gs_unref_object NMConnection *con = NULL;
+ gs_free char *id = g_strdup_printf ("%s[%s]", G_STRFUNC, type);
+
+ base_type = nm_setting_lookup_type (type);
+ g_assert (base_type != G_TYPE_INVALID);
+ g_assert (_nm_setting_type_is_base_type (base_type));
+
+ con = nmtst_create_minimal_connection (id, NULL, NULL, &s_con);
+
+ nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
+
+ if (add_setting_fcn)
+ s_base = add_setting_fcn (con);
+ else {
+ s_base = NM_SETTING (g_object_new (base_type, NULL));
+ nm_connection_add_setting (con, s_base);
+ }
+
+ g_assert (!nm_connection_get_connection_type (con));
+ g_assert (nm_connection_get_setting_by_name (con, type) == s_base);
+
+ nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
+
+ g_assert_cmpstr (nm_connection_get_connection_type (con), ==, type);
+ g_assert (nm_connection_get_setting_by_name (con, type) == s_base);
+}
+
+static NMSetting *
+_add_setting_fcn_adsl (NMConnection *con)
+{
+ NMSetting *setting;
+
+ setting = g_object_new (NM_TYPE_SETTING_ADSL,
+ NM_SETTING_ADSL_USERNAME, "test-user",
+ NM_SETTING_ADSL_PROTOCOL, NM_SETTING_ADSL_PROTOCOL_PPPOA,
+ NM_SETTING_ADSL_ENCAPSULATION, NM_SETTING_ADSL_ENCAPSULATION_VCMUX,
+ NULL);
+
+ nm_connection_add_setting (con, setting);
+ return setting;
+}
+
+static NMSetting *
+_add_setting_fcn_bluetooth (NMConnection *con)
+{
+ NMSetting *setting;
+
+ setting = g_object_new (NM_TYPE_SETTING_BLUETOOTH,
+ NM_SETTING_BLUETOOTH_BDADDR, "11:22:33:44:55:66",
+ NM_SETTING_BLUETOOTH_TYPE, NM_SETTING_BLUETOOTH_TYPE_PANU,
+ NULL);
+
+ nm_connection_add_setting (con, setting);
+ return setting;
+}
+
+static NMSetting *
+_add_setting_fcn_bond (NMConnection *con)
+{
+ NMSetting *setting;
+ NMSettingConnection *s_con;
+
+ setting = g_object_new (NM_TYPE_SETTING_BOND, NULL);
+
+ nm_connection_add_setting (con, setting);
+
+ s_con = nm_connection_get_setting_connection (con);
+
+ g_object_set (s_con,
+ NM_SETTING_CONNECTION_INTERFACE_NAME, "test-bond",
+ NULL);
+
+ return setting;
+}
+
+static NMSetting *
+_add_setting_fcn_bridge (NMConnection *con)
+{
+ NMSetting *setting;
+ NMSettingConnection *s_con;
+
+ setting = g_object_new (NM_TYPE_SETTING_BRIDGE, NULL);
+
+ nm_connection_add_setting (con, setting);
+
+ s_con = nm_connection_get_setting_connection (con);
+
+ g_object_set (s_con,
+ NM_SETTING_CONNECTION_INTERFACE_NAME, "test-bridge",
+ NULL);
+
+ return setting;
+}
+
+static NMSetting *
+_add_setting_fcn_cdma (NMConnection *con)
+{
+ NMSetting *setting;
+
+ setting = g_object_new (NM_TYPE_SETTING_CDMA,
+ NM_SETTING_CDMA_NUMBER, "test-number",
+ NULL);
+
+ nm_connection_add_setting (con, setting);
+ return setting;
+}
+
+static NMSetting *
+_add_setting_fcn_infiniband (NMConnection *con)
+{
+ NMSetting *setting;
+
+ setting = g_object_new (NM_TYPE_SETTING_INFINIBAND,
+ NM_SETTING_INFINIBAND_TRANSPORT_MODE, "connected",
+ NULL);
+
+ nm_connection_add_setting (con, setting);
+ return setting;
+}
+
+static NMSetting *
+_add_setting_fcn_olpc_mesh (NMConnection *con)
+{
+ NMSetting *setting;
+ const char *ssid_data = "ssid-test";
+ GBytes *ssid;
+
+ ssid = g_bytes_new (ssid_data, strlen (ssid_data));
+ setting = g_object_new (NM_TYPE_SETTING_OLPC_MESH,
+ NM_SETTING_OLPC_MESH_SSID, ssid,
+ NM_SETTING_OLPC_MESH_CHANNEL, 1,
+ NULL);
+ g_bytes_unref (ssid);
+
+ nm_connection_add_setting (con, setting);
+ return setting;
+}
+
+static NMSetting *
+_add_setting_fcn_team (NMConnection *con)
+{
+ NMSetting *setting;
+ NMSettingConnection *s_con;
+
+ setting = g_object_new (NM_TYPE_SETTING_TEAM, NULL);
+
+ nm_connection_add_setting (con, setting);
+
+ s_con = nm_connection_get_setting_connection (con);
+
+ g_object_set (s_con,
+ NM_SETTING_CONNECTION_INTERFACE_NAME, "test-team",
+ NULL);
+
+ return setting;
+}
+
+static NMSetting *
+_add_setting_fcn_vlan (NMConnection *con)
+{
+ NMSetting *setting;
+
+ setting = g_object_new (NM_TYPE_SETTING_VLAN,
+ NM_SETTING_VLAN_PARENT, "test-parent",
+ NULL);
+
+ nm_connection_add_setting (con, setting);
+ return setting;
+}
+
+static NMSetting *
+_add_setting_fcn_vpn (NMConnection *con)
+{
+ NMSetting *setting;
+
+ setting = g_object_new (NM_TYPE_SETTING_VPN,
+ NM_SETTING_VPN_SERVICE_TYPE, "test-vpn-service-type",
+ NULL);
+
+ nm_connection_add_setting (con, setting);
+ return setting;
+}
+
+static NMSetting *
+_add_setting_fcn_wimax (NMConnection *con)
+{
+ NMSetting *setting;
+
+ setting = g_object_new (NM_TYPE_SETTING_WIMAX,
+ NM_SETTING_WIMAX_NETWORK_NAME, "test-network",
+ NULL);
+
+ nm_connection_add_setting (con, setting);
+ return setting;
+}
+
+static NMSetting *
+_add_setting_fcn_wireless (NMConnection *con)
+{
+ NMSetting *setting;
+ const char *ssid_data = "ssid-test";
+ GBytes *ssid;
+
+ ssid = g_bytes_new (ssid_data, strlen (ssid_data));
+ setting = g_object_new (NM_TYPE_SETTING_WIRELESS,
+ NM_SETTING_WIRELESS_SSID, ssid,
+ NULL);
+ g_bytes_unref (ssid);
+
+ nm_connection_add_setting (con, setting);
+ return setting;
+}
+
+static void
+_prepare_normalizable_fcn_vlan (NMConnection *con)
+{
+ nm_connection_add_setting (con, g_object_new (NM_TYPE_SETTING_WIRED,
+ NM_SETTING_WIRED_MAC_ADDRESS, "11:22:33:44:55:66",
+ NULL));
+}
+
+static void
+test_connection_normalize_type (void)
+{
+ guint i;
+ struct {
+ const char *type;
+ gboolean normalizable;
+ NMSetting *(*add_setting_fcn) (NMConnection *con);
+ void (*prepare_normalizable_fcn) (NMConnection *con);
+ } types[] = {
+ { NM_SETTING_GENERIC_SETTING_NAME, TRUE },
+ { NM_SETTING_GSM_SETTING_NAME, TRUE },
+ { NM_SETTING_WIRED_SETTING_NAME, TRUE },
+ { NM_SETTING_VLAN_SETTING_NAME, TRUE, _add_setting_fcn_vlan, _prepare_normalizable_fcn_vlan },
+
+ { NM_SETTING_ADSL_SETTING_NAME, FALSE, _add_setting_fcn_adsl },
+ { NM_SETTING_BLUETOOTH_SETTING_NAME, FALSE, _add_setting_fcn_bluetooth },
+ { NM_SETTING_BOND_SETTING_NAME, FALSE, _add_setting_fcn_bond },
+ { NM_SETTING_BRIDGE_SETTING_NAME, FALSE, _add_setting_fcn_bridge },
+ { NM_SETTING_CDMA_SETTING_NAME, FALSE, _add_setting_fcn_cdma },
+ { NM_SETTING_INFINIBAND_SETTING_NAME, FALSE, _add_setting_fcn_infiniband },
+ { NM_SETTING_OLPC_MESH_SETTING_NAME, FALSE, _add_setting_fcn_olpc_mesh },
+ { NM_SETTING_TEAM_SETTING_NAME, FALSE, _add_setting_fcn_team },
+ { NM_SETTING_VLAN_SETTING_NAME, FALSE, _add_setting_fcn_vlan },
+ { NM_SETTING_VPN_SETTING_NAME, FALSE, _add_setting_fcn_vpn },
+ { NM_SETTING_WIMAX_SETTING_NAME, FALSE, _add_setting_fcn_wimax },
+ { NM_SETTING_WIRELESS_SETTING_NAME, FALSE, _add_setting_fcn_wireless },
+ { 0 },
+ };
+
+ for (i = 0; types[i].type; i++) {
+ const char *type = types[i].type;
+
+ if (types[i].normalizable)
+ _test_connection_normalize_type_normalizable_setting (type, types[i].prepare_normalizable_fcn);
+ else
+ _test_connection_normalize_type_unnormalizable_setting (type);
+ _test_connection_normalize_type_normalizable_type (type, types[i].add_setting_fcn);
+ }
+}
+
+static void
+test_connection_normalize_slave_type_1 (void)
+{
+ gs_unref_object NMConnection *con = NULL;
+ NMSettingConnection *s_con;
+
+ con = nmtst_create_minimal_connection ("test_connection_normalize_slave_type_1",
+ "cc4cd5df-45dc-483e-b291-6b76c2338ecb",
+ NM_SETTING_WIRED_SETTING_NAME, &s_con);
+
+ g_object_set (s_con,
+ NM_SETTING_CONNECTION_MASTER, "master0",
+ NM_SETTING_CONNECTION_SLAVE_TYPE, "invalid-type",
+ NULL);
+
+ nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
+ g_assert (!nm_connection_get_setting_by_name (con, NM_SETTING_BRIDGE_PORT_SETTING_NAME));
+
+ g_object_set (s_con,
+ NM_SETTING_CONNECTION_SLAVE_TYPE, "bridge",
+ NULL);
+
+ g_assert (!nm_connection_get_setting_by_name (con, NM_SETTING_BRIDGE_PORT_SETTING_NAME));
+ nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_SETTING);
+ g_assert (nm_connection_get_setting_by_name (con, NM_SETTING_BRIDGE_PORT_SETTING_NAME));
+ g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_BRIDGE_SETTING_NAME);
+}
+
+static void
+test_connection_normalize_slave_type_2 (void)
+{
+ gs_unref_object NMConnection *con = NULL;
+ NMSettingConnection *s_con;
+
+ con = nmtst_create_minimal_connection ("test_connection_normalize_slave_type_2",
+ "40bea008-ca72-439a-946b-e65f827656f9",
+ NM_SETTING_WIRED_SETTING_NAME, &s_con);
+
+ g_object_set (s_con,
+ NM_SETTING_CONNECTION_MASTER, "master0",
+ NM_SETTING_CONNECTION_SLAVE_TYPE, "invalid-type",
+ NULL);
+
+ nmtst_assert_connection_unnormalizable (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
+ g_assert (!nm_connection_get_setting_by_name (con, NM_SETTING_BRIDGE_PORT_SETTING_NAME));
+
+ g_object_set (s_con,
+ NM_SETTING_CONNECTION_SLAVE_TYPE, NULL,
+ NULL);
+ nm_connection_add_setting (con, nm_setting_bridge_port_new ());
+
+ g_assert (nm_connection_get_setting_by_name (con, NM_SETTING_BRIDGE_PORT_SETTING_NAME));
+ g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NULL);
+ nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_MISSING_PROPERTY);
+ g_assert (nm_connection_get_setting_by_name (con, NM_SETTING_BRIDGE_PORT_SETTING_NAME));
+ g_assert_cmpstr (nm_setting_connection_get_slave_type (s_con), ==, NM_SETTING_BRIDGE_SETTING_NAME);
+}
+
+static void
+test_connection_normalize_infiniband_mtu (void)
+{
+ gs_unref_object NMConnection *con = NULL;
+ NMSettingInfiniband *s_infini;
+
+ con = nmtst_create_minimal_connection ("test_connection_normalize_infiniband_mtu", NULL,
+ NM_SETTING_INFINIBAND_SETTING_NAME, NULL);
+
+ s_infini = nm_connection_get_setting_infiniband (con);
+ g_object_set (s_infini,
+ NM_SETTING_INFINIBAND_TRANSPORT_MODE, "connected",
+ NULL);
+ nmtst_assert_connection_verifies_and_normalizable (con);
+
+ g_object_set (s_infini,
+ NM_SETTING_INFINIBAND_TRANSPORT_MODE, "datagram",
+ NM_SETTING_INFINIBAND_MTU, (guint) 2044,
+ NULL);
+ nmtst_assert_connection_verifies_without_normalization (con);
+ g_assert_cmpint (2044, ==, nm_setting_infiniband_get_mtu (s_infini));
+
+ g_object_set (s_infini,
+ NM_SETTING_INFINIBAND_TRANSPORT_MODE, "datagram",
+ NM_SETTING_INFINIBAND_MTU, (guint) 2045,
+ NULL);
+ nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
+ g_assert_cmpint (2044, ==, nm_setting_infiniband_get_mtu (s_infini));
+
+ g_object_set (s_infini,
+ NM_SETTING_INFINIBAND_TRANSPORT_MODE, "connected",
+ NM_SETTING_INFINIBAND_MTU, (guint) 65520,
+ NULL);
+ nmtst_assert_connection_verifies_without_normalization (con);
+ g_assert_cmpint (65520, ==, nm_setting_infiniband_get_mtu (s_infini));
+
+ g_object_set (s_infini,
+ NM_SETTING_INFINIBAND_TRANSPORT_MODE, "connected",
+ NM_SETTING_INFINIBAND_MTU, (guint) 65521,
+ NULL);
+ nmtst_assert_connection_verifies_after_normalization (con, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
+ g_assert_cmpint (65520, ==, nm_setting_infiniband_get_mtu (s_infini));
+}
+
+static void
+test_setting_ip4_gateway (void)
+{
+ NMConnection *conn;
+ NMSettingIPConfig *s_ip4;
+ NMIPAddress *addr;
+ GVariant *conn_dict, *ip4_dict, *value;
+ GVariantIter iter;
+ GVariant *addr_var;
+ guint32 addr_vals_0[] = { htonl (0xc0a8010a), 0x00000018, htonl (0x00000000) };
+ guint32 addr_vals_1[] = { htonl (0xc0a8010b), 0x00000018, htonl (0xc0a80101) };
+ GVariantBuilder addrs_builder;
+ GError *error = NULL;
+
+ g_assert_cmpstr (nm_utils_inet4_ntop (addr_vals_0[0], NULL), ==, "192.168.1.10");
+
+ /* When serializing on the daemon side, ipv4.gateway is copied to the first
+ * entry of ipv4.addresses
+ */
+ conn = nmtst_create_minimal_connection ("test_setting_ip4_gateway", NULL,
+ NM_SETTING_WIRED_SETTING_NAME, NULL);
+ s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
+ g_object_set (s_ip4,
+ NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
+ NM_SETTING_IP_CONFIG_GATEWAY, "192.168.1.1",
+ NULL);
+ nm_connection_add_setting (conn, NM_SETTING (s_ip4));
+
+ addr = nm_ip_address_new (AF_INET, "192.168.1.10", 24, &error);
+ g_assert_no_error (error);
+ nm_setting_ip_config_add_address (s_ip4, addr);
+ nm_ip_address_unref (addr);
+
+ _nm_utils_is_manager_process = TRUE;
+ conn_dict = nm_connection_to_dbus (conn, NM_CONNECTION_SERIALIZE_ALL);
+ _nm_utils_is_manager_process = FALSE;
+ g_object_unref (conn);
+
+ ip4_dict = g_variant_lookup_value (conn_dict, NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
+ g_assert (ip4_dict != NULL);
+
+ value = g_variant_lookup_value (ip4_dict, NM_SETTING_IP_CONFIG_GATEWAY, G_VARIANT_TYPE_STRING);
+ g_assert (value != NULL);
+ g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "192.168.1.1");
+ g_variant_unref (value);
+
+ value = g_variant_lookup_value (ip4_dict, NM_SETTING_IP_CONFIG_ADDRESSES, G_VARIANT_TYPE ("aau"));
+ g_assert (value != NULL);
+
+ g_variant_iter_init (&iter, value);
+ while (g_variant_iter_next (&iter, "@au", &addr_var)) {
+ const guint32 *addr_array;
+ gsize length;
+
+ addr_array = g_variant_get_fixed_array (addr_var, &length, sizeof (guint32));
+ g_assert_cmpint (length, ==, 3);
+ g_assert_cmpstr (nm_utils_inet4_ntop (addr_array[2], NULL), ==, "192.168.1.1");
+ g_variant_unref (addr_var);
+ }
+ g_variant_unref (value);
+
+ g_variant_unref (ip4_dict);
+
+ /* When deserializing an old-style connection, the first non-0 gateway in
+ * ipv4.addresses is copied to :gateway.
+ */
+ NMTST_VARIANT_EDITOR (conn_dict,
+ NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP4_CONFIG_SETTING_NAME,
+ NM_SETTING_IP_CONFIG_GATEWAY);
+ NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP4_CONFIG_SETTING_NAME,
+ "address-data");
+ );
+
+ conn = nm_simple_connection_new_from_dbus (conn_dict, &error);
+ g_assert_no_error (error);
+
+ s_ip4 = (NMSettingIPConfig *) nm_connection_get_setting_ip4_config (conn);
+ g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, "192.168.1.1");
+
+ g_object_unref (conn);
+
+ /* Try again with the gateway in the second address. */
+ g_variant_builder_init (&addrs_builder, G_VARIANT_TYPE ("aau"));
+ g_variant_builder_add (&addrs_builder, "@au",
+ g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
+ addr_vals_0, 3, 4));
+ g_variant_builder_add (&addrs_builder, "@au",
+ g_variant_new_fixed_array (G_VARIANT_TYPE_UINT32,
+ addr_vals_1, 3, 4));
+
+ NMTST_VARIANT_EDITOR (conn_dict,
+ NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_IP4_CONFIG_SETTING_NAME,
+ "addresses", "aau", &addrs_builder);
+ );
+
+ conn = nm_simple_connection_new_from_dbus (conn_dict, &error);
+ g_assert_no_error (error);
+ g_variant_unref (conn_dict);
+
+ s_ip4 = (NMSettingIPConfig *) nm_connection_get_setting_ip4_config (conn);
+ g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip4), ==, "192.168.1.1");
+
+ g_object_unref (conn);
+}
+
+static void
+test_setting_ip6_gateway (void)
+{
+ NMConnection *conn;
+ NMSettingIPConfig *s_ip6;
+ NMIPAddress *addr;
+ GVariant *conn_dict, *ip6_dict, *value;
+ GVariantIter iter;
+ GVariant *gateway_var;
+ GVariantBuilder addrs_builder;
+ guint8 addr_bytes_0[] = { 0xab, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a };
+ guint8 addr_bytes_1[] = { 0xab, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b };
+ guint8 gateway_bytes_1[] = { 0xab, 0xcd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
+ GError *error = NULL;
+
+ /* When serializing on the daemon side, ipv6.gateway is copied to the first
+ * entry of ipv6.addresses
+ */
+ conn = nmtst_create_minimal_connection ("test_setting_ip6_gateway", NULL,
+ NM_SETTING_WIRED_SETTING_NAME, NULL);
+ s_ip6 = (NMSettingIPConfig *) nm_setting_ip6_config_new ();
+ g_object_set (s_ip6,
+ NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_MANUAL,
+ NM_SETTING_IP_CONFIG_GATEWAY, "abcd::1",
+ NULL);
+ nm_connection_add_setting (conn, NM_SETTING (s_ip6));
+
+ addr = nm_ip_address_new (AF_INET6, "abcd::10", 64, &error);
+ g_assert_no_error (error);
+ nm_setting_ip_config_add_address (s_ip6, addr);
+ nm_ip_address_unref (addr);
+
+ _nm_utils_is_manager_process = TRUE;
+ conn_dict = nm_connection_to_dbus (conn, NM_CONNECTION_SERIALIZE_ALL);
+ _nm_utils_is_manager_process = FALSE;
+ g_object_unref (conn);
+
+ ip6_dict = g_variant_lookup_value (conn_dict, NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_VARIANT_TYPE_SETTING);
+ g_assert (ip6_dict != NULL);
+
+ value = g_variant_lookup_value (ip6_dict, NM_SETTING_IP_CONFIG_GATEWAY, G_VARIANT_TYPE_STRING);
+ g_assert (value != NULL);
+ g_assert_cmpstr (g_variant_get_string (value, NULL), ==, "abcd::1");
+
+ value = g_variant_lookup_value (ip6_dict, NM_SETTING_IP_CONFIG_ADDRESSES, G_VARIANT_TYPE ("a(ayuay)"));
+ g_assert (value != NULL);
+
+ g_variant_iter_init (&iter, value);
+ while (g_variant_iter_next (&iter, "(@ayu@ay)", NULL, NULL, &gateway_var)) {
+ const guint8 *gateway_bytes;
+ gsize length;
+
+ gateway_bytes = g_variant_get_fixed_array (gateway_var, &length, 1);
+ g_assert_cmpint (length, ==, 16);
+ g_assert_cmpstr (nm_utils_inet6_ntop ((struct in6_addr *) gateway_bytes, NULL), ==, "abcd::1");
+ g_variant_unref (gateway_var);
+ }
+ g_variant_unref (value);
+
+ g_variant_unref (ip6_dict);
+
+ /* When deserializing an old-style connection, the first non-0 gateway in
+ * ipv6.addresses is copied to :gateway.
+ */
+ NMTST_VARIANT_EDITOR (conn_dict,
+ NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP6_CONFIG_SETTING_NAME,
+ NM_SETTING_IP_CONFIG_GATEWAY);
+ NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP6_CONFIG_SETTING_NAME,
+ "address-data");
+ );
+
+ conn = nm_simple_connection_new_from_dbus (conn_dict, &error);
+ g_assert_no_error (error);
+
+ s_ip6 = (NMSettingIPConfig *) nm_connection_get_setting_ip6_config (conn);
+ g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip6), ==, "abcd::1");
+
+ g_object_unref (conn);
+
+ /* Try again with the gateway in the second address. */
+ g_variant_builder_init (&addrs_builder, G_VARIANT_TYPE ("a(ayuay)"));
+ g_variant_builder_add (&addrs_builder, "(@ayu@ay)",
+ g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+ addr_bytes_0, 16, 1),
+ 64,
+ g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+ &in6addr_any, 16, 1));
+ g_variant_builder_add (&addrs_builder, "(@ayu@ay)",
+ g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+ addr_bytes_1, 16, 1),
+ 64,
+ g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
+ gateway_bytes_1, 16, 1));
+
+ NMTST_VARIANT_EDITOR (conn_dict,
+ NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_IP6_CONFIG_SETTING_NAME,
+ "addresses", "a(ayuay)", &addrs_builder);
+ );
+
+ conn = nm_simple_connection_new_from_dbus (conn_dict, &error);
+ g_assert_no_error (error);
+ g_variant_unref (conn_dict);
+
+ s_ip6 = (NMSettingIPConfig *) nm_connection_get_setting_ip6_config (conn);
+ g_assert_cmpstr (nm_setting_ip_config_get_gateway (s_ip6), ==, "abcd::1");
+
+ g_object_unref (conn);
+}
+
+typedef struct {
+ const char *str;
+ const guint8 expected[20];
+ const guint expected_len;
+} HexItem;
+
+static void
+test_hexstr2bin (void)
+{
+ static const HexItem items[] = {
+ { "aaBBCCddDD10496a", { 0xaa, 0xbb, 0xcc, 0xdd, 0xdd, 0x10, 0x49, 0x6a }, 8 },
+ { "aa:bb:cc:dd:10:49:6a", { 0xaa, 0xbb, 0xcc, 0xdd, 0x10, 0x49, 0x6a }, 7 },
+ { "0xccddeeff", { 0xcc, 0xdd, 0xee, 0xff }, 4 },
+ { "1:2:66:77:80", { 0x01, 0x02, 0x66, 0x77, 0x80 }, 5 },
+ { "e", { 0x0e }, 1 },
+ { "aabb1199:" },
+ { ":aabb1199" },
+ { "aabb$$dd" },
+ { "aab:ccc:ddd" },
+ { "aab::ccc:ddd" },
+ };
+ GBytes *b;
+ guint i;
+
+ for (i = 0; i < G_N_ELEMENTS (items); i++) {
+ b = nm_utils_hexstr2bin (items[i].str);
+ 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);
+ } else
+ g_assert (b == NULL);
+ }
+}
+
+/******************************************************************************/
+
+#define UUID_NIL "00000000-0000-0000-0000-000000000000"
+#define UUID_NS_DNS "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
+
+static void
+_test_uuid (int uuid_type, const char *expected_uuid, const char *str, gssize slen, gpointer type_args)
+{
+ gs_free char *uuid_test = NULL;
+
+ uuid_test = nm_utils_uuid_generate_from_string (str, slen, uuid_type, type_args);
+
+ g_assert (uuid_test);
+ g_assert (nm_utils_is_uuid (uuid_test));
+
+ if (strcmp (uuid_test, expected_uuid)) {
+ g_error ("UUID test failed: type=%d; text=%s, len=%lld, uuid=%s, expected=%s", uuid_type,
+ str, (long long) slen, uuid_test, expected_uuid);
+ }
+
+ if (slen < 0) {
+ /* also test that passing slen==-1 yields the same result as passing strlen(str). */
+ _test_uuid (uuid_type, expected_uuid, str, strlen (str), type_args);
+ } else if (str && slen == 0) {
+ /* also test if we accept NULL for slen==0 */
+ _test_uuid (uuid_type, expected_uuid, NULL, 0, type_args);
+ }
+
+ if (uuid_type == NM_UTILS_UUID_TYPE_VARIANT3 && !type_args) {
+ /* For NM_UTILS_UUID_TYPE_VARIANT3, a missing @type_args is equal to UUID_NIL */
+ _test_uuid (uuid_type, expected_uuid, str, slen, UUID_NIL);
+ }
+}
+
+static void
+test_nm_utils_uuid_generate_from_string (void)
+{
+ _test_uuid (NM_UTILS_UUID_TYPE_LEGACY, "d41d8cd9-8f00-b204-e980-0998ecf8427e", "", -1, NULL);
+ _test_uuid (NM_UTILS_UUID_TYPE_LEGACY, "0cc175b9-c0f1-b6a8-31c3-99e269772661", "a", -1, NULL);
+ _test_uuid (NM_UTILS_UUID_TYPE_LEGACY, "098f6bcd-4621-d373-cade-4e832627b4f6", "test", -1, NULL);
+ _test_uuid (NM_UTILS_UUID_TYPE_LEGACY, "70350f60-27bc-e371-3f6b-76473084309b", "a\0b", 3, NULL);
+ _test_uuid (NM_UTILS_UUID_TYPE_LEGACY, "59c0547b-7fe2-1c15-2cce-e328e8bf6742", "/etc/NetworkManager/system-connections/em1", -1, NULL);
+
+ _test_uuid (NM_UTILS_UUID_TYPE_VARIANT3, "4ae71336-e44b-39bf-b9d2-752e234818a5", "", -1, NULL);
+ _test_uuid (NM_UTILS_UUID_TYPE_VARIANT3, "0531103a-d8fc-3dd4-b972-d98e4750994e", "a", -1, NULL);
+ _test_uuid (NM_UTILS_UUID_TYPE_VARIANT3, "96e17d7a-ac89-38cf-95e1-bf5098da34e1", "test", -1, NULL);
+ _test_uuid (NM_UTILS_UUID_TYPE_VARIANT3, "8156568e-4ae6-3f34-a93e-18e2c6cbbf78", "a\0b", 3, NULL);
+
+ _test_uuid (NM_UTILS_UUID_TYPE_VARIANT3, "c87ee674-4ddc-3efe-a74e-dfe25da5d7b3", "", -1, UUID_NS_DNS);
+ _test_uuid (NM_UTILS_UUID_TYPE_VARIANT3, "4c104dd0-4821-30d5-9ce3-0e7a1f8b7c0d", "a", -1, UUID_NS_DNS);
+ _test_uuid (NM_UTILS_UUID_TYPE_VARIANT3, "45a113ac-c7f2-30b0-90a5-a399ab912716", "test", -1, UUID_NS_DNS);
+ _test_uuid (NM_UTILS_UUID_TYPE_VARIANT3, "002a0ada-f547-375a-bab5-896a11d1927e", "a\0b", 3, UUID_NS_DNS);
+}
+
+/******************************************************************************/
+
+NMTST_DEFINE ();
+
+int main (int argc, char **argv)
+{
+ nmtst_init (&argc, &argv, TRUE);
+
+ /* The tests */
+ g_test_add_func ("/core/general/test_setting_vpn_items", test_setting_vpn_items);
+ g_test_add_func ("/core/general/test_setting_vpn_update_secrets", test_setting_vpn_update_secrets);
+ g_test_add_func ("/core/general/test_setting_vpn_modify_during_foreach", test_setting_vpn_modify_during_foreach);
+ g_test_add_func ("/core/general/test_setting_ip4_config_labels", test_setting_ip4_config_labels);
+ g_test_add_func ("/core/general/test_setting_ip4_config_address_data", test_setting_ip4_config_address_data);
+ g_test_add_func ("/core/general/test_setting_gsm_apn_spaces", test_setting_gsm_apn_spaces);
+ g_test_add_func ("/core/general/test_setting_gsm_apn_bad_chars", test_setting_gsm_apn_bad_chars);
+ g_test_add_func ("/core/general/test_setting_gsm_apn_underscore", test_setting_gsm_apn_underscore);
+ g_test_add_func ("/core/general/test_setting_gsm_without_number", test_setting_gsm_without_number);
+ g_test_add_func ("/core/general/test_setting_to_dbus_all", test_setting_to_dbus_all);
+ g_test_add_func ("/core/general/test_setting_to_dbus_no_secrets", test_setting_to_dbus_no_secrets);
+ g_test_add_func ("/core/general/test_setting_to_dbus_only_secrets", test_setting_to_dbus_only_secrets);
+ g_test_add_func ("/core/general/test_setting_to_dbus_transform", test_setting_to_dbus_transform);
+ g_test_add_func ("/core/general/test_setting_to_dbus_enum", test_setting_to_dbus_enum);
+ g_test_add_func ("/core/general/test_setting_compare_id", test_setting_compare_id);
+ g_test_add_func ("/core/general/test_setting_compare_timestamp", test_setting_compare_timestamp);
+#define ADD_FUNC(func, secret_flags, comp_flags, remove_secret) \
+ g_test_add_data_func_full ("/core/general/" G_STRINGIFY (func), \
+ test_data_compare_secrets_new (secret_flags, comp_flags, remove_secret), \
+ func, g_free)
+ ADD_FUNC (test_setting_compare_secrets, NM_SETTING_SECRET_FLAG_AGENT_OWNED, NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS, TRUE);
+ ADD_FUNC (test_setting_compare_secrets, NM_SETTING_SECRET_FLAG_NOT_SAVED, NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS, TRUE);
+ ADD_FUNC (test_setting_compare_secrets, NM_SETTING_SECRET_FLAG_NONE, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, TRUE);
+ ADD_FUNC (test_setting_compare_secrets, NM_SETTING_SECRET_FLAG_NONE, NM_SETTING_COMPARE_FLAG_EXACT, FALSE);
+ ADD_FUNC (test_setting_compare_vpn_secrets, NM_SETTING_SECRET_FLAG_AGENT_OWNED, NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS, TRUE);
+ ADD_FUNC (test_setting_compare_vpn_secrets, NM_SETTING_SECRET_FLAG_NOT_SAVED, NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS, TRUE);
+ ADD_FUNC (test_setting_compare_vpn_secrets, NM_SETTING_SECRET_FLAG_NONE, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, TRUE);
+ ADD_FUNC (test_setting_compare_vpn_secrets, NM_SETTING_SECRET_FLAG_NONE, NM_SETTING_COMPARE_FLAG_EXACT, FALSE);
+ g_test_add_func ("/core/general/test_setting_old_uuid", test_setting_old_uuid);
+
+ g_test_add_func ("/core/general/test_connection_to_dbus_setting_name", test_connection_to_dbus_setting_name);
+ g_test_add_func ("/core/general/test_connection_to_dbus_deprecated_props", test_connection_to_dbus_deprecated_props);
+ g_test_add_func ("/core/general/test_setting_new_from_dbus", test_setting_new_from_dbus);
+ g_test_add_func ("/core/general/test_setting_new_from_dbus_transform", test_setting_new_from_dbus_transform);
+ g_test_add_func ("/core/general/test_setting_new_from_dbus_enum", test_setting_new_from_dbus_enum);
+ g_test_add_func ("/core/general/test_connection_replace_settings", test_connection_replace_settings);
+ g_test_add_func ("/core/general/test_connection_replace_settings_from_connection", test_connection_replace_settings_from_connection);
+ g_test_add_func ("/core/general/test_connection_replace_settings_bad", test_connection_replace_settings_bad);
+ g_test_add_func ("/core/general/test_connection_new_from_dbus", test_connection_new_from_dbus);
+ g_test_add_func ("/core/general/test_connection_normalize_virtual_iface_name", test_connection_normalize_virtual_iface_name);
+ g_test_add_func ("/core/general/test_connection_normalize_uuid", test_connection_normalize_uuid);
+ g_test_add_func ("/core/general/test_connection_normalize_type", test_connection_normalize_type);
+ g_test_add_func ("/core/general/test_connection_normalize_slave_type_1", test_connection_normalize_slave_type_1);
+ g_test_add_func ("/core/general/test_connection_normalize_slave_type_2", test_connection_normalize_slave_type_2);
+ g_test_add_func ("/core/general/test_connection_normalize_infiniband_mtu", test_connection_normalize_infiniband_mtu);
+
+ g_test_add_func ("/core/general/test_setting_connection_permissions_helpers", test_setting_connection_permissions_helpers);
+ g_test_add_func ("/core/general/test_setting_connection_permissions_property", test_setting_connection_permissions_property);
+
+ g_test_add_func ("/core/general/test_connection_compare_same", test_connection_compare_same);
+ g_test_add_func ("/core/general/test_connection_compare_key_only_in_a", test_connection_compare_key_only_in_a);
+ g_test_add_func ("/core/general/test_connection_compare_setting_only_in_a", test_connection_compare_setting_only_in_a);
+ g_test_add_func ("/core/general/test_connection_compare_key_only_in_b", test_connection_compare_key_only_in_b);
+ g_test_add_func ("/core/general/test_connection_compare_setting_only_in_b", test_connection_compare_setting_only_in_b);
+
+ g_test_add_func ("/core/general/test_connection_diff_a_only", test_connection_diff_a_only);
+ g_test_add_func ("/core/general/test_connection_diff_same", test_connection_diff_same);
+ g_test_add_func ("/core/general/test_connection_diff_different", test_connection_diff_different);
+ g_test_add_func ("/core/general/test_connection_diff_no_secrets", test_connection_diff_no_secrets);
+ g_test_add_func ("/core/general/test_connection_diff_inferrable", test_connection_diff_inferrable);
+ g_test_add_func ("/core/general/test_connection_good_base_types", test_connection_good_base_types);
+ g_test_add_func ("/core/general/test_connection_bad_base_types", test_connection_bad_base_types);
+
+ g_test_add_func ("/core/general/test_hwaddr_aton_ether_normal", test_hwaddr_aton_ether_normal);
+ g_test_add_func ("/core/general/test_hwaddr_aton_ib_normal", test_hwaddr_aton_ib_normal);
+ g_test_add_func ("/core/general/test_hwaddr_aton_no_leading_zeros", test_hwaddr_aton_no_leading_zeros);
+ g_test_add_func ("/core/general/test_hwaddr_aton_malformed", test_hwaddr_aton_malformed);
+ g_test_add_func ("/core/general/test_hwaddr_equal", test_hwaddr_equal);
+ g_test_add_func ("/core/general/test_hwaddr_canonical", test_hwaddr_canonical);
+
+ g_test_add_func ("/core/general/test_ip4_prefix_to_netmask", test_ip4_prefix_to_netmask);
+ g_test_add_func ("/core/general/test_ip4_netmask_to_prefix", test_ip4_netmask_to_prefix);
+
+ g_test_add_func ("/core/general/test_connection_changed_signal", test_connection_changed_signal);
+ g_test_add_func ("/core/general/test_setting_connection_changed_signal", test_setting_connection_changed_signal);
+ g_test_add_func ("/core/general/test_setting_bond_changed_signal", test_setting_bond_changed_signal);
+ g_test_add_func ("/core/general/test_setting_ip4_changed_signal", test_setting_ip4_changed_signal);
+ g_test_add_func ("/core/general/test_setting_ip6_changed_signal", test_setting_ip6_changed_signal);
+ g_test_add_func ("/core/general/test_setting_vlan_changed_signal", test_setting_vlan_changed_signal);
+ g_test_add_func ("/core/general/test_setting_vpn_changed_signal", test_setting_vpn_changed_signal);
+ g_test_add_func ("/core/general/test_setting_wired_changed_signal", test_setting_wired_changed_signal);
+ g_test_add_func ("/core/general/test_setting_wireless_changed_signal", test_setting_wireless_changed_signal);
+ g_test_add_func ("/core/general/test_setting_wireless_security_changed_signal", test_setting_wireless_security_changed_signal);
+ g_test_add_func ("/core/general/test_setting_802_1x_changed_signal", test_setting_802_1x_changed_signal);
+ g_test_add_func ("/core/general/test_setting_ip4_gateway", test_setting_ip4_gateway);
+ g_test_add_func ("/core/general/test_setting_ip6_gateway", test_setting_ip6_gateway);
+
+ g_test_add_func ("/core/general/hexstr2bin", test_hexstr2bin);
+ g_test_add_func ("/core/general/test_nm_utils_uuid_generate_from_string", test_nm_utils_uuid_generate_from_string);
+
+ return g_test_run ();
+}
+
diff --git a/libnm-core/tests/test-secrets.c b/libnm-core/tests/test-secrets.c
new file mode 100644
index 000000000..1254dfffe
--- /dev/null
+++ b/libnm-core/tests/test-secrets.c
@@ -0,0 +1,766 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2008 - 2011 Red Hat, Inc.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <string.h>
+
+#include "nm-setting-8021x.h"
+#include "nm-setting-cdma.h"
+#include "nm-setting-connection.h"
+#include "nm-setting-gsm.h"
+#include "nm-setting-ip4-config.h"
+#include "nm-setting-ppp.h"
+#include "nm-setting-pppoe.h"
+#include "nm-setting-vpn.h"
+#include "nm-setting-wired.h"
+#include "nm-setting-wireless-security.h"
+#include "nm-setting-wireless.h"
+#include "nm-simple-connection.h"
+#include "nm-utils.h"
+
+#include "nm-test-utils.h"
+
+#define TEST_NEED_SECRETS_EAP_TLS_CA_CERT TEST_CERT_DIR "/test_ca_cert.pem"
+#define TEST_NEED_SECRETS_EAP_TLS_CLIENT_CERT TEST_CERT_DIR "/test_key_and_cert.pem"
+#define TEST_NEED_SECRETS_EAP_TLS_PRIVATE_KEY TEST_CERT_DIR "/test_key_and_cert.pem"
+
+static gboolean
+find_hints_item (GPtrArray *hints, const char *item)
+{
+ int i;
+
+ for (i = 0; i < hints->len; i++) {
+ if (!strcmp (item, (const char *) g_ptr_array_index (hints, i)))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static NMConnection *
+make_tls_connection (const char *detail, NMSetting8021xCKScheme scheme)
+{
+ NMConnection *connection;
+ NMSettingConnection *s_con;
+ NMSetting8021x *s_8021x;
+ NMSettingWired *s_wired;
+ NMSettingIP4Config *s_ip4;
+ char *uuid;
+ gboolean success;
+ GError *error = NULL;
+
+ connection = nm_simple_connection_new ();
+
+ /* Connection setting */
+ s_con = (NMSettingConnection *) nm_setting_connection_new ();
+ nm_connection_add_setting (connection, NM_SETTING (s_con));
+
+ uuid = nm_utils_uuid_generate ();
+ g_object_set (s_con,
+ NM_SETTING_CONNECTION_ID, "Test Need TLS Secrets",
+ NM_SETTING_CONNECTION_UUID, uuid,
+ NM_SETTING_CONNECTION_AUTOCONNECT, TRUE,
+ NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
+ NULL);
+ g_free (uuid);
+
+ /* Wired setting */
+ s_wired = (NMSettingWired *) nm_setting_wired_new ();
+ nm_connection_add_setting (connection, NM_SETTING (s_wired));
+
+ /* Wireless security setting */
+ s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
+ nm_connection_add_setting (connection, NM_SETTING (s_8021x));
+
+ g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, "Bill Smith", NULL);
+
+ nm_setting_802_1x_add_eap_method (s_8021x, "tls");
+
+ success = nm_setting_802_1x_set_ca_cert (s_8021x,
+ TEST_NEED_SECRETS_EAP_TLS_CA_CERT,
+ scheme,
+ NULL,
+ &error);
+ ASSERT (success == TRUE,
+ detail, "failed to set CA certificate '%s': %s",
+ TEST_NEED_SECRETS_EAP_TLS_CA_CERT, error->message);
+
+ success = nm_setting_802_1x_set_client_cert (s_8021x,
+ TEST_NEED_SECRETS_EAP_TLS_CLIENT_CERT,
+ scheme,
+ NULL,
+ &error);
+ ASSERT (success == TRUE,
+ detail, "failed to set client certificate '%s': %s",
+ TEST_NEED_SECRETS_EAP_TLS_CLIENT_CERT, error->message);
+
+ success = nm_setting_802_1x_set_private_key (s_8021x,
+ TEST_NEED_SECRETS_EAP_TLS_PRIVATE_KEY,
+ "test",
+ scheme,
+ NULL,
+ &error);
+ ASSERT (success == TRUE,
+ detail, "failed to set private key '%s': %s",
+ TEST_NEED_SECRETS_EAP_TLS_PRIVATE_KEY, error->message);
+
+ /* IP4 setting */
+ s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
+ nm_connection_add_setting (connection, NM_SETTING (s_ip4));
+
+ g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
+
+ ASSERT (nm_connection_verify (connection, &error) == TRUE,
+ detail, "failed to verify connection: %s",
+ (error && error->message) ? error->message : "(unknown)");
+
+ return connection;
+}
+
+static void
+test_need_tls_secrets_path (void)
+{
+ NMConnection *connection;
+ const char *setting_name;
+ GPtrArray *hints = NULL;
+
+ connection = make_tls_connection ("need-tls-secrets-path-key", NM_SETTING_802_1X_CK_SCHEME_PATH);
+ ASSERT (connection != NULL,
+ "need-tls-secrets-path-key",
+ "error creating test connection");
+
+ /* Ensure we don't need any secrets since we just set up the connection */
+ setting_name = nm_connection_need_secrets (connection, &hints);
+ ASSERT (setting_name == NULL,
+ "need-tls-secrets-path-key",
+ "secrets are unexpectedly required");
+ ASSERT (hints == NULL,
+ "need-tls-secrets-path-key",
+ "hints should be NULL since no secrets were required");
+
+ /* Connection is good; clear secrets and ensure private key password is then required */
+ nm_connection_clear_secrets (connection);
+
+ hints = NULL;
+ setting_name = nm_connection_need_secrets (connection, &hints);
+ ASSERT (setting_name != NULL,
+ "need-tls-secrets-path-key-password",
+ "unexpected secrets success");
+ ASSERT (strcmp (setting_name, NM_SETTING_802_1X_SETTING_NAME) == 0,
+ "need-tls-secrets-path-key-password",
+ "unexpected setting secrets required");
+
+ ASSERT (hints != NULL,
+ "need-tls-secrets-path-key-password",
+ "expected returned secrets hints");
+ ASSERT (find_hints_item (hints, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD),
+ "need-tls-secrets-path-key-password",
+ "expected to require private key password, but it wasn't");
+
+ g_object_unref (connection);
+}
+
+static void
+test_need_tls_secrets_blob (void)
+{
+ NMConnection *connection;
+ const char *setting_name;
+ GPtrArray *hints = NULL;
+
+ connection = make_tls_connection ("need-tls-secrets-blob-key", NM_SETTING_802_1X_CK_SCHEME_BLOB);
+ ASSERT (connection != NULL,
+ "need-tls-secrets-blob-key",
+ "error creating test connection");
+
+ /* Ensure we don't need any secrets since we just set up the connection */
+ setting_name = nm_connection_need_secrets (connection, &hints);
+ ASSERT (setting_name == NULL,
+ "need-tls-secrets-blob-key",
+ "secrets are unexpectedly required");
+ ASSERT (hints == NULL,
+ "need-tls-secrets-blob-key",
+ "hints should be NULL since no secrets were required");
+
+ /* Clear secrets and ensure password is again required */
+ nm_connection_clear_secrets (connection);
+
+ hints = NULL;
+ setting_name = nm_connection_need_secrets (connection, &hints);
+ ASSERT (setting_name != NULL,
+ "need-tls-secrets-blob-key-password",
+ "unexpected secrets success");
+ ASSERT (strcmp (setting_name, NM_SETTING_802_1X_SETTING_NAME) == 0,
+ "need-tls-secrets-blob-key-password",
+ "unexpected setting secrets required");
+
+ ASSERT (hints != NULL,
+ "need-tls-secrets-blob-key-password",
+ "expected returned secrets hints");
+ ASSERT (find_hints_item (hints, NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD),
+ "need-tls-secrets-blob-key-password",
+ "expected to require private key password, but it wasn't");
+
+ g_object_unref (connection);
+}
+
+static NMConnection *
+make_tls_phase2_connection (const char *detail, NMSetting8021xCKScheme scheme)
+{
+ NMConnection *connection;
+ NMSettingConnection *s_con;
+ NMSetting8021x *s_8021x;
+ NMSettingWired *s_wired;
+ NMSettingIP4Config *s_ip4;
+ char *uuid;
+ gboolean success;
+ GError *error = NULL;
+
+ connection = nm_simple_connection_new ();
+
+ /* Connection setting */
+ s_con = (NMSettingConnection *) nm_setting_connection_new ();
+ nm_connection_add_setting (connection, NM_SETTING (s_con));
+
+ uuid = nm_utils_uuid_generate ();
+ g_object_set (s_con,
+ NM_SETTING_CONNECTION_ID, "Test Need TLS Secrets",
+ NM_SETTING_CONNECTION_UUID, uuid,
+ NM_SETTING_CONNECTION_AUTOCONNECT, TRUE,
+ NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME,
+ NULL);
+ g_free (uuid);
+
+ /* Wired setting */
+ s_wired = (NMSettingWired *) nm_setting_wired_new ();
+ nm_connection_add_setting (connection, NM_SETTING (s_wired));
+
+ /* Wireless security setting */
+ s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
+ nm_connection_add_setting (connection, NM_SETTING (s_8021x));
+
+ g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY, "blahblah", NULL);
+ g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, "Bill Smith", NULL);
+
+ nm_setting_802_1x_add_eap_method (s_8021x, "ttls");
+ g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, "tls", NULL);
+
+ success = nm_setting_802_1x_set_phase2_ca_cert (s_8021x,
+ TEST_NEED_SECRETS_EAP_TLS_CA_CERT,
+ scheme,
+ NULL,
+ &error);
+ ASSERT (success == TRUE,
+ detail, "failed to set phase2 CA certificate '%s': %s",
+ TEST_NEED_SECRETS_EAP_TLS_CA_CERT, error->message);
+
+ success = nm_setting_802_1x_set_phase2_client_cert (s_8021x,
+ TEST_NEED_SECRETS_EAP_TLS_CLIENT_CERT,
+ scheme,
+ NULL,
+ &error);
+ ASSERT (success == TRUE,
+ detail, "failed to set phase2 client certificate '%s': %s",
+ TEST_NEED_SECRETS_EAP_TLS_CLIENT_CERT, error->message);
+
+ success = nm_setting_802_1x_set_phase2_private_key (s_8021x,
+ TEST_NEED_SECRETS_EAP_TLS_PRIVATE_KEY,
+ "test",
+ scheme,
+ NULL,
+ &error);
+ ASSERT (success == TRUE,
+ detail, "failed to set phase2 private key '%s': %s",
+ TEST_NEED_SECRETS_EAP_TLS_PRIVATE_KEY, error->message);
+
+ /* IP4 setting */
+ s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
+ nm_connection_add_setting (connection, NM_SETTING (s_ip4));
+
+ g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
+
+ ASSERT (nm_connection_verify (connection, &error) == TRUE,
+ detail, "failed to verify connection: %s",
+ (error && error->message) ? error->message : "(unknown)");
+
+ return connection;
+}
+
+static void
+test_need_tls_phase2_secrets_path (void)
+{
+ NMConnection *connection;
+ const char *setting_name;
+ GPtrArray *hints = NULL;
+
+ connection = make_tls_phase2_connection ("need-tls-phase2-secrets-path-key",
+ NM_SETTING_802_1X_CK_SCHEME_PATH);
+ ASSERT (connection != NULL,
+ "need-tls-phase2-secrets-path-key",
+ "error creating test connection");
+
+ /* Ensure we don't need any secrets since we just set up the connection */
+ setting_name = nm_connection_need_secrets (connection, &hints);
+ ASSERT (setting_name == NULL,
+ "need-tls-phase2-secrets-path-key",
+ "secrets are unexpectedly required");
+ ASSERT (hints == NULL,
+ "need-tls-phase2-secrets-path-key",
+ "hints should be NULL since no secrets were required");
+
+ /* Connection is good; clear secrets and ensure private key password is then required */
+ nm_connection_clear_secrets (connection);
+
+ hints = NULL;
+ setting_name = nm_connection_need_secrets (connection, &hints);
+ ASSERT (setting_name != NULL,
+ "need-tls-phase2-secrets-path-key-password",
+ "unexpected secrets success");
+ ASSERT (strcmp (setting_name, NM_SETTING_802_1X_SETTING_NAME) == 0,
+ "need-tls-phase2-secrets-path-key-password",
+ "unexpected setting secrets required");
+
+ ASSERT (hints != NULL,
+ "need-tls-phase2-secrets-path-key-password",
+ "expected returned secrets hints");
+ ASSERT (find_hints_item (hints, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD),
+ "need-tls-phase2-secrets-path-key-password",
+ "expected to require private key password, but it wasn't");
+
+ g_object_unref (connection);
+}
+
+static void
+test_need_tls_phase2_secrets_blob (void)
+{
+ NMConnection *connection;
+ const char *setting_name;
+ GPtrArray *hints = NULL;
+
+ connection = make_tls_phase2_connection ("need-tls-phase2-secrets-blob-key",
+ NM_SETTING_802_1X_CK_SCHEME_BLOB);
+ ASSERT (connection != NULL,
+ "need-tls-phase2-secrets-blob-key",
+ "error creating test connection");
+
+ /* Ensure we don't need any secrets since we just set up the connection */
+ setting_name = nm_connection_need_secrets (connection, &hints);
+ ASSERT (setting_name == NULL,
+ "need-tls-phase2-secrets-blob-key",
+ "secrets are unexpectedly required");
+ ASSERT (hints == NULL,
+ "need-tls-phase2-secrets-blob-key",
+ "hints should be NULL since no secrets were required");
+
+ /* Connection is good; clear secrets and ensure private key password is then required */
+ nm_connection_clear_secrets (connection);
+
+ hints = NULL;
+ setting_name = nm_connection_need_secrets (connection, &hints);
+ ASSERT (setting_name != NULL,
+ "need-tls-phase2-secrets-blob-key-password",
+ "unexpected secrets success");
+ ASSERT (strcmp (setting_name, NM_SETTING_802_1X_SETTING_NAME) == 0,
+ "need-tls-phase2-secrets-blob-key-password",
+ "unexpected setting secrets required");
+
+ ASSERT (hints != NULL,
+ "need-tls-phase2-secrets-blob-key-password",
+ "expected returned secrets hints");
+ ASSERT (find_hints_item (hints, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD),
+ "need-tls-phase2-secrets-blob-key-password",
+ "expected to require private key password, but it wasn't");
+
+ g_object_unref (connection);
+}
+
+static NMConnection *
+wifi_connection_new (void)
+{
+ NMConnection *connection;
+ NMSettingConnection *s_con;
+ NMSettingWireless *s_wifi;
+ NMSettingWirelessSecurity *s_wsec;
+ unsigned char tmpssid[] = { 0x31, 0x33, 0x33, 0x37 };
+ char *uuid;
+ GBytes *ssid;
+
+ connection = nm_simple_connection_new ();
+ g_assert (connection);
+
+ /* Connection setting */
+ s_con = (NMSettingConnection *) nm_setting_connection_new ();
+ g_assert (s_con);
+
+ uuid = nm_utils_uuid_generate ();
+ g_object_set (s_con,
+ NM_SETTING_CONNECTION_ID, "Test Wireless",
+ NM_SETTING_CONNECTION_UUID, uuid,
+ NM_SETTING_CONNECTION_AUTOCONNECT, FALSE,
+ NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME,
+ NULL);
+ g_free (uuid);
+ nm_connection_add_setting (connection, NM_SETTING (s_con));
+
+ /* Wireless setting */
+ s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
+ g_assert (s_wifi);
+
+ ssid = g_bytes_new (tmpssid, sizeof (tmpssid));
+ g_object_set (s_wifi,
+ NM_SETTING_WIRELESS_SSID, ssid,
+ NULL);
+ g_bytes_unref (ssid);
+ nm_connection_add_setting (connection, NM_SETTING (s_wifi));
+
+ /* Wifi security */
+ s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
+ g_assert (s_wsec);
+
+ g_object_set (G_OBJECT (s_wsec),
+ NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "none",
+ NULL);
+ nm_connection_add_setting (connection, NM_SETTING (s_wsec));
+
+ return connection;
+}
+
+static GVariant *
+build_wep_secrets (const char *wepkey)
+{
+ GVariantBuilder builder;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+ g_variant_builder_add (&builder, "{sv}",
+ NM_SETTING_WIRELESS_SECURITY_WEP_KEY0,
+ g_variant_new_string (wepkey));
+ g_variant_builder_add (&builder, "{sv}",
+ NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE,
+ g_variant_new_uint32 (NM_WEP_KEY_TYPE_KEY));
+
+ return g_variant_builder_end (&builder);
+}
+
+static void
+test_update_secrets_wifi_single_setting (void)
+{
+ NMConnection *connection;
+ NMSettingWirelessSecurity *s_wsec;
+ GVariant *secrets;
+ GError *error = NULL;
+ gboolean success;
+ const char *wepkey = "11111111111111111111111111";
+ const char *tmp;
+
+ /* Test update with a hashed setting of 802-11-wireless secrets */
+
+ connection = wifi_connection_new ();
+
+ secrets = build_wep_secrets (wepkey);
+ success = nm_connection_update_secrets (connection,
+ NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+ secrets,
+ &error);
+ g_assert_no_error (error);
+ g_assert (success);
+
+ g_variant_unref (secrets);
+
+ /* Make sure the secret is now in the connection */
+ s_wsec = nm_connection_get_setting_wireless_security (connection);
+ g_assert (s_wsec);
+ tmp = nm_setting_wireless_security_get_wep_key (s_wsec, 0);
+ g_assert_cmpstr (tmp, ==, wepkey);
+
+ g_object_unref (connection);
+}
+
+static void
+test_update_secrets_wifi_full_hash (void)
+{
+ NMConnection *connection;
+ NMSettingWirelessSecurity *s_wsec;
+ GVariantBuilder builder;
+ GVariant *all;
+ GError *error = NULL;
+ gboolean success;
+ const char *wepkey = "11111111111111111111111111";
+ const char *tmp;
+
+ /* Test update with a hashed connection containing only 802-11-wireless
+ * setting and secrets.
+ */
+
+ connection = wifi_connection_new ();
+
+ g_variant_builder_init (&builder, NM_VARIANT_TYPE_CONNECTION);
+ g_variant_builder_add (&builder, "{s@a{sv}}",
+ NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+ build_wep_secrets (wepkey));
+ all = g_variant_builder_end (&builder);
+
+ success = nm_connection_update_secrets (connection,
+ NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+ all,
+ &error);
+ g_assert_no_error (error);
+ g_assert (success);
+
+ g_variant_unref (all);
+
+ /* Make sure the secret is now in the connection */
+ s_wsec = nm_connection_get_setting_wireless_security (connection);
+ g_assert (s_wsec);
+ tmp = nm_setting_wireless_security_get_wep_key (s_wsec, 0);
+ g_assert_cmpstr (tmp, ==, wepkey);
+
+ g_object_unref (connection);
+}
+
+static void
+test_update_secrets_wifi_bad_setting_name (void)
+{
+ NMConnection *connection;
+ GVariant *secrets;
+ GError *error = NULL;
+ gboolean success;
+ const char *wepkey = "11111111111111111111111111";
+
+ /* Test that passing an invalid setting name to
+ * nm_connection_update_secrets() fails with the correct error.
+ */
+
+ connection = wifi_connection_new ();
+
+ secrets = build_wep_secrets (wepkey);
+
+ success = nm_connection_update_secrets (connection,
+ "asdfasdfasdfasf",
+ secrets,
+ &error);
+ g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_SETTING_NOT_FOUND);
+ g_assert (success == FALSE);
+
+ g_variant_unref (secrets);
+
+ g_object_unref (connection);
+}
+
+static void
+test_update_secrets_whole_connection (void)
+{
+ NMConnection *connection;
+ NMSettingWirelessSecurity *s_wsec;
+ GVariant *secrets;
+ GError *error = NULL;
+ gboolean success;
+ const char *wepkey = "11111111111111111111111111";
+
+ /* Test calling nm_connection_update_secrets() with an entire hashed
+ * connection including non-secrets.
+ */
+
+ connection = wifi_connection_new ();
+
+ /* Build up the secrets dictionary */
+ secrets = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL);
+ NMTST_VARIANT_EDITOR (secrets,
+ NMTST_VARIANT_ADD_PROPERTY (NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+ NM_SETTING_WIRELESS_SECURITY_WEP_KEY0,
+ "s",
+ wepkey);
+ );
+
+ success = nm_connection_update_secrets (connection, NULL, secrets, &error);
+ g_assert_no_error (error);
+ g_assert (success == TRUE);
+
+ g_variant_unref (secrets);
+
+ s_wsec = nm_connection_get_setting_wireless_security (connection);
+ g_assert (s_wsec);
+ g_assert_cmpstr (nm_setting_wireless_security_get_wep_key (s_wsec, 0), ==, wepkey);
+
+ g_object_unref (connection);
+}
+
+static void
+test_update_secrets_whole_connection_empty_hash (void)
+{
+ NMConnection *connection;
+ GVariant *secrets;
+ GError *error = NULL;
+ gboolean success;
+
+ /* Test that updating secrets with an empty connection hash returns success */
+
+ connection = wifi_connection_new ();
+ secrets = g_variant_new_array (G_VARIANT_TYPE ("{sa{sv}}"), NULL, 0);
+ success = nm_connection_update_secrets (connection, NULL, secrets, &error);
+ g_assert_no_error (error);
+ g_assert (success == TRUE);
+ g_variant_unref (secrets);
+ g_object_unref (connection);
+}
+
+static void
+test_update_secrets_whole_connection_bad_setting (void)
+{
+ NMConnection *connection;
+ NMSettingWirelessSecurity *s_wsec;
+ GVariant *secrets, *copy, *setting_hash;
+ const char *setting_name;
+ GVariantBuilder conn_builder;
+ GVariantIter conn_iter;
+ GError *error = NULL;
+ gboolean success;
+ const char *wepkey = "11111111111111111111111111";
+
+ /* Test that sending a hashed connection containing an invalid setting
+ * name fails with the right error.
+ */
+
+ connection = wifi_connection_new ();
+ s_wsec = nm_connection_get_setting_wireless_security (connection);
+ g_assert (s_wsec != NULL);
+ g_object_set (G_OBJECT (s_wsec),
+ NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, wepkey,
+ NULL);
+
+ /* Build up the secrets hash */
+ secrets = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL);
+
+ /* Copy the dict, renaming the wireless-security setting in the process
+ * (so we ensure libnm is returning the right error when it finds an entry
+ * in the connection hash that doesn't match any setting in the connection).
+ */
+ g_variant_builder_init (&conn_builder, NM_VARIANT_TYPE_CONNECTION);
+ g_variant_iter_init (&conn_iter, secrets);
+ while (g_variant_iter_next (&conn_iter, "{&s@a{sv}}", &setting_name, &setting_hash)) {
+ if (strcmp (setting_name, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) == 0)
+ setting_name = "asdfasdfasdfasdf";
+
+ g_variant_builder_add (&conn_builder, "{s@a{sv}}", setting_name, setting_hash);
+ g_variant_unref (setting_hash);
+ }
+ copy = g_variant_builder_end (&conn_builder);
+ g_variant_unref (secrets);
+
+ success = nm_connection_update_secrets (connection, NULL, copy, &error);
+ g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_SETTING_NOT_FOUND);
+ g_assert (success == FALSE);
+
+ g_variant_unref (copy);
+ g_object_unref (connection);
+}
+
+static void
+test_update_secrets_whole_connection_empty_base_setting (void)
+{
+ NMConnection *connection;
+ GVariant *secrets, *setting;
+ GError *error = NULL;
+ gboolean success;
+
+ /* Test that a hashed connection which does not have any hashed secrets
+ * for the requested setting returns success.
+ */
+
+ connection = wifi_connection_new ();
+ secrets = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ONLY_SECRETS);
+ g_assert_cmpint (g_variant_n_children (secrets), ==, 3);
+
+ setting = g_variant_lookup_value (secrets, NM_SETTING_WIRELESS_SETTING_NAME, NULL);
+ g_assert (setting != NULL);
+ g_variant_unref (setting);
+
+ success = nm_connection_update_secrets (connection,
+ NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+ secrets,
+ &error);
+ g_assert_no_error (error);
+ g_assert (success);
+
+ g_variant_unref (secrets);
+ g_object_unref (connection);
+}
+
+static void
+test_update_secrets_null_setting_name_with_setting_hash (void)
+{
+ NMConnection *connection;
+ GVariant *secrets;
+ GError *error = NULL;
+ gboolean success;
+ const char *wepkey = "11111111111111111111111111";
+
+ /* Ensure that a NULL setting name and only a hashed setting fails */
+
+ connection = wifi_connection_new ();
+
+ secrets = build_wep_secrets (wepkey);
+
+ g_test_expect_message ("libnm", G_LOG_LEVEL_CRITICAL,
+ "*nm_connection_update_secrets*setting_name != NULL || full_connection*");
+ success = nm_connection_update_secrets (connection, NULL, secrets, &error);
+ g_test_assert_expected_messages ();
+ g_assert_no_error (error);
+ g_assert (!success);
+
+ g_variant_unref (secrets);
+ g_object_unref (connection);
+}
+
+NMTST_DEFINE ();
+
+int
+main (int argc, char **argv)
+{
+ char *base;
+
+#if !GLIB_CHECK_VERSION (2, 35, 0)
+ g_type_init ();
+#endif
+
+ nmtst_init (&argc, &argv, TRUE);
+
+ /* The tests */
+ test_need_tls_secrets_path ();
+ test_need_tls_secrets_blob ();
+ test_need_tls_phase2_secrets_path ();
+ test_need_tls_phase2_secrets_blob ();
+
+ test_update_secrets_wifi_single_setting ();
+ test_update_secrets_wifi_full_hash ();
+ test_update_secrets_wifi_bad_setting_name ();
+
+ test_update_secrets_whole_connection ();
+ test_update_secrets_whole_connection_empty_hash ();
+ test_update_secrets_whole_connection_bad_setting ();
+ test_update_secrets_whole_connection_empty_base_setting ();
+ test_update_secrets_null_setting_name_with_setting_hash ();
+
+ base = g_path_get_basename (argv[0]);
+ fprintf (stdout, "%s: SUCCESS\n", base);
+ g_free (base);
+ return 0;
+}
+
diff --git a/libnm-core/tests/test-setting-8021x.c b/libnm-core/tests/test-setting-8021x.c
new file mode 100644
index 000000000..637ab81c1
--- /dev/null
+++ b/libnm-core/tests/test-setting-8021x.c
@@ -0,0 +1,458 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2008 - 2011 Red Hat, Inc.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <string.h>
+
+#include <nm-utils.h>
+
+#include "nm-setting-connection.h"
+#include "nm-setting-8021x.h"
+
+#include "nm-test-utils.h"
+
+static void
+compare_blob_data (const char *test,
+ const char *key_path,
+ GBytes *key)
+{
+ char *contents = NULL;
+ gsize len = 0;
+ GError *error = NULL;
+ gboolean success;
+
+ success = g_file_get_contents (key_path, &contents, &len, &error);
+ ASSERT (success == TRUE,
+ test, "failed to read blob key file: %s", error->message);
+
+ ASSERT (len > 0, test, "blob key file invalid (size 0)");
+
+ ASSERT (len == g_bytes_get_size (key),
+ test, "blob key file (%d) and setting key data (%d) lengths don't match",
+ len, g_bytes_get_size (key));
+
+ ASSERT (memcmp (contents, g_bytes_get_data (key, NULL), len) == 0,
+ test, "blob key file and blob key data don't match");
+
+ g_free (contents);
+}
+
+#define SCHEME_PATH "file://"
+
+static void
+check_scheme_path (GBytes *value, const char *path)
+{
+ const guint8 *p = g_bytes_get_data (value, NULL);
+
+ g_assert (memcmp (p, SCHEME_PATH, strlen (SCHEME_PATH)) == 0);
+ p += strlen (SCHEME_PATH);
+ g_assert (memcmp (p, path, strlen (path)) == 0);
+ p += strlen (path);
+ g_assert (*p == '\0');
+}
+
+static void
+test_private_key_import (const char *path,
+ const char *password,
+ NMSetting8021xCKScheme scheme)
+{
+ NMSetting8021x *s_8021x;
+ gboolean success;
+ NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ NMSetting8021xCKFormat tmp_fmt;
+ GError *error = NULL;
+ GBytes *tmp_key = NULL, *client_cert = NULL;
+ const char *pw;
+
+ s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
+ ASSERT (s_8021x != NULL, "private-key-import", "setting was NULL");
+
+ success = nm_setting_802_1x_set_private_key (s_8021x,
+ path,
+ password,
+ scheme,
+ &format,
+ &error);
+ ASSERT (success == TRUE,
+ "private-key-import", "error reading private key: %s", error->message);
+ ASSERT (format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN,
+ "private-key-import", "unexpected private key format (got %d)", format);
+ tmp_fmt = nm_setting_802_1x_get_private_key_format (s_8021x);
+ ASSERT (tmp_fmt == format,
+ "private-key-import", "unexpected re-read private key format (expected %d, got %d)",
+ format, tmp_fmt);
+
+ /* Make sure the password is what we expect */
+ pw = nm_setting_802_1x_get_private_key_password (s_8021x);
+ ASSERT (pw != NULL,
+ "private-key-import", "failed to get previous private key password");
+ ASSERT (strcmp (pw, password) == 0,
+ "private-key-import", "failed to compare private key password");
+
+ if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
+ tmp_key = nm_setting_802_1x_get_private_key_blob (s_8021x);
+ ASSERT (tmp_key != NULL, "private-key-import", "missing private key blob");
+ compare_blob_data ("private-key-import", path, tmp_key);
+ } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+ g_object_get (s_8021x, NM_SETTING_802_1X_PRIVATE_KEY, &tmp_key, NULL);
+ ASSERT (tmp_key != NULL, "private-key-import", "missing private key value");
+ check_scheme_path (tmp_key, path);
+ g_bytes_unref (tmp_key);
+ } else
+ g_assert_not_reached ();
+
+ /* If it's PKCS#12 ensure the client cert is the same value */
+ if (format == NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
+ g_object_get (s_8021x, NM_SETTING_802_1X_PRIVATE_KEY, &tmp_key, NULL);
+ ASSERT (tmp_key != NULL, "private-key-import", "missing private key value");
+
+ g_object_get (s_8021x, NM_SETTING_802_1X_CLIENT_CERT, &client_cert, NULL);
+ ASSERT (client_cert != NULL, "private-key-import", "missing client certificate value");
+
+ /* make sure they are the same */
+ ASSERT (g_bytes_equal (tmp_key, client_cert),
+ "private-key-import", "unexpected different private key and client cert data");
+
+ g_bytes_unref (tmp_key);
+ g_bytes_unref (client_cert);
+ }
+
+ g_object_unref (s_8021x);
+}
+
+static void
+test_phase2_private_key_import (const char *path,
+ const char *password,
+ NMSetting8021xCKScheme scheme)
+{
+ NMSetting8021x *s_8021x;
+ gboolean success;
+ NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ NMSetting8021xCKFormat tmp_fmt;
+ GError *error = NULL;
+ GBytes *tmp_key = NULL, *client_cert = NULL;
+ const char *pw;
+
+ s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
+ ASSERT (s_8021x != NULL, "phase2-private-key-import", "setting was NULL");
+
+ success = nm_setting_802_1x_set_phase2_private_key (s_8021x,
+ path,
+ password,
+ scheme,
+ &format,
+ &error);
+ ASSERT (success == TRUE,
+ "phase2-private-key-import", "error reading private key: %s", error->message);
+ ASSERT (format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN,
+ "phase2-private-key-import", "unexpected private key format");
+ tmp_fmt = nm_setting_802_1x_get_phase2_private_key_format (s_8021x);
+ ASSERT (tmp_fmt == format,
+ "phase2-private-key-import", "unexpected re-read private key format (expected %d, got %d)",
+ format, tmp_fmt);
+
+ /* Make sure the password is what we expect */
+ pw = nm_setting_802_1x_get_phase2_private_key_password (s_8021x);
+ ASSERT (pw != NULL,
+ "phase2-private-key-import", "failed to get previous private key password");
+ ASSERT (strcmp (pw, password) == 0,
+ "phase2-private-key-import", "failed to compare private key password");
+
+ if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
+ tmp_key = nm_setting_802_1x_get_phase2_private_key_blob (s_8021x);
+ ASSERT (tmp_key != NULL, "phase2-private-key-import", "missing private key blob");
+ compare_blob_data ("phase2-private-key-import", path, tmp_key);
+ } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
+ g_object_get (s_8021x, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, &tmp_key, NULL);
+ ASSERT (tmp_key != NULL, "phase2-private-key-import", "missing private key value");
+ check_scheme_path (tmp_key, path);
+ } else
+ g_assert_not_reached ();
+
+ /* If it's PKCS#12 ensure the client cert is the same value */
+ if (format == NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
+ g_object_get (s_8021x, NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, &tmp_key, NULL);
+ ASSERT (tmp_key != NULL, "private-key-import", "missing private key value");
+
+ g_object_get (s_8021x, NM_SETTING_802_1X_PHASE2_CLIENT_CERT, &client_cert, NULL);
+ ASSERT (client_cert != NULL, "private-key-import", "missing client certificate value");
+
+ /* make sure they are the same */
+ ASSERT (g_bytes_equal (tmp_key, client_cert),
+ "private-key-import", "unexpected different private key and client cert data");
+
+ g_bytes_unref (tmp_key);
+ g_bytes_unref (client_cert);
+ }
+
+ g_object_unref (s_8021x);
+}
+
+static void
+test_wrong_password_keeps_data (const char *path, const char *password)
+{
+ NMSetting8021x *s_8021x;
+ gboolean success;
+ NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ GError *error = NULL;
+ const char *pw;
+
+ s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
+ ASSERT (s_8021x != NULL, "wrong-password-keeps-data", "setting was NULL");
+
+ success = nm_setting_802_1x_set_private_key (s_8021x,
+ path,
+ password,
+ NM_SETTING_802_1X_CK_SCHEME_BLOB,
+ &format,
+ &error);
+ ASSERT (success == TRUE,
+ "wrong-password-keeps-data", "error reading private key: %s", error->message);
+ ASSERT (format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN,
+ "wrong-password-keeps-data", "unexpected private key format (got %d)", format);
+
+ /* Now try to set it to something that's not a certificate */
+ format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ success = nm_setting_802_1x_set_private_key (s_8021x,
+ "Makefile.am",
+ password,
+ NM_SETTING_802_1X_CK_SCHEME_BLOB,
+ &format,
+ &error);
+ ASSERT (success == FALSE,
+ "wrong-password-keeps-data", "unexpected success reading private key");
+ ASSERT (error != NULL,
+ "wrong-password-keeps-data", "unexpected missing error");
+ ASSERT (format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN,
+ "wrong-password-keeps-data", "unexpected success reading private key format");
+
+ /* Make sure the password hasn't changed */
+ pw = nm_setting_802_1x_get_private_key_password (s_8021x);
+ ASSERT (pw != NULL,
+ "wrong-password-keeps-data", "failed to get previous private key password");
+ ASSERT (strcmp (pw, password) == 0,
+ "wrong-password-keeps-data", "failed to compare private key password");
+
+ g_object_unref (s_8021x);
+}
+
+static void
+test_clear_private_key (const char *path, const char *password)
+{
+ NMSetting8021x *s_8021x;
+ gboolean success;
+ NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ GError *error = NULL;
+ const char *pw;
+
+ s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
+ ASSERT (s_8021x != NULL, "clear-private-key", "setting was NULL");
+
+ success = nm_setting_802_1x_set_private_key (s_8021x,
+ path,
+ password,
+ NM_SETTING_802_1X_CK_SCHEME_BLOB,
+ &format,
+ &error);
+ ASSERT (success == TRUE,
+ "clear-private-key", "error reading private key: %s", error->message);
+ ASSERT (format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN,
+ "clear-private-key", "unexpected private key format (got %d)", format);
+
+ /* Make sure the password is what we expect */
+ pw = nm_setting_802_1x_get_private_key_password (s_8021x);
+ ASSERT (pw != NULL,
+ "clear-private-key", "failed to get previous private key password");
+ ASSERT (strcmp (pw, password) == 0,
+ "clear-private-key", "failed to compare private key password");
+
+ /* Now clear it */
+ success = nm_setting_802_1x_set_private_key (s_8021x,
+ NULL,
+ NULL,
+ NM_SETTING_802_1X_CK_SCHEME_BLOB,
+ NULL,
+ &error);
+ ASSERT (success == TRUE,
+ "clear-private-key", "unexpected failure clearing private key");
+ ASSERT (error == NULL,
+ "clear-private-key", "unexpected error clearing private key");
+
+ /* Ensure the password is also now clear */
+ ASSERT (nm_setting_802_1x_get_private_key_password (s_8021x) == NULL,
+ "clear-private-key", "unexpected private key password");
+
+ g_object_unref (s_8021x);
+}
+
+static void
+test_wrong_phase2_password_keeps_data (const char *path, const char *password)
+{
+ NMSetting8021x *s_8021x;
+ gboolean success;
+ NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ GError *error = NULL;
+ const char *pw;
+
+ s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
+ ASSERT (s_8021x != NULL, "wrong-phase2-password-keeps-data", "setting was NULL");
+
+ success = nm_setting_802_1x_set_phase2_private_key (s_8021x,
+ path,
+ password,
+ NM_SETTING_802_1X_CK_SCHEME_BLOB,
+ &format,
+ &error);
+ ASSERT (success == TRUE,
+ "wrong-phase2-password-keeps-data", "error reading private key: %s", error->message);
+ ASSERT (format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN,
+ "wrong-phase2-password-keeps-data", "unexpected private key format (got %d)", format);
+
+ /* Now try to set it to something that's not a certificate */
+ format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ success = nm_setting_802_1x_set_phase2_private_key (s_8021x,
+ "Makefile.am",
+ password,
+ NM_SETTING_802_1X_CK_SCHEME_BLOB,
+ &format,
+ &error);
+ ASSERT (success == FALSE,
+ "wrong-phase2-password-keeps-data", "unexpected success reading private key");
+ ASSERT (error != NULL,
+ "wrong-phase2-password-keeps-data", "unexpected missing error");
+ ASSERT (format == NM_SETTING_802_1X_CK_FORMAT_UNKNOWN,
+ "wrong-phase2-password-keeps-data", "unexpected success reading private key format");
+
+ /* Make sure the password hasn't changed */
+ pw = nm_setting_802_1x_get_phase2_private_key_password (s_8021x);
+ ASSERT (pw != NULL,
+ "wrong-phase2-password-keeps-data", "failed to get previous private key password");
+ ASSERT (strcmp (pw, password) == 0,
+ "wrong-phase2-password-keeps-data", "failed to compare private key password");
+
+ g_object_unref (s_8021x);
+}
+
+static void
+test_clear_phase2_private_key (const char *path, const char *password)
+{
+ NMSetting8021x *s_8021x;
+ gboolean success;
+ NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+ GError *error = NULL;
+ const char *pw;
+
+ s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
+ ASSERT (s_8021x != NULL, "clear-phase2-private-key", "setting was NULL");
+
+ success = nm_setting_802_1x_set_phase2_private_key (s_8021x,
+ path,
+ password,
+ NM_SETTING_802_1X_CK_SCHEME_BLOB,
+ &format,
+ &error);
+ ASSERT (success == TRUE,
+ "clear-phase2-private-key", "error reading private key: %s", error->message);
+ ASSERT (format != NM_SETTING_802_1X_CK_FORMAT_UNKNOWN,
+ "clear-phase2-private-key", "unexpected private key format (got %d)", format);
+
+ /* Make sure the password is what we expect */
+ pw = nm_setting_802_1x_get_phase2_private_key_password (s_8021x);
+ ASSERT (pw != NULL,
+ "clear-phase2-private-key", "failed to get previous private key password");
+ ASSERT (strcmp (pw, password) == 0,
+ "clear-phase2-private-key", "failed to compare private key password");
+
+ /* Now clear it */
+ success = nm_setting_802_1x_set_phase2_private_key (s_8021x,
+ NULL,
+ NULL,
+ NM_SETTING_802_1X_CK_SCHEME_BLOB,
+ NULL,
+ &error);
+ ASSERT (success == TRUE,
+ "clear-phase2-private-key", "unexpected failure clearing private key");
+ ASSERT (error == NULL,
+ "clear-phase2-private-key", "unexpected error clearing private key");
+
+ /* Ensure the password is also now clear */
+ ASSERT (nm_setting_802_1x_get_phase2_private_key_password (s_8021x) == NULL,
+ "clear-phase2-private-key", "unexpected private key password");
+
+ g_object_unref (s_8021x);
+}
+
+static void
+do_8021x_test (gconstpointer test_data)
+{
+ char **parts, *path, *password;
+
+ parts = g_strsplit ((const char *) test_data, ", ", -1);
+ g_assert_cmpint (g_strv_length (parts), ==, 2);
+
+ path = g_build_filename (TEST_CERT_DIR, parts[0], NULL);
+ password = parts[1];
+
+ /* Test phase1 and phase2 path scheme */
+ test_private_key_import (path, password, NM_SETTING_802_1X_CK_SCHEME_PATH);
+ test_phase2_private_key_import (path, password, NM_SETTING_802_1X_CK_SCHEME_PATH);
+
+ /* Test phase1 and phase2 blob scheme */
+ test_private_key_import (path, password, NM_SETTING_802_1X_CK_SCHEME_BLOB);
+ test_phase2_private_key_import (path, password, NM_SETTING_802_1X_CK_SCHEME_BLOB);
+
+ /* Test that using a wrong password does not change existing data */
+ test_wrong_password_keeps_data (path, password);
+ test_wrong_phase2_password_keeps_data (path, password);
+
+ /* Test clearing the private key */
+ test_clear_private_key (path, password);
+ test_clear_phase2_private_key (path, password);
+
+ g_free (path);
+ g_strfreev (parts);
+}
+
+NMTST_DEFINE ();
+
+int
+main (int argc, char **argv)
+{
+ nmtst_init (&argc, &argv, TRUE);
+
+ g_test_add_data_func ("/libnm/setting-8021x/key-and-cert",
+ "test_key_and_cert.pem, test",
+ do_8021x_test);
+ g_test_add_data_func ("/libnm/setting-8021x/key-only",
+ "test-key-only.pem, test",
+ do_8021x_test);
+ g_test_add_data_func ("/libnm/setting-8021x/pkcs8-enc-key",
+ "pkcs8-enc-key.pem, 1234567890",
+ do_8021x_test);
+ g_test_add_data_func ("/libnm/setting-8021x/pkcs12",
+ "test-cert.p12, test",
+ do_8021x_test);
+
+ return g_test_run ();
+}
+
diff --git a/libnm-core/tests/test-setting-dcb.c b/libnm-core/tests/test-setting-dcb.c
new file mode 100644
index 000000000..8adab8ce8
--- /dev/null
+++ b/libnm-core/tests/test-setting-dcb.c
@@ -0,0 +1,326 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2013 Red Hat, Inc.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <string.h>
+#include <nm-utils.h>
+#include <nm-glib-compat.h>
+#include "nm-setting-dcb.h"
+#include "nm-connection.h"
+#include "nm-errors.h"
+
+#define DCB_FLAGS_ALL (NM_SETTING_DCB_FLAG_ENABLE | \
+ NM_SETTING_DCB_FLAG_ADVERTISE | \
+ NM_SETTING_DCB_FLAG_WILLING)
+
+static void
+test_dcb_flags_valid (void)
+{
+ NMSettingDcb *s_dcb;
+ GError *error = NULL;
+ gboolean success;
+ guint i;
+
+ s_dcb = (NMSettingDcb *) nm_setting_dcb_new ();
+ g_assert (s_dcb);
+
+ g_assert_cmpint (nm_setting_dcb_get_app_fcoe_flags (s_dcb), ==, 0);
+ g_assert_cmpint (nm_setting_dcb_get_app_iscsi_flags (s_dcb), ==, 0);
+ g_assert_cmpint (nm_setting_dcb_get_app_fip_flags (s_dcb), ==, 0);
+ g_assert_cmpint (nm_setting_dcb_get_priority_flow_control_flags (s_dcb), ==, 0);
+ g_assert_cmpint (nm_setting_dcb_get_priority_group_flags (s_dcb), ==, 0);
+
+ g_object_set (G_OBJECT (s_dcb),
+ NM_SETTING_DCB_APP_FCOE_FLAGS, DCB_FLAGS_ALL,
+ NM_SETTING_DCB_APP_ISCSI_FLAGS, DCB_FLAGS_ALL,
+ NM_SETTING_DCB_APP_FIP_FLAGS, DCB_FLAGS_ALL,
+ NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, DCB_FLAGS_ALL,
+ NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, DCB_FLAGS_ALL,
+ NULL);
+ /* Priority Group Bandwidth must total 100% */
+ for (i = 0; i < 7; i++)
+ nm_setting_dcb_set_priority_group_bandwidth (s_dcb, i, 12);
+ nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 7, 16);
+
+ success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error);
+ g_assert_no_error (error);
+ g_assert (success);
+
+ g_assert_cmpint (nm_setting_dcb_get_app_fcoe_flags (s_dcb), ==, DCB_FLAGS_ALL);
+ g_assert_cmpint (nm_setting_dcb_get_app_iscsi_flags (s_dcb), ==, DCB_FLAGS_ALL);
+ g_assert_cmpint (nm_setting_dcb_get_app_fip_flags (s_dcb), ==, DCB_FLAGS_ALL);
+ g_assert_cmpint (nm_setting_dcb_get_priority_flow_control_flags (s_dcb), ==, DCB_FLAGS_ALL);
+ g_assert_cmpint (nm_setting_dcb_get_priority_group_flags (s_dcb), ==, DCB_FLAGS_ALL);
+}
+
+#define TEST_FLAG(p, f, v) \
+{ \
+ /* GObject property min/max should ensure the property does not get set to \
+ * the invalid value, so we ensure the value we just tried to set is 0 and \
+ * that verify is successful since the property never got set. \
+ */ \
+ g_object_set (G_OBJECT (s_dcb), p, v, NULL); \
+ g_assert_cmpint (f (s_dcb), ==, 0); \
+ success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error); \
+ g_assert_no_error (error); \
+ g_assert (success); \
+}
+
+static void
+test_dcb_flags_invalid (void)
+{
+ NMSettingDcb *s_dcb;
+ GError *error = NULL;
+ gboolean success;
+
+ s_dcb = (NMSettingDcb *) nm_setting_dcb_new ();
+ g_assert (s_dcb);
+
+ g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*");
+ TEST_FLAG (NM_SETTING_DCB_APP_FCOE_FLAGS, nm_setting_dcb_get_app_fcoe_flags, 0x332523);
+ g_test_assert_expected_messages ();
+
+ g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*");
+ TEST_FLAG (NM_SETTING_DCB_APP_ISCSI_FLAGS, nm_setting_dcb_get_app_iscsi_flags, 0xFF);
+ g_test_assert_expected_messages ();
+
+ g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*");
+ TEST_FLAG (NM_SETTING_DCB_APP_FIP_FLAGS, nm_setting_dcb_get_app_fip_flags, 0x1111);
+ g_test_assert_expected_messages ();
+
+ g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*");
+ TEST_FLAG (NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, nm_setting_dcb_get_priority_flow_control_flags, G_MAXUINT32);
+ g_test_assert_expected_messages ();
+
+ g_test_expect_message ("GLib-GObject", G_LOG_LEVEL_WARNING, "*invalid or out of range*");
+ TEST_FLAG (NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, nm_setting_dcb_get_priority_group_flags,
+ (NM_SETTING_DCB_FLAG_ENABLE | NM_SETTING_DCB_FLAG_ADVERTISE | NM_SETTING_DCB_FLAG_WILLING) + 1);
+ g_test_assert_expected_messages ();
+}
+
+#define TEST_APP_PRIORITY(lcprop, ucprop, v) \
+{ \
+ g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_APP_##ucprop##_FLAGS, NM_SETTING_DCB_FLAG_NONE, NULL); \
+ \
+ g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_APP_##ucprop##_PRIORITY, v, NULL); \
+ g_assert_cmpint (nm_setting_dcb_get_app_##lcprop##_priority (s_dcb), ==, v); \
+ \
+ /* Assert that the setting is invalid while the app is disabled unless v is default */ \
+ success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error); \
+ if (v >= 0) { \
+ g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); \
+ g_assert (success == FALSE); \
+ } else { \
+ g_assert_no_error (error); \
+ g_assert (success); \
+ } \
+ g_clear_error (&error); \
+ \
+ /* Set the enable flag and re-verify, this time it should be valid */ \
+ g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_APP_##ucprop##_FLAGS, NM_SETTING_DCB_FLAG_ENABLE, NULL); \
+ success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error); \
+ g_assert_no_error (error); \
+ g_assert (success); \
+ \
+ g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_APP_##ucprop##_PRIORITY, 0, NULL); \
+}
+
+static void
+test_dcb_app_priorities (void)
+{
+ NMSettingDcb *s_dcb;
+ GError *error = NULL;
+ gboolean success;
+
+ s_dcb = (NMSettingDcb *) nm_setting_dcb_new ();
+ g_assert (s_dcb);
+
+ /* Defaults */
+ g_assert_cmpint (nm_setting_dcb_get_app_fcoe_priority (s_dcb), ==, -1);
+ g_assert_cmpint (nm_setting_dcb_get_app_iscsi_priority (s_dcb), ==, -1);
+ g_assert_cmpint (nm_setting_dcb_get_app_fip_priority (s_dcb), ==, -1);
+
+ TEST_APP_PRIORITY (fcoe, FCOE, 6);
+ TEST_APP_PRIORITY (iscsi, ISCSI, 5);
+ TEST_APP_PRIORITY (fip, FIP, 4);
+
+ TEST_APP_PRIORITY (fcoe, FCOE, -1);
+ TEST_APP_PRIORITY (iscsi, ISCSI, -1);
+ TEST_APP_PRIORITY (fip, FIP, -1);
+}
+
+#define TEST_PRIORITY_VALID(fn, id, val, flagsprop, verify) \
+{ \
+ /* Assert that setting the value gets the same value back out */ \
+ nm_setting_dcb_set_priority_##fn (s_dcb, id, val); \
+ g_assert_cmpint (nm_setting_dcb_get_priority_##fn (s_dcb, id), ==, val); \
+ \
+ if (verify) { \
+ if (val != 0) { \
+ /* Assert that verify fails because the flags do not include 'enabled' \
+ * and a value has been set. \
+ */ \
+ success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error); \
+ g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); \
+ g_assert (success == FALSE); \
+ g_clear_error (&error); \
+ } \
+ \
+ /* Assert that adding the 'enabled' flag verifies the setting */ \
+ g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_PRIORITY_##flagsprop##_FLAGS, NM_SETTING_DCB_FLAG_ENABLE, NULL); \
+ success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error); \
+ g_assert_no_error (error); \
+ g_assert (success); \
+ } \
+ \
+ /* Reset everything */ \
+ g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_PRIORITY_##flagsprop##_FLAGS, NM_SETTING_DCB_FLAG_NONE, NULL); \
+ nm_setting_dcb_set_priority_##fn (s_dcb, id, 0); \
+}
+
+/* If Priority Groups are enabled, PG bandwidth must equal 100% */
+#define SET_VALID_PRIORITY_GROUP_BANDWIDTH \
+{ \
+ guint x; \
+ for (x = 0; x < 7; x++) \
+ nm_setting_dcb_set_priority_group_bandwidth (s_dcb, x, 12); \
+ nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 7, 16); \
+}
+
+static void
+test_dcb_priorities_valid (void)
+{
+ NMSettingDcb *s_dcb;
+ GError *error = NULL;
+ gboolean success;
+ guint i;
+
+ s_dcb = (NMSettingDcb *) nm_setting_dcb_new ();
+ g_assert (s_dcb);
+
+ for (i = 0; i < 8; i++)
+ TEST_PRIORITY_VALID (flow_control, i, TRUE, FLOW_CONTROL, TRUE);
+
+ SET_VALID_PRIORITY_GROUP_BANDWIDTH
+ for (i = 0; i < 8; i++) {
+ TEST_PRIORITY_VALID (group_id, i, i, GROUP, TRUE);
+ TEST_PRIORITY_VALID (group_id, i, 7 - i, GROUP, TRUE);
+ }
+
+ /* Clear PG bandwidth from earlier tests */
+ for (i = 0; i < 8; i++)
+ nm_setting_dcb_set_priority_group_bandwidth (s_dcb, i, 0);
+
+ /* Priority Group Bandwidth must add up to 100% if enabled, which requires
+ * some dancing for verifying individual values here.
+ */
+ for (i = 0; i < 8; i++) {
+ guint other = 7 - (i % 8);
+
+ /* Set another priority group to the remaining bandwidth */
+ nm_setting_dcb_set_priority_group_bandwidth (s_dcb, other, 100 - i);
+ TEST_PRIORITY_VALID (group_bandwidth, i, i, GROUP, TRUE);
+
+ /* Set another priority group to the remaining bandwidth */
+ nm_setting_dcb_set_priority_group_bandwidth (s_dcb, other, 100 - (7 - i));
+ TEST_PRIORITY_VALID (group_bandwidth, i, 7 - i, GROUP, TRUE);
+
+ /* Clear remaining bandwidth */
+ nm_setting_dcb_set_priority_group_bandwidth (s_dcb, other, 0);
+ }
+
+ SET_VALID_PRIORITY_GROUP_BANDWIDTH
+ for (i = 0; i < 8; i++) {
+ TEST_PRIORITY_VALID (bandwidth, i, i, GROUP, TRUE);
+ TEST_PRIORITY_VALID (bandwidth, i, 7 - i, GROUP, TRUE);
+ }
+
+ SET_VALID_PRIORITY_GROUP_BANDWIDTH
+ for (i = 0; i < 8; i++)
+ TEST_PRIORITY_VALID (strict_bandwidth, i, TRUE, GROUP, TRUE);
+
+ SET_VALID_PRIORITY_GROUP_BANDWIDTH
+ for (i = 0; i < 8; i++) {
+ TEST_PRIORITY_VALID (traffic_class, i, i, GROUP, TRUE);
+ TEST_PRIORITY_VALID (traffic_class, i, 7 - i, GROUP, TRUE);
+ }
+}
+
+static void
+test_dcb_bandwidth_sums (void)
+{
+ NMSettingDcb *s_dcb;
+ GError *error = NULL;
+ gboolean success;
+
+ s_dcb = (NMSettingDcb *) nm_setting_dcb_new ();
+ g_assert (s_dcb);
+
+ /* Assert that setting the value gets the same value back out */
+ nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 0, 9);
+ nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 1, 10);
+ nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 2, 11);
+ nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 3, 12);
+ nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 4, 13);
+ nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 5, 14);
+ nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 6, 15);
+ nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 7, 16);
+
+ /* Assert verify success when sums total 100% */
+ g_object_set (G_OBJECT (s_dcb), NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, NM_SETTING_DCB_FLAG_ENABLE, NULL);
+ success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error);
+ g_assert_no_error (error);
+ g_assert (success);
+
+ /* Assert verify fails when sums do not total 100% */
+ nm_setting_dcb_set_priority_group_bandwidth (s_dcb, 4, 20);
+ success = nm_setting_verify (NM_SETTING (s_dcb), NULL, &error);
+ g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY);
+ g_assert (success == FALSE);
+ g_clear_error (&error);
+}
+
+#define TPATH "/libnm/settings/dcb/"
+
+int
+main (int argc, char **argv)
+{
+ g_test_init (&argc, &argv, NULL);
+
+#if !GLIB_CHECK_VERSION (2, 35, 0)
+ g_type_init ();
+#endif
+
+#if !GLIB_CHECK_VERSION(2,34,0)
+ g_log_set_always_fatal (G_LOG_LEVEL_CRITICAL);
+#endif
+
+ g_test_add_func (TPATH "flags-valid", test_dcb_flags_valid);
+ g_test_add_func (TPATH "flags-invalid", test_dcb_flags_invalid);
+ g_test_add_func (TPATH "app-priorities", test_dcb_app_priorities);
+ g_test_add_func (TPATH "priorities", test_dcb_priorities_valid);
+ g_test_add_func (TPATH "bandwidth-sums", test_dcb_bandwidth_sums);
+
+ return g_test_run ();
+}
+
diff --git a/libnm-core/tests/test-settings-defaults.c b/libnm-core/tests/test-settings-defaults.c
new file mode 100644
index 000000000..0e7861872
--- /dev/null
+++ b/libnm-core/tests/test-settings-defaults.c
@@ -0,0 +1,133 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright 2008 - 2011 Red Hat, Inc.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <string.h>
+
+#include <nm-utils.h>
+
+#include "nm-setting-8021x.h"
+#include "nm-setting-cdma.h"
+#include "nm-setting-connection.h"
+#include "nm-setting-gsm.h"
+#include "nm-setting-ip4-config.h"
+#include "nm-setting-ip6-config.h"
+#include "nm-setting-ppp.h"
+#include "nm-setting-pppoe.h"
+#include "nm-setting-serial.h"
+#include "nm-setting-vpn.h"
+#include "nm-setting-wired.h"
+#include "nm-setting-wireless.h"
+#include "nm-setting-wireless-security.h"
+
+#include "nm-test-utils.h"
+
+static void
+test_defaults (GType type, const char *name)
+{
+ GParamSpec **property_specs;
+ guint n_property_specs;
+ GObject *setting;
+ int i;
+
+ setting = g_object_new (type, NULL);
+
+ property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
+ ASSERT (property_specs != NULL,
+ name, "couldn't find property specs for object of type '%s'",
+ g_type_name (G_OBJECT_TYPE (setting)));
+
+ for (i = 0; i < n_property_specs; i++) {
+ GParamSpec *prop_spec = property_specs[i];
+ GValue value = G_VALUE_INIT;
+ GValue defvalue = G_VALUE_INIT;
+ char *actual, *expected;
+ gboolean ok = FALSE;
+
+ /* Ignore non-fundamental types since they won't really have
+ * defaults.
+ */
+ if (!G_TYPE_IS_FUNDAMENTAL (prop_spec->value_type))
+ continue;
+
+ g_value_init (&value, prop_spec->value_type);
+ g_object_get_property (G_OBJECT (setting), prop_spec->name, &value);
+
+ g_value_init (&defvalue, prop_spec->value_type);
+ g_param_value_set_default (prop_spec, &defvalue);
+
+ actual = g_strdup_value_contents (&value);
+ expected = g_strdup_value_contents (&defvalue);
+
+ if (!strcmp (prop_spec->name, NM_SETTING_NAME)) {
+ /* 'name' is always the setting name, not the default value */
+ ok = !strcmp (nm_setting_get_name (NM_SETTING (setting)), name);
+ g_free (expected);
+ expected = g_strdup (name);
+ } else
+ ok = g_param_value_defaults (prop_spec, &value);
+
+ ASSERT (ok,
+ name, "property '%s' value '%s' not the expected default value '%s'",
+ prop_spec->name, actual, expected);
+
+ g_free (actual);
+ g_free (expected);
+ g_value_unset (&value);
+ g_value_unset (&defvalue);
+ }
+
+ g_free (property_specs);
+ g_object_unref (setting);
+}
+
+int
+main (int argc, char **argv)
+{
+ char *base;
+
+#if !GLIB_CHECK_VERSION (2, 35, 0)
+ g_type_init ();
+#endif
+
+ /* The tests */
+ test_defaults (NM_TYPE_SETTING_CONNECTION, NM_SETTING_CONNECTION_SETTING_NAME);
+ test_defaults (NM_TYPE_SETTING_802_1X, NM_SETTING_802_1X_SETTING_NAME);
+ test_defaults (NM_TYPE_SETTING_CDMA, NM_SETTING_CDMA_SETTING_NAME);
+ test_defaults (NM_TYPE_SETTING_GSM, NM_SETTING_GSM_SETTING_NAME);
+ test_defaults (NM_TYPE_SETTING_IP4_CONFIG, NM_SETTING_IP4_CONFIG_SETTING_NAME);
+ test_defaults (NM_TYPE_SETTING_IP6_CONFIG, NM_SETTING_IP6_CONFIG_SETTING_NAME);
+ test_defaults (NM_TYPE_SETTING_PPP, NM_SETTING_PPP_SETTING_NAME);
+ test_defaults (NM_TYPE_SETTING_PPPOE, NM_SETTING_PPPOE_SETTING_NAME);
+ test_defaults (NM_TYPE_SETTING_SERIAL, NM_SETTING_SERIAL_SETTING_NAME);
+ test_defaults (NM_TYPE_SETTING_VPN, NM_SETTING_VPN_SETTING_NAME);
+ test_defaults (NM_TYPE_SETTING_WIRED, NM_SETTING_WIRED_SETTING_NAME);
+ test_defaults (NM_TYPE_SETTING_WIRELESS, NM_SETTING_WIRELESS_SETTING_NAME);
+ test_defaults (NM_TYPE_SETTING_WIRELESS_SECURITY, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
+
+ base = g_path_get_basename (argv[0]);
+ fprintf (stdout, "%s: SUCCESS\n", base);
+ g_free (base);
+ return 0;
+}
+