summaryrefslogtreecommitdiff
path: root/src/settings/plugins/ifnet
diff options
context:
space:
mode:
Diffstat (limited to 'src/settings/plugins/ifnet')
-rw-r--r--src/settings/plugins/ifnet/Makefile.am57
-rw-r--r--src/settings/plugins/ifnet/Makefile.in922
-rw-r--r--src/settings/plugins/ifnet/connection_parser.c3069
-rw-r--r--src/settings/plugins/ifnet/connection_parser.h46
-rw-r--r--src/settings/plugins/ifnet/net_parser.c639
-rw-r--r--src/settings/plugins/ifnet/net_parser.h46
-rw-r--r--src/settings/plugins/ifnet/net_utils.c974
-rw-r--r--src/settings/plugins/ifnet/net_utils.h80
-rw-r--r--src/settings/plugins/ifnet/nm-ifnet-connection.c191
-rw-r--r--src/settings/plugins/ifnet/nm-ifnet-connection.h51
-rw-r--r--src/settings/plugins/ifnet/plugin.c541
-rw-r--r--src/settings/plugins/ifnet/plugin.h47
-rw-r--r--src/settings/plugins/ifnet/tests/Makefile.am18
-rw-r--r--src/settings/plugins/ifnet/tests/Makefile.in716
-rw-r--r--src/settings/plugins/ifnet/tests/hostname2
-rw-r--r--src/settings/plugins/ifnet/tests/net147
-rw-r--r--src/settings/plugins/ifnet/tests/net.all864
-rw-r--r--src/settings/plugins/ifnet/tests/nm-system-settings.conf5
-rw-r--r--src/settings/plugins/ifnet/tests/test_all.c399
-rw-r--r--src/settings/plugins/ifnet/tests/wpa_supplicant.conf864
-rw-r--r--src/settings/plugins/ifnet/wpa_parser.c566
-rw-r--r--src/settings/plugins/ifnet/wpa_parser.h40
22 files changed, 10284 insertions, 0 deletions
diff --git a/src/settings/plugins/ifnet/Makefile.am b/src/settings/plugins/ifnet/Makefile.am
new file mode 100644
index 000000000..9bf8a79a1
--- /dev/null
+++ b/src/settings/plugins/ifnet/Makefile.am
@@ -0,0 +1,57 @@
+SUBDIRS = . tests
+INCLUDES = \
+ -I$(top_srcdir)/src/settings \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/libnm-glib \
+ -I$(top_srcdir)/libnm-util
+
+pkglib_LTLIBRARIES = libnm-settings-plugin-ifnet.la
+
+noinst_LTLIBRARIES = lib-ifnet-io.la
+
+libnm_settings_plugin_ifnet_la_SOURCES = \
+ nm-ifnet-connection.c \
+ nm-ifnet-connection.h \
+ plugin.c \
+ plugin.h
+
+libnm_settings_plugin_ifnet_la_CPPFLAGS = \
+ $(GLIB_CFLAGS) \
+ $(GMODULE_CFLAGS) \
+ $(DBUS_CFLAGS) \
+ $(GUDEV_CFLAGS) \
+ -DG_DISABLE_DEPRECATED \
+ -DSYSCONFDIR=\"$(sysconfdir)\"
+
+libnm_settings_plugin_ifnet_la_LDFLAGS = -module -avoid-version
+
+libnm_settings_plugin_ifnet_la_LIBADD = \
+ $(top_builddir)/libnm-util/libnm-util.la \
+ $(top_builddir)/libnm-glib/libnm-glib.la \
+ lib-ifnet-io.la\
+ $(GLIB_LIBS) \
+ $(GMODULE_LIBS) \
+ $(GUDEV_LIBS) \
+ $(GIO_LIBS)
+
+lib_ifnet_io_la_SOURCES = \
+ net_parser.c\
+ net_parser.h\
+ connection_parser.c \
+ connection_parser.h \
+ net_utils.h\
+ net_utils.c\
+ wpa_parser.h\
+ wpa_parser.c
+
+lib_ifnet_io_la_CPPFLAGS = \
+ $(GLIB_CFLAGS) \
+ $(DBUS_CFLAGS) \
+ -DG_DISABLE_DEPRECATED \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DSBINDIR=\"$(sbindir)\"
+
+lib_ifnet_io_la_LIBADD = \
+ $(top_builddir)/libnm-util/libnm-util.la \
+ $(GLIB_LIBS)\
+ $(GIO_LIBS)
diff --git a/src/settings/plugins/ifnet/Makefile.in b/src/settings/plugins/ifnet/Makefile.in
new file mode 100644
index 000000000..793258f75
--- /dev/null
+++ b/src/settings/plugins/ifnet/Makefile.in
@@ -0,0 +1,922 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@
+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@
+subdir = src/settings/plugins/ifnet
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
+ $(top_srcdir)/m4/gettext.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/libnl-check.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)/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 =
+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__installdirs = "$(DESTDIR)$(pkglibdir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkglib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+lib_ifnet_io_la_DEPENDENCIES = \
+ $(top_builddir)/libnm-util/libnm-util.la $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+am_lib_ifnet_io_la_OBJECTS = lib_ifnet_io_la-net_parser.lo \
+ lib_ifnet_io_la-connection_parser.lo \
+ lib_ifnet_io_la-net_utils.lo lib_ifnet_io_la-wpa_parser.lo
+lib_ifnet_io_la_OBJECTS = $(am_lib_ifnet_io_la_OBJECTS)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+libnm_settings_plugin_ifnet_la_DEPENDENCIES = \
+ $(top_builddir)/libnm-util/libnm-util.la \
+ $(top_builddir)/libnm-glib/libnm-glib.la lib-ifnet-io.la \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am_libnm_settings_plugin_ifnet_la_OBJECTS = \
+ libnm_settings_plugin_ifnet_la-nm-ifnet-connection.lo \
+ libnm_settings_plugin_ifnet_la-plugin.lo
+libnm_settings_plugin_ifnet_la_OBJECTS = \
+ $(am_libnm_settings_plugin_ifnet_la_OBJECTS)
+libnm_settings_plugin_ifnet_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) \
+ $(libnm_settings_plugin_ifnet_la_LDFLAGS) $(LDFLAGS) -o $@
+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_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+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_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(lib_ifnet_io_la_SOURCES) \
+ $(libnm_settings_plugin_ifnet_la_SOURCES)
+DIST_SOURCES = $(lib_ifnet_io_la_SOURCES) \
+ $(libnm_settings_plugin_ifnet_la_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-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 uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+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@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_LIBS = @DBUS_LIBS@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DHCLIENT_PATH = @DHCLIENT_PATH@
+DHCLIENT_VERSION = @DHCLIENT_VERSION@
+DHCPCD_PATH = @DHCPCD_PATH@
+DISABLE_DEPRECATED = @DISABLE_DEPRECATED@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_CFLAGS = @GIO_CFLAGS@
+GIO_LIBS = @GIO_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GMODULE_CFLAGS = @GMODULE_CFLAGS@
+GMODULE_LIBS = @GMODULE_LIBS@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+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@
+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@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBDL = @LIBDL@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBM = @LIBM@
+LIBNL_CFLAGS = @LIBNL_CFLAGS@
+LIBNL_LIBS = @LIBNL_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @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@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
+NM_MICRO_VERSION = @NM_MICRO_VERSION@
+NM_MINOR_VERSION = @NM_MINOR_VERSION@
+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@
+PKGCONFIG_PATH = @PKGCONFIG_PATH@
+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_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
+RANLIB = @RANLIB@
+RESOLVCONF_PATH = @RESOLVCONF_PATH@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
+UDEV_BASE_DIR = @UDEV_BASE_DIR@
+USE_NLS = @USE_NLS@
+UUID_CFLAGS = @UUID_CFLAGS@
+UUID_LIBS = @UUID_LIBS@
+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_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@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+systemdsystemunitdir = @systemdsystemunitdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = . tests
+INCLUDES = \
+ -I$(top_srcdir)/src/settings \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/libnm-glib \
+ -I$(top_srcdir)/libnm-util
+
+pkglib_LTLIBRARIES = libnm-settings-plugin-ifnet.la
+noinst_LTLIBRARIES = lib-ifnet-io.la
+libnm_settings_plugin_ifnet_la_SOURCES = \
+ nm-ifnet-connection.c \
+ nm-ifnet-connection.h \
+ plugin.c \
+ plugin.h
+
+libnm_settings_plugin_ifnet_la_CPPFLAGS = \
+ $(GLIB_CFLAGS) \
+ $(GMODULE_CFLAGS) \
+ $(DBUS_CFLAGS) \
+ $(GUDEV_CFLAGS) \
+ -DG_DISABLE_DEPRECATED \
+ -DSYSCONFDIR=\"$(sysconfdir)\"
+
+libnm_settings_plugin_ifnet_la_LDFLAGS = -module -avoid-version
+libnm_settings_plugin_ifnet_la_LIBADD = \
+ $(top_builddir)/libnm-util/libnm-util.la \
+ $(top_builddir)/libnm-glib/libnm-glib.la \
+ lib-ifnet-io.la\
+ $(GLIB_LIBS) \
+ $(GMODULE_LIBS) \
+ $(GUDEV_LIBS) \
+ $(GIO_LIBS)
+
+lib_ifnet_io_la_SOURCES = \
+ net_parser.c\
+ net_parser.h\
+ connection_parser.c \
+ connection_parser.h \
+ net_utils.h\
+ net_utils.c\
+ wpa_parser.h\
+ wpa_parser.c
+
+lib_ifnet_io_la_CPPFLAGS = \
+ $(GLIB_CFLAGS) \
+ $(DBUS_CFLAGS) \
+ -DG_DISABLE_DEPRECATED \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
+ -DSBINDIR=\"$(sbindir)\"
+
+lib_ifnet_io_la_LIBADD = \
+ $(top_builddir)/libnm-util/libnm-util.la \
+ $(GLIB_LIBS)\
+ $(GIO_LIBS)
+
+all: all-recursive
+
+.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 src/settings/plugins/ifnet/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/settings/plugins/ifnet/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-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(pkglibdir)" || $(MKDIR_P) "$(DESTDIR)$(pkglibdir)"
+ @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \
+ }
+
+uninstall-pkglibLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \
+ done
+
+clean-pkglibLTLIBRARIES:
+ -test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES)
+ @list='$(pkglib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+lib-ifnet-io.la: $(lib_ifnet_io_la_OBJECTS) $(lib_ifnet_io_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) $(lib_ifnet_io_la_OBJECTS) $(lib_ifnet_io_la_LIBADD) $(LIBS)
+libnm-settings-plugin-ifnet.la: $(libnm_settings_plugin_ifnet_la_OBJECTS) $(libnm_settings_plugin_ifnet_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libnm_settings_plugin_ifnet_la_LINK) -rpath $(pkglibdir) $(libnm_settings_plugin_ifnet_la_OBJECTS) $(libnm_settings_plugin_ifnet_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib_ifnet_io_la-connection_parser.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib_ifnet_io_la-net_parser.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib_ifnet_io_la-net_utils.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lib_ifnet_io_la-wpa_parser.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_settings_plugin_ifnet_la-nm-ifnet-connection.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_settings_plugin_ifnet_la-plugin.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+lib_ifnet_io_la-net_parser.lo: net_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_ifnet_io_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib_ifnet_io_la-net_parser.lo -MD -MP -MF $(DEPDIR)/lib_ifnet_io_la-net_parser.Tpo -c -o lib_ifnet_io_la-net_parser.lo `test -f 'net_parser.c' || echo '$(srcdir)/'`net_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lib_ifnet_io_la-net_parser.Tpo $(DEPDIR)/lib_ifnet_io_la-net_parser.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='net_parser.c' object='lib_ifnet_io_la-net_parser.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_ifnet_io_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib_ifnet_io_la-net_parser.lo `test -f 'net_parser.c' || echo '$(srcdir)/'`net_parser.c
+
+lib_ifnet_io_la-connection_parser.lo: connection_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_ifnet_io_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib_ifnet_io_la-connection_parser.lo -MD -MP -MF $(DEPDIR)/lib_ifnet_io_la-connection_parser.Tpo -c -o lib_ifnet_io_la-connection_parser.lo `test -f 'connection_parser.c' || echo '$(srcdir)/'`connection_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lib_ifnet_io_la-connection_parser.Tpo $(DEPDIR)/lib_ifnet_io_la-connection_parser.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='connection_parser.c' object='lib_ifnet_io_la-connection_parser.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_ifnet_io_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib_ifnet_io_la-connection_parser.lo `test -f 'connection_parser.c' || echo '$(srcdir)/'`connection_parser.c
+
+lib_ifnet_io_la-net_utils.lo: net_utils.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_ifnet_io_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib_ifnet_io_la-net_utils.lo -MD -MP -MF $(DEPDIR)/lib_ifnet_io_la-net_utils.Tpo -c -o lib_ifnet_io_la-net_utils.lo `test -f 'net_utils.c' || echo '$(srcdir)/'`net_utils.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lib_ifnet_io_la-net_utils.Tpo $(DEPDIR)/lib_ifnet_io_la-net_utils.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='net_utils.c' object='lib_ifnet_io_la-net_utils.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_ifnet_io_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib_ifnet_io_la-net_utils.lo `test -f 'net_utils.c' || echo '$(srcdir)/'`net_utils.c
+
+lib_ifnet_io_la-wpa_parser.lo: wpa_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_ifnet_io_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lib_ifnet_io_la-wpa_parser.lo -MD -MP -MF $(DEPDIR)/lib_ifnet_io_la-wpa_parser.Tpo -c -o lib_ifnet_io_la-wpa_parser.lo `test -f 'wpa_parser.c' || echo '$(srcdir)/'`wpa_parser.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/lib_ifnet_io_la-wpa_parser.Tpo $(DEPDIR)/lib_ifnet_io_la-wpa_parser.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='wpa_parser.c' object='lib_ifnet_io_la-wpa_parser.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_ifnet_io_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lib_ifnet_io_la-wpa_parser.lo `test -f 'wpa_parser.c' || echo '$(srcdir)/'`wpa_parser.c
+
+libnm_settings_plugin_ifnet_la-nm-ifnet-connection.lo: nm-ifnet-connection.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_settings_plugin_ifnet_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_settings_plugin_ifnet_la-nm-ifnet-connection.lo -MD -MP -MF $(DEPDIR)/libnm_settings_plugin_ifnet_la-nm-ifnet-connection.Tpo -c -o libnm_settings_plugin_ifnet_la-nm-ifnet-connection.lo `test -f 'nm-ifnet-connection.c' || echo '$(srcdir)/'`nm-ifnet-connection.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnm_settings_plugin_ifnet_la-nm-ifnet-connection.Tpo $(DEPDIR)/libnm_settings_plugin_ifnet_la-nm-ifnet-connection.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-ifnet-connection.c' object='libnm_settings_plugin_ifnet_la-nm-ifnet-connection.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_settings_plugin_ifnet_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_settings_plugin_ifnet_la-nm-ifnet-connection.lo `test -f 'nm-ifnet-connection.c' || echo '$(srcdir)/'`nm-ifnet-connection.c
+
+libnm_settings_plugin_ifnet_la-plugin.lo: plugin.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_settings_plugin_ifnet_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_settings_plugin_ifnet_la-plugin.lo -MD -MP -MF $(DEPDIR)/libnm_settings_plugin_ifnet_la-plugin.Tpo -c -o libnm_settings_plugin_ifnet_la-plugin.lo `test -f 'plugin.c' || echo '$(srcdir)/'`plugin.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnm_settings_plugin_ifnet_la-plugin.Tpo $(DEPDIR)/libnm_settings_plugin_ifnet_la-plugin.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='plugin.c' object='libnm_settings_plugin_ifnet_la-plugin.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_settings_plugin_ifnet_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_settings_plugin_ifnet_la-plugin.lo `test -f 'plugin.c' || echo '$(srcdir)/'`plugin.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+# 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.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; 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"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ 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; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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"
+
+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 \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ 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: check-recursive
+all-am: Makefile $(LTLIBRARIES)
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(pkglibdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: 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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+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-recursive
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pkglibLTLIBRARIES 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-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am: install-pkglibLTLIBRARIES
+
+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-pkglibLTLIBRARIES
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-generic clean-libtool \
+ clean-noinstLTLIBRARIES clean-pkglibLTLIBRARIES ctags \
+ ctags-recursive 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-pkglibLTLIBRARIES 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-recursive \
+ uninstall uninstall-am uninstall-pkglibLTLIBRARIES
+
+
+# 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/src/settings/plugins/ifnet/connection_parser.c b/src/settings/plugins/ifnet/connection_parser.c
new file mode 100644
index 000000000..982f94f9c
--- /dev/null
+++ b/src/settings/plugins/ifnet/connection_parser.c
@@ -0,0 +1,3069 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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 (C) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <netinet/ether.h>
+#include <errno.h>
+#include <ctype.h>
+#include <glib/gi18n.h>
+
+#include <nm-setting-connection.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-wired.h>
+#include <nm-setting-wireless.h>
+#include <nm-setting-8021x.h>
+#include <nm-system-config-interface.h>
+#include <nm-utils.h>
+
+#include "net_utils.h"
+#include "wpa_parser.h"
+#include "connection_parser.h"
+#include "nm-ifnet-connection.h"
+
+static const char *
+get_prefix (void)
+{
+ return _("System");
+}
+
+static void
+update_connection_id (NMConnection *connection, const char *conn_name)
+{
+ gchar *idstr = NULL;
+ gchar *uuid_base = NULL;
+ gchar *uuid = NULL;
+ int name_len;
+ NMSettingConnection *setting;
+
+ name_len = strlen (conn_name);
+ if ((name_len > 2) && (g_str_has_prefix (conn_name, "0x"))) {
+ gchar * conn_name_printable = utils_hexstr2bin (conn_name + 2, name_len - 2);
+ idstr = g_strdup_printf ("%s (%s)", get_prefix (), conn_name_printable);
+ g_free (conn_name_printable);
+ } else
+ idstr = g_strdup_printf ("%s (%s)", get_prefix (), conn_name);
+ uuid_base = idstr;
+ uuid = nm_utils_uuid_generate_from_string (uuid_base);
+ setting =
+ (NMSettingConnection *) nm_connection_get_setting (connection,
+ NM_TYPE_SETTING_CONNECTION);
+ g_object_set (setting, NM_SETTING_CONNECTION_ID, idstr,
+ NM_SETTING_CONNECTION_UUID, uuid, NULL);
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+ "update_connection_setting_from_config_block: name:%s, id:%s, uuid: %s",
+ conn_name, idstr, uuid);
+
+ g_free (uuid);
+ g_free (idstr);
+}
+
+static gboolean eap_simple_reader (const char *eap_method,
+ const char *ssid,
+ NMSetting8021x *s_8021x,
+ gboolean phase2,
+ GError **error);
+
+static gboolean eap_tls_reader (const char *eap_method,
+ const char *ssid,
+ NMSetting8021x *s_8021x,
+ gboolean phase2,
+ GError **error);
+
+static gboolean eap_peap_reader (const char *eap_method,
+ const char *ssid,
+ NMSetting8021x *s_8021x,
+ gboolean phase2,
+ GError **error);
+
+static gboolean eap_ttls_reader (const char *eap_method,
+ const char *ssid,
+ NMSetting8021x *s_8021x,
+ gboolean phase2,
+ GError **error);
+
+typedef struct {
+ const char *method;
+ gboolean (*reader) (const char *eap_method,
+ const char *ssid,
+ NMSetting8021x *s_8021x,
+ gboolean phase2,
+ GError **error);
+ gboolean wifi_phase2_only;
+} EAPReader;
+
+static EAPReader eap_readers[] = {
+ {"md5", eap_simple_reader, TRUE},
+ {"pap", eap_simple_reader, TRUE},
+ {"chap", eap_simple_reader, TRUE},
+ {"mschap", eap_simple_reader, TRUE},
+ {"mschapv2", eap_simple_reader, TRUE},
+ {"leap", eap_simple_reader, TRUE},
+ {"tls", eap_tls_reader, FALSE},
+ {"peap", eap_peap_reader, FALSE},
+ {"ttls", eap_ttls_reader, FALSE},
+ {NULL, NULL}
+};
+
+/* reading identity and password */
+static gboolean
+eap_simple_reader (const char *eap_method,
+ const char *ssid,
+ NMSetting8021x *s_8021x,
+ gboolean phase2,
+ GError **error)
+{
+ const char *value;
+
+ /* identity */
+ value = wpa_get_value (ssid, "identity");
+ if (!value) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Missing IEEE_8021X_IDENTITY for EAP method '%s'.",
+ eap_method);
+ return FALSE;
+ }
+ g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, value, NULL);
+
+ /* password */
+ value = wpa_get_value (ssid, "password");
+ if (!value) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Missing IEEE_8021X_PASSWORD for EAP method '%s'.",
+ eap_method);
+ return FALSE;
+ }
+
+ g_object_set (s_8021x, NM_SETTING_802_1X_PASSWORD, value, NULL);
+
+ return TRUE;
+}
+
+static gboolean
+eap_tls_reader (const char *eap_method,
+ const char *ssid,
+ NMSetting8021x *s_8021x,
+ gboolean phase2,
+ GError **error)
+{
+ const char *value;
+ const char *ca_cert = NULL;
+ const char *client_cert = NULL;
+ const char *privkey = NULL;
+ const char *privkey_password = NULL;
+ gboolean success = FALSE;
+ NMSetting8021xCKFormat privkey_format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
+
+ /* identity */
+ value = wpa_get_value (ssid, "identity");
+ if (!value) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Missing IEEE_8021X_IDENTITY for EAP method '%s'.",
+ eap_method);
+ return FALSE;
+ }
+ g_object_set (s_8021x, NM_SETTING_802_1X_IDENTITY, value, NULL);
+
+ /* ca cert */
+ ca_cert = wpa_get_value (ssid, phase2 ? "ca_cert2" : "ca_cert");
+ if (ca_cert) {
+ if (phase2) {
+ if (!nm_setting_802_1x_set_phase2_ca_cert (s_8021x,
+ ca_cert,
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ NULL, error))
+ goto done;
+ } else {
+ if (!nm_setting_802_1x_set_ca_cert (s_8021x,
+ ca_cert,
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ NULL, error))
+ goto done;
+ }
+ } else {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ " warning: missing %s for EAP"
+ " method '%s'; this is insecure!",
+ phase2 ? "IEEE_8021X_INNER_CA_CERT" :
+ "IEEE_8021X_CA_CERT", eap_method);
+ }
+
+ /* Private key password */
+ privkey_password = wpa_get_value (ssid,
+ phase2 ? "private_key_passwd2" :
+ "private_key_passwd");
+
+ if (!privkey_password) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Missing %s for EAP method '%s'.",
+ phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY_PASSWORD" :
+ "IEEE_8021X_PRIVATE_KEY_PASSWORD", eap_method);
+ goto done;
+ }
+
+ /* The private key itself */
+ privkey = wpa_get_value (ssid, phase2 ? "private_key2" : "private_key");
+ if (!privkey) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Missing %s for EAP method '%s'.",
+ phase2 ? "IEEE_8021X_INNER_PRIVATE_KEY" :
+ "IEEE_8021X_PRIVATE_KEY", eap_method);
+ goto done;
+ }
+
+ if (phase2) {
+ if (!nm_setting_802_1x_set_phase2_private_key (s_8021x,
+ privkey,
+ privkey_password,
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ &privkey_format,
+ error))
+ goto done;
+ } else {
+ if (!nm_setting_802_1x_set_private_key (s_8021x,
+ privkey,
+ privkey_password,
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ &privkey_format, error))
+ goto done;
+ }
+
+ /* Only set the client certificate if the private key is not PKCS#12 format,
+ * as NM (due to supplicant restrictions) requires. If the key was PKCS#12,
+ * then nm_setting_802_1x_set_private_key() already set the client certificate
+ * to the same value as the private key.
+ */
+ if (privkey_format == NM_SETTING_802_1X_CK_FORMAT_RAW_KEY
+ || privkey_format == NM_SETTING_802_1X_CK_FORMAT_X509) {
+ client_cert = wpa_get_value (ssid,
+ phase2 ? "client_cert2" :
+ "client_cert");
+ if (!client_cert) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Missing %s for EAP method '%s'.",
+ phase2 ? "IEEE_8021X_INNER_CLIENT_CERT" :
+ "IEEE_8021X_CLIENT_CERT", eap_method);
+ goto done;
+ }
+
+ if (phase2) {
+ if (!nm_setting_802_1x_set_phase2_client_cert (s_8021x,
+ client_cert,
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ NULL,
+ error))
+ goto done;
+ } else {
+ if (!nm_setting_802_1x_set_client_cert (s_8021x,
+ client_cert,
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ NULL, error))
+ goto done;
+ }
+ }
+
+ success = TRUE;
+
+done:
+ return success;
+}
+
+static gboolean
+eap_peap_reader (const char *eap_method,
+ const char *ssid,
+ NMSetting8021x *s_8021x,
+ gboolean phase2,
+ GError **error)
+{
+ const char *ca_cert = NULL;
+ const char *inner_auth = NULL;
+ const char *peapver = NULL;
+ char **list = NULL, **iter, *lower;
+ gboolean success = FALSE;
+
+ ca_cert = wpa_get_value (ssid, "ca_cert");
+ if (ca_cert) {
+ if (!nm_setting_802_1x_set_ca_cert (s_8021x,
+ ca_cert,
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ NULL, error))
+ goto done;
+ } else {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME, " warning: missing "
+ "IEEE_8021X_CA_CERT for EAP method '%s'; this is"
+ " insecure!", eap_method);
+ }
+
+ peapver = wpa_get_value (ssid, "phase1");
+ /* peap version, default is automatic */
+ if (peapver && strstr (peapver, "peapver")) {
+ if (strstr (peapver, "peapver=0"))
+ g_object_set (s_8021x, NM_SETTING_802_1X_PHASE1_PEAPVER,
+ "0", NULL);
+ else if (strstr (peapver, "peapver=1"))
+ g_object_set (s_8021x, NM_SETTING_802_1X_PHASE1_PEAPVER,
+ "1", NULL);
+ else {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Unknown IEEE_8021X_PEAP_VERSION value '%s'",
+ peapver);
+ goto done;
+ }
+ }
+
+ /* peaplabel */
+ if (peapver && strstr (peapver, "peaplabel=1"))
+ g_object_set (s_8021x, NM_SETTING_802_1X_PHASE1_PEAPLABEL, "1",
+ NULL);
+
+ inner_auth = wpa_get_value (ssid, "phase2");
+ if (!inner_auth) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Missing IEEE_8021X_INNER_AUTH_METHODS.");
+ goto done;
+ }
+ /* Handle options for the inner auth method */
+ list = g_strsplit (inner_auth, " ", 0);
+ for (iter = list; iter && *iter; iter++) {
+ gchar *pos = NULL;
+
+ if (!strlen (*iter))
+ continue;
+
+ if (!(pos = strstr (*iter, "MSCHAPV2"))
+ || !(pos = strstr (*iter, "MD5"))
+ || !(pos = strstr (*iter, "GTC"))) {
+ if (!eap_simple_reader
+ (pos, ssid, s_8021x, TRUE, error))
+ goto done;
+ } else if (!(pos = strstr (*iter, "TLS"))) {
+ if (!eap_tls_reader (pos, ssid, s_8021x, TRUE, error))
+ goto done;
+ } else {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Unknown IEEE_8021X_INNER_AUTH_METHOD '%s'.",
+ *iter);
+ goto done;
+ }
+
+ pos = strchr (*iter, '=');
+ pos++;
+ lower = g_ascii_strdown (pos, -1);
+ g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH, lower,
+ NULL);
+ g_free (lower);
+ break;
+ }
+
+ if (!nm_setting_802_1x_get_phase2_auth (s_8021x)) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "No valid IEEE_8021X_INNER_AUTH_METHODS found.");
+ goto done;
+ }
+
+ success = TRUE;
+
+done:
+ if (list)
+ g_strfreev (list);
+ return success;
+}
+
+static gboolean
+eap_ttls_reader (const char *eap_method,
+ const char *ssid,
+ NMSetting8021x *s_8021x,
+ gboolean phase2,
+ GError **error)
+{
+ gboolean success = FALSE;
+ const char *anon_ident = NULL;
+ const char *ca_cert = NULL;
+ const char *tmp;
+ char **list = NULL, **iter, *inner_auth = NULL;
+
+ /* ca cert */
+ ca_cert = wpa_get_value (ssid, "ca_cert");
+ if (ca_cert) {
+ if (!nm_setting_802_1x_set_ca_cert (s_8021x,
+ ca_cert,
+ NM_SETTING_802_1X_CK_SCHEME_PATH,
+ NULL, error))
+ goto done;
+ } else {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME, " warning: missing "
+ "IEEE_8021X_CA_CERT for EAP method '%s'; this is"
+ " insecure!", eap_method);
+ }
+
+ /* anonymous indentity for tls */
+ anon_ident = wpa_get_value (ssid, "anonymous_identity");
+ if (anon_ident && strlen (anon_ident))
+ g_object_set (s_8021x, NM_SETTING_802_1X_ANONYMOUS_IDENTITY,
+ anon_ident, NULL);
+
+ tmp = wpa_get_value (ssid, "phase2");
+ if (!tmp) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Missing IEEE_8021X_INNER_AUTH_METHODS.");
+ goto done;
+ }
+
+ /* Handle options for the inner auth method */
+ inner_auth = g_ascii_strdown (tmp, -1);
+ list = g_strsplit (inner_auth, " ", 0);
+ for (iter = list; iter && *iter; iter++) {
+ gchar *pos = NULL;
+
+ if (!strlen (*iter))
+ continue;
+ if ((pos = strstr (*iter, "mschapv2")) != NULL
+ || (pos = strstr (*iter, "mschap")) != NULL
+ || (pos = strstr (*iter, "pap")) != NULL
+ || (pos = strstr (*iter, "chap")) != NULL) {
+ if (!eap_simple_reader
+ (pos, ssid, s_8021x, TRUE, error))
+ goto done;
+ g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTH,
+ pos, NULL);
+ } else if ((pos = strstr (*iter, "tls")) != NULL) {
+ if (!eap_tls_reader (pos, ssid, s_8021x, TRUE, error))
+ goto done;
+ g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP,
+ "tls", NULL);
+ } else if ((pos = strstr (*iter, "mschapv2")) != NULL
+ || (pos = strstr (*iter, "md5")) != NULL) {
+ if (!eap_simple_reader
+ (pos, ssid, s_8021x, TRUE, error)) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME, "SIMPLE ERROR");
+ goto done;
+ }
+ g_object_set (s_8021x, NM_SETTING_802_1X_PHASE2_AUTHEAP,
+ pos, NULL);
+ } else {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Unknown IEEE_8021X_INNER_AUTH_METHOD '%s'.",
+ *iter);
+ goto done;
+ }
+ break;
+ }
+
+ success = TRUE;
+done:
+ if (list)
+ g_strfreev (list);
+ g_free (inner_auth);
+ return success;
+}
+
+/* type is already decided by net_parser, this function is just used to
+ * doing tansformation*/
+static const gchar *
+guess_connection_type (const char *conn_name)
+{
+ const gchar *type = ifnet_get_data (conn_name, "type");
+ const gchar *ret_type = NULL;
+
+ if (!g_strcmp0 (type, "ppp"))
+ ret_type = NM_SETTING_PPPOE_SETTING_NAME;
+
+ if (!g_strcmp0 (type, "wireless"))
+ ret_type = NM_SETTING_WIRELESS_SETTING_NAME;
+
+ if (!ret_type)
+ ret_type = NM_SETTING_WIRED_SETTING_NAME;
+
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+ "guessed connection type (%s) = %s", conn_name, ret_type);
+ return ret_type;
+}
+
+/* Reading mac address for setting connection option.
+ * Unmanaged device mac address is required by NetworkManager*/
+static gboolean
+read_mac_address (const char *conn_name, GByteArray **array, GError **error)
+{
+ const char *value = ifnet_get_data (conn_name, "mac");
+ struct ether_addr *mac;
+
+ if (!value || !strlen (value))
+ return TRUE;
+
+ mac = ether_aton (value);
+ if (!mac) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "The MAC address '%s' was invalid.", value);
+ return FALSE;
+ }
+
+ *array = g_byte_array_sized_new (ETH_ALEN);
+ g_byte_array_append (*array, (guint8 *) mac->ether_addr_octet, ETH_ALEN);
+ return TRUE;
+}
+
+static void
+make_wired_connection_setting (NMConnection *connection,
+ const char *conn_name,
+ GError **error)
+{
+ GByteArray *mac = NULL;
+ NMSettingWired *s_wired = NULL;
+ const char *value = NULL;
+
+ s_wired = NM_SETTING_WIRED (nm_setting_wired_new ());
+
+ /* mtu_xxx */
+ value = ifnet_get_data (conn_name, "mtu");
+ if (value) {
+ long int mtu;
+
+ errno = 0;
+ mtu = strtol (value, NULL, 10);
+ if (errno || mtu < 0 || mtu > 65535) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ " warning: invalid MTU '%s' for %s",
+ value, conn_name);
+ } else
+ g_object_set (s_wired, NM_SETTING_WIRED_MTU,
+ (guint32) mtu, NULL);
+ }
+
+ if (read_mac_address (conn_name, &mac, error)) {
+ if (mac) {
+ g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS,
+ mac, NULL);
+ g_byte_array_free (mac, TRUE);
+ }
+ } else {
+ g_object_unref (s_wired);
+ s_wired = NULL;
+ }
+ if (s_wired)
+ nm_connection_add_setting (connection, NM_SETTING (s_wired));
+}
+
+/* add NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME,
+ * NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID in future*/
+static void
+make_ip4_setting (NMConnection *connection,
+ const char *conn_name,
+ GError **error)
+{
+
+ NMSettingIP4Config *ip4_setting =
+ NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ());
+ const char *value, *method;
+ gboolean is_static_block = is_static_ip4 (conn_name);
+ ip_block *iblock = NULL;
+
+ /* set dhcp options (dhcp_xxx) */
+ value = ifnet_get_data (conn_name, "dhcp");
+ g_object_set (ip4_setting, NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS, value
+ && strstr (value, "nodns") ? TRUE : FALSE,
+ NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES, value
+ && strstr (value, "nogateway") ? TRUE : FALSE, NULL);
+
+ if (!is_static_block) {
+ method = ifnet_get_data (conn_name, "config");
+ if (!method){
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Unknown config for %s", conn_name);
+ g_object_unref (ip4_setting);
+ return;
+ }
+ if (!strcmp (method, "dhcp"))
+ g_object_set (ip4_setting,
+ NM_SETTING_IP4_CONFIG_METHOD,
+ NM_SETTING_IP4_CONFIG_METHOD_AUTO,
+ NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, FALSE, NULL);
+ else if (!strcmp (method, "autoip")){
+ g_object_set (ip4_setting,
+ NM_SETTING_IP4_CONFIG_METHOD,
+ NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL,
+ NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, FALSE, NULL);
+ nm_connection_add_setting (connection, NM_SETTING (ip4_setting));
+ return;
+ } else if (!strcmp (method, "shared")){
+ g_object_set (ip4_setting,
+ NM_SETTING_IP4_CONFIG_METHOD,
+ NM_SETTING_IP4_CONFIG_METHOD_SHARED,
+ NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, FALSE, NULL);
+ nm_connection_add_setting (connection, NM_SETTING (ip4_setting));
+ return;
+ } else {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Unknown config for %s", conn_name);
+ g_object_unref (ip4_setting);
+ return;
+ }
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Using %s method for %s",
+ method, conn_name);
+ }else {
+ iblock = convert_ip4_config_block (conn_name);
+ if (!iblock) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Ifnet plugin: can't aquire ip configuration for %s",
+ conn_name);
+ g_object_unref (ip4_setting);
+ return;
+ }
+ /************** add all ip settings to the connection**********/
+ while (iblock) {
+ ip_block *current_iblock;
+ NMIP4Address *ip4_addr = nm_ip4_address_new ();
+
+ nm_ip4_address_set_address (ip4_addr, iblock->ip);
+ nm_ip4_address_set_prefix (ip4_addr,
+ nm_utils_ip4_netmask_to_prefix
+ (iblock->netmask));
+ /* currently all the IPs has the same gateway */
+ nm_ip4_address_set_gateway (ip4_addr, iblock->gateway);
+ if (iblock->gateway)
+ g_object_set (ip4_setting,
+ NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES,
+ TRUE, NULL);
+ if (!nm_setting_ip4_config_add_address (ip4_setting, ip4_addr))
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "ignoring duplicate IP4 address");
+ nm_ip4_address_unref (ip4_addr);
+ current_iblock = iblock;
+ iblock = iblock->next;
+ destroy_ip_block (current_iblock);
+
+ }
+ g_object_set (ip4_setting,
+ NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL,
+ NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, !has_default_ip4_route (conn_name),
+ NULL);
+ }
+
+ /* add dhcp hostname and client id */
+ if (!is_static_block && !strcmp (method, "dhcp")) {
+ gchar *dhcp_hostname, *client_id;
+
+ get_dhcp_hostname_and_client_id (&dhcp_hostname, &client_id);
+ if (dhcp_hostname) {
+ g_object_set (ip4_setting,
+ NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME,
+ dhcp_hostname, NULL);
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "DHCP hostname: %s",
+ dhcp_hostname);
+ g_free (dhcp_hostname);
+ }
+ if (client_id) {
+ g_object_set (ip4_setting,
+ NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID,
+ client_id, NULL);
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "DHCP client id: %s",
+ client_id);
+ g_free (client_id);
+ }
+ }
+
+ /* add all IPv4 dns servers, IPv6 servers will be ignored */
+ set_ip4_dns_servers (ip4_setting, conn_name);
+
+ /* DNS searches */
+ value = ifnet_get_data (conn_name, "dns_search");
+ if (value) {
+ char *stripped = g_strdup (value);
+ char **searches = NULL;
+
+ strip_string (stripped, '"');
+
+ searches = g_strsplit (stripped, " ", 0);
+ if (searches) {
+ char **item;
+
+ for (item = searches; *item; item++) {
+ if (strlen (*item)) {
+ if (!nm_setting_ip4_config_add_dns_search (ip4_setting, *item))
+ PLUGIN_WARN
+ (IFNET_PLUGIN_NAME,
+ " warning: duplicate DNS domain '%s'",
+ *item);
+ }
+ }
+ g_strfreev (searches);
+ }
+ }
+
+ /* static routes */
+ iblock = convert_ip4_routes_block (conn_name);
+ while (iblock) {
+ ip_block *current_iblock = iblock;
+ const char *metric_str;
+ char *stripped;
+ long int metric;
+ NMIP4Route *route = nm_ip4_route_new ();
+
+ nm_ip4_route_set_dest (route, iblock->ip);
+ nm_ip4_route_set_next_hop (route, iblock->gateway);
+ nm_ip4_route_set_prefix (route,
+ nm_utils_ip4_netmask_to_prefix
+ (iblock->netmask));
+ if ((metric_str = ifnet_get_data (conn_name, "metric")) != NULL) {
+ metric = strtol (metric_str, NULL, 10);
+ nm_ip4_route_set_metric (route, (guint32) metric);
+ } else {
+ metric_str = ifnet_get_global_data ("metric");
+ if (metric_str) {
+ stripped = g_strdup (metric_str);
+ strip_string (stripped, '"');
+ metric = strtol (metric_str, NULL, 10);
+ nm_ip4_route_set_metric (route,
+ (guint32) metric);
+ g_free (stripped);
+ }
+ }
+
+ if (!nm_setting_ip4_config_add_route (ip4_setting, route))
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "warning: duplicate IP4 route");
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+ "new IP4 route:%d\n", iblock->ip);
+
+ nm_ip4_route_unref (route);
+
+ current_iblock = iblock;
+ iblock = iblock->next;
+ destroy_ip_block (current_iblock);
+ }
+
+ /* Finally add setting to connection */
+ nm_connection_add_setting (connection, NM_SETTING (ip4_setting));
+}
+
+static void
+make_ip6_setting (NMConnection *connection,
+ const char *conn_name,
+ GError **error)
+{
+ NMSettingIP6Config *s_ip6 = NULL;
+ gboolean is_static_block = is_static_ip6 (conn_name);
+
+ // used to disable IPv6
+ gboolean ipv6_enabled = FALSE;
+ gchar *method = NM_SETTING_IP6_CONFIG_METHOD_MANUAL;
+ const char *value;
+ ip6_block *iblock;
+ gboolean never_default = !has_default_ip6_route (conn_name);
+
+ s_ip6 = (NMSettingIP6Config *) nm_setting_ip6_config_new ();
+ if (!s_ip6) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Could not allocate IP6 setting");
+ return;
+ }
+
+ value = ifnet_get_data (conn_name, "enable_ipv6");
+ if (value && is_true (value))
+ ipv6_enabled = TRUE;
+
+ //FIXME Handle other methods that NM supports in future
+ // Currently only Manual and DHCP are supported
+ if (!ipv6_enabled) {
+ g_object_set (s_ip6,
+ NM_SETTING_IP6_CONFIG_METHOD,
+ NM_SETTING_IP6_CONFIG_METHOD_IGNORE, NULL);
+ goto done;
+ } else if (!is_static_block) {
+ // config_eth* contains "dhcp6"
+ method = NM_SETTING_IP6_CONFIG_METHOD_AUTO;
+ never_default = FALSE;
+ }
+ // else if (!has_ip6_address(conn_name))
+ // doesn't have "dhcp6" && doesn't have any ipv6 address
+ // method = NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL;
+ else
+ // doesn't have "dhcp6" && has at least one ipv6 address
+ method = NM_SETTING_IP6_CONFIG_METHOD_MANUAL;
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "IPv6 for %s enabled, using %s",
+ conn_name, method);
+
+ g_object_set (s_ip6,
+ NM_SETTING_IP6_CONFIG_METHOD, method,
+ NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS, FALSE,
+ NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES, FALSE,
+ NM_SETTING_IP6_CONFIG_NEVER_DEFAULT, never_default, NULL);
+
+ /* Make manual settings */
+ if (!strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
+ ip6_block *current_iblock;
+
+ iblock = convert_ip6_config_block (conn_name);
+ if (!iblock) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Ifnet plugin: can't aquire ip6 configuration for %s",
+ conn_name);
+ goto error;
+ }
+ /* add all IPv6 addresses */
+ while (iblock) {
+ NMIP6Address *ip6_addr = nm_ip6_address_new ();
+
+ nm_ip6_address_set_address (ip6_addr, iblock->ip);
+ nm_ip6_address_set_prefix (ip6_addr, iblock->prefix);
+ if (nm_setting_ip6_config_add_address (s_ip6, ip6_addr)) {
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+ "ipv6 addresses count: %d",
+ nm_setting_ip6_config_get_num_addresses
+ (s_ip6));
+ } else {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "ignoring duplicate IP4 address");
+ }
+ nm_ip6_address_unref (ip6_addr);
+ current_iblock = iblock;
+ iblock = iblock->next;
+ destroy_ip6_block (current_iblock);
+ }
+
+ } else if (!strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) {
+ /* - autoconf or DHCPv6 stuff goes here */
+ }
+ // DNS Servers, set NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS TRUE here
+ set_ip6_dns_servers (s_ip6, conn_name);
+
+ /* DNS searches ('DOMAIN' key) are read by make_ip4_setting() and included in NMSettingIP4Config */
+
+ // Add routes
+ iblock = convert_ip6_routes_block (conn_name);
+ if (iblock)
+ g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES,
+ TRUE, NULL);
+ /* Add all IPv6 routes */
+ while (iblock) {
+ ip6_block *current_iblock = iblock;
+ const char *metric_str;
+ char *stripped;
+ long int metric = 1;
+ NMIP6Route *route = nm_ip6_route_new ();
+
+ nm_ip6_route_set_dest (route, iblock->ip);
+ nm_ip6_route_set_next_hop (route, iblock->next_hop);
+ nm_ip6_route_set_prefix (route, iblock->prefix);
+ /* metric is not per routes configuration right now
+ * global metric is also supported (metric="x") */
+ if ((metric_str = ifnet_get_data (conn_name, "metric")) != NULL) {
+ metric = strtol (metric_str, NULL, 10);
+ nm_ip6_route_set_metric (route, (guint32) metric);
+ } else {
+ metric_str = ifnet_get_global_data ("metric");
+ if (metric_str) {
+ stripped = g_strdup (metric_str);
+ strip_string (stripped, '"');
+ metric = strtol (metric_str, NULL, 10);
+ nm_ip6_route_set_metric (route,
+ (guint32) metric);
+ g_free (stripped);
+ } else
+ nm_ip6_route_set_metric (route, (guint32) 1);
+ }
+
+ if (!nm_setting_ip6_config_add_route (s_ip6, route))
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ " warning: duplicate IP6 route");
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, " info: new IP6 route");
+ nm_ip6_route_unref (route);
+
+ current_iblock = iblock;
+ iblock = iblock->next;
+ destroy_ip6_block (current_iblock);
+ }
+
+done:
+ nm_connection_add_setting (connection, NM_SETTING (s_ip6));
+ return;
+
+error:
+ g_object_unref (s_ip6);
+ PLUGIN_WARN (IFNET_PLUGIN_NAME, " warning: Ignore IPv6 for %s",
+ conn_name);
+ return;
+}
+
+static NMSetting *
+make_wireless_connection_setting (const char *conn_name,
+ NMSetting8021x **s_8021x,
+ GError **error)
+{
+ GByteArray *array, *mac = NULL;
+ NMSettingWireless *wireless_setting = NULL;
+ gboolean adhoc = FALSE;
+ const char *value;
+ const char *type;
+
+ /* PPP over WIFI is not supported yet */
+ g_return_val_if_fail (conn_name != NULL
+ && strcmp (ifnet_get_data (conn_name, "type"),
+ "ppp") != 0, NULL);
+ type = ifnet_get_data (conn_name, "type");
+ if (strcmp (type, "ppp") == 0) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "PPP over WIFI is not supported yet");
+ return NULL;
+ }
+
+ wireless_setting = NM_SETTING_WIRELESS (nm_setting_wireless_new ());
+ if (read_mac_address (conn_name, &mac, error)) {
+ if (mac) {
+ g_object_set (wireless_setting,
+ NM_SETTING_WIRELESS_MAC_ADDRESS, mac,
+ NULL);
+ g_byte_array_free (mac, TRUE);
+
+ }
+ } else {
+ g_object_unref (wireless_setting);
+ return NULL;
+ }
+
+ /* handle ssid (hex and ascii) */
+ if (conn_name) {
+ gsize ssid_len = 0, value_len = strlen (conn_name);
+ const char *p;
+ char *tmp, *converted = NULL;
+
+ ssid_len = value_len;
+ if ((value_len > 2) && (g_str_has_prefix (conn_name, "0x"))) {
+ /* Hex representation */
+ if (value_len % 2) {
+ g_set_error (error, ifnet_plugin_error_quark (),
+ 0,
+ "Invalid SSID '%s' size (looks like hex but length not multiple of 2)",
+ conn_name);
+ goto error;
+ }
+ // ignore "0x"
+ p = conn_name + 2;
+ if (!is_hex (p)) {
+ g_set_error (error,
+ ifnet_plugin_error_quark (),
+ 0,
+ "Invalid SSID '%s' character (looks like hex SSID but '%c' isn't a hex digit)",
+ conn_name, *p);
+ goto error;
+
+ }
+ tmp = utils_hexstr2bin (p, value_len - 2);
+ ssid_len = (value_len - 2) / 2;
+ converted = g_malloc0 (ssid_len + 1);
+ memcpy (converted, tmp, ssid_len);
+ g_free (tmp);
+ }
+
+ if (ssid_len > 32 || ssid_len == 0) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Invalid SSID '%s' (size %zu not between 1 and 32 inclusive)",
+ conn_name, ssid_len);
+ goto error;
+ }
+ array = g_byte_array_sized_new (ssid_len);
+ g_byte_array_append (array, (const guint8 *) (converted ? converted : conn_name), ssid_len);
+ g_object_set (wireless_setting, NM_SETTING_WIRELESS_SSID, array, NULL);
+ g_byte_array_free (array, TRUE);
+ g_free (converted);
+ } else {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Missing SSID");
+ goto error;
+ }
+
+ /* mode=0: infrastructure
+ * mode=1: adhoc */
+ value = wpa_get_value (conn_name, "mode");
+ if (value)
+ adhoc = strcmp (value, "1") == 0 ? TRUE : FALSE;
+
+ if (exist_ssid (conn_name)) {
+ const char *mode = adhoc ? "adhoc" : "infrastructure";
+
+ g_object_set (wireless_setting, NM_SETTING_WIRELESS_MODE, mode,
+ NULL);
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Using mode: %s", mode);
+ }
+
+ /* BSSID setting */
+ value = wpa_get_value (conn_name, "bssid");
+ if (value) {
+ struct ether_addr *eth;
+ GByteArray *bssid;
+
+ eth = ether_aton (value);
+ if (!eth) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Invalid BSSID '%s'", value);
+ goto error;
+ }
+
+ bssid = g_byte_array_sized_new (ETH_ALEN);
+ g_byte_array_append (bssid, eth->ether_addr_octet, ETH_ALEN);
+ g_object_set (wireless_setting, NM_SETTING_WIRELESS_BSSID,
+ bssid, NULL);
+ g_byte_array_free (bssid, TRUE);
+
+ }
+
+ /* mtu_ssid="xx" */
+ value = ifnet_get_data (conn_name, "mtu");
+ if (value) {
+ long int mtu;
+
+ errno = 0;
+ mtu = strtol (value, NULL, 10);
+ if (errno || mtu < 0 || mtu > 50000) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ " warning: invalid MTU '%s' for %s",
+ value, conn_name);
+ } else
+ g_object_set (wireless_setting, NM_SETTING_WIRELESS_MTU,
+ (guint32) mtu, NULL);
+
+ }
+
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "wireless_setting added for %s",
+ conn_name);
+ return NM_SETTING (wireless_setting);
+error:
+ if (wireless_setting)
+ g_object_unref (wireless_setting);
+ return NULL;
+
+}
+
+static NMSettingWirelessSecurity *
+make_leap_setting (const char *ssid, GError **error)
+{
+ NMSettingWirelessSecurity *wsec;
+ const char *value;
+
+ wsec =
+ NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ());
+
+ value = wpa_get_value (ssid, "key_mgmt");
+ if (!value || strcmp (value, "IEEE8021X"))
+ goto error; /* Not LEAP */
+
+ value = wpa_get_value (ssid, "eap");
+ if (!value || strcasecmp (value, "LEAP"))
+ goto error; /* Not LEAP */
+
+ value = wpa_get_value (ssid, "password");
+ if (value && strlen (value))
+ g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD,
+ value, NULL);
+
+ value = wpa_get_value (ssid, "identity");
+ if (!value || !strlen (value)) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Missing LEAP identity");
+ goto error;
+ }
+ g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, value,
+ NULL);
+
+ g_object_set (wsec,
+ NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x",
+ NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "leap", NULL);
+
+ return wsec;
+error:
+ if (wsec)
+ g_object_unref (wsec);
+ return NULL;
+}
+
+static gboolean
+add_one_wep_key (const char *ssid,
+ const char *key,
+ int key_idx,
+ NMSettingWirelessSecurity *s_wsec,
+ GError **error)
+{
+ const char *value;
+ char *converted = NULL;
+ gboolean success = FALSE;
+
+ g_return_val_if_fail (ssid != NULL, FALSE);
+ g_return_val_if_fail (key != NULL, FALSE);
+ g_return_val_if_fail (key_idx >= 0 && key_idx <= 3, FALSE);
+ g_return_val_if_fail (s_wsec != NULL, FALSE);
+
+ value = wpa_get_value (ssid, key);
+ if (!value)
+ return TRUE;
+
+ /* Validate keys */
+ if (strlen (value) == 10 || strlen (value) == 26) {
+ /* Hexadecimal WEP key */
+ if (!is_hex (value)) {
+ g_set_error (error, ifnet_plugin_error_quark (),
+ 0, "Invalid hexadecimal WEP key.");
+ goto out;
+ }
+ converted = g_strdup (value);
+ } else if (value[0] == '"'
+ && (strlen (value) == 7 || strlen (value) == 15)) {
+ /* ASCII passphrase */
+ char *tmp = g_strdup (value);
+ char *p = strip_string (tmp, '"');
+
+ if (!is_ascii (p)) {
+ g_set_error (error, ifnet_plugin_error_quark (),
+ 0, "Invalid ASCII WEP passphrase.");
+ g_free (tmp);
+ goto out;
+
+ }
+
+ converted = utils_bin2hexstr (tmp, strlen (tmp), strlen (tmp) * 2);
+ g_free (tmp);
+ } else {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Invalid WEP key length. Key: %s", value);
+ goto out;
+ }
+
+ if (converted) {
+ nm_setting_wireless_security_set_wep_key (s_wsec, key_idx, converted);
+ g_free (converted);
+ success = TRUE;
+ }
+
+out:
+ return success;
+}
+
+static gboolean
+add_wep_keys (const char *ssid,
+ NMSettingWirelessSecurity *s_wsec,
+ GError **error)
+{
+ if (!add_one_wep_key (ssid, "wep_key0", 0, s_wsec, error))
+ return FALSE;
+ if (!add_one_wep_key (ssid, "wep_key1", 1, s_wsec, error))
+ return FALSE;
+ if (!add_one_wep_key (ssid, "wep_key2", 2, s_wsec, error))
+ return FALSE;
+ if (!add_one_wep_key (ssid, "wep_key3", 3, s_wsec, error))
+ return FALSE;
+ return TRUE;
+
+}
+
+static NMSettingWirelessSecurity *
+make_wep_setting (const char *ssid, GError **error)
+{
+ const char *auth_alg, *value;
+ int default_key_idx = 0;
+ NMSettingWirelessSecurity *s_wireless_sec;
+
+ s_wireless_sec =
+ NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ());
+ g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
+ "none", NULL);
+
+ /* default key index */
+ value = wpa_get_value (ssid, "wep_tx_keyidx");
+ if (value) {
+ default_key_idx = atoi (value);
+ if (default_key_idx >= 0 && default_key_idx <= 3) {
+ g_object_set (s_wireless_sec,
+ NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX,
+ default_key_idx, NULL);
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+ "Default key index: %d", default_key_idx);
+ } else {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Invalid default WEP key '%s'", value);
+ goto error;
+ }
+ }
+
+ if (!add_wep_keys (ssid, s_wireless_sec, error))
+ goto error;
+
+ /* If there's a default key, ensure that key exists */
+ if ((default_key_idx == 1)
+ && !nm_setting_wireless_security_get_wep_key (s_wireless_sec, 1)) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Default WEP key index was 2, but no valid KEY2 exists.");
+ goto error;
+ } else if ((default_key_idx == 2)
+ && !nm_setting_wireless_security_get_wep_key (s_wireless_sec,
+ 2)) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Default WEP key index was 3, but no valid KEY3 exists.");
+ goto error;
+ } else if ((default_key_idx == 3)
+ && !nm_setting_wireless_security_get_wep_key (s_wireless_sec,
+ 3)) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Default WEP key index was 4, but no valid KEY4 exists.");
+ goto error;
+ }
+
+ /* authentication algorithms */
+ auth_alg = wpa_get_value (ssid, "auth_alg");
+ if (auth_alg) {
+ if (strcmp (auth_alg, "OPEN") == 0) {
+ g_object_set (s_wireless_sec,
+ NM_SETTING_WIRELESS_SECURITY_AUTH_ALG,
+ "open", NULL);
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+ "WEP: Use open system authentication");
+ } else if (strcmp (auth_alg, "SHARED") == 0) {
+ g_object_set (s_wireless_sec,
+ NM_SETTING_WIRELESS_SECURITY_AUTH_ALG,
+ "shared", NULL);
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+ "WEP: Use shared system authentication");
+ } else {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Invalid WEP authentication algorithm '%s'",
+ auth_alg);
+ goto error;
+ }
+
+ }
+
+ if (!nm_setting_wireless_security_get_wep_key (s_wireless_sec, 0)
+ && !nm_setting_wireless_security_get_wep_key (s_wireless_sec, 1)
+ && !nm_setting_wireless_security_get_wep_key (s_wireless_sec, 2)
+ && !nm_setting_wireless_security_get_wep_key (s_wireless_sec, 3)
+ && !nm_setting_wireless_security_get_wep_tx_keyidx (s_wireless_sec)) {
+ if (auth_alg && !strcmp (auth_alg, "shared")) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "WEP Shared Key authentication is invalid for "
+ "unencrypted connections.");
+ goto error;
+ }
+ /* Unencrypted */
+ g_object_unref (s_wireless_sec);
+ s_wireless_sec = NULL;
+ }
+ return s_wireless_sec;
+
+error:
+ if (s_wireless_sec)
+ g_object_unref (s_wireless_sec);
+ return NULL;
+}
+
+static char *
+parse_wpa_psk (const char *psk, GError **error)
+{
+ char *hashed = NULL;
+ gboolean quoted = FALSE;
+
+ if (!psk) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Missing WPA_PSK for WPA-PSK key management");
+ return NULL;
+ }
+
+ /* Passphrase must be between 10 and 66 characters in length becuase WPA
+ * hex keys are exactly 64 characters (no quoting), and WPA passphrases
+ * are between 8 and 63 characters (inclusive), plus optional quoting if
+ * the passphrase contains spaces.
+ */
+
+ if (psk[0] == '"' && psk[strlen (psk) - 1] == '"')
+ quoted = TRUE;
+ if (!quoted && (strlen (psk) == 64)) {
+ /* Verify the hex PSK; 64 digits */
+ if (!is_hex (psk)) {
+ g_set_error (error, ifnet_plugin_error_quark (),
+ 0,
+ "Invalid WPA_PSK (contains non-hexadecimal characters)");
+ goto out;
+ }
+ hashed = g_strdup (psk);
+ } else {
+ char *stripped = g_strdup (psk);
+
+ strip_string (stripped, '"');
+
+ /* Length check */
+ if (strlen (stripped) < 8 || strlen (stripped) > 63) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Invalid WPA_PSK (passphrases must be between "
+ "8 and 63 characters long (inclusive))");
+ g_free (stripped);
+ goto out;
+ }
+
+ hashed = g_strdup (stripped);
+ g_free (stripped);
+ }
+
+ if (!hashed) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Invalid WPA_PSK (doesn't look like a passphrase or hex key)");
+ goto out;
+ }
+
+out:
+ return hashed;
+}
+
+static gboolean
+fill_wpa_ciphers (const char *ssid,
+ NMSettingWirelessSecurity *wsec,
+ gboolean group,
+ gboolean adhoc)
+{
+ const char *value;
+ char **list = NULL, **iter;
+ int i = 0;
+
+ value = wpa_get_value (ssid, group ? "group" : "pairwise");
+ if (!value)
+ return TRUE;
+
+ list = g_strsplit_set (value, " ", 0);
+ for (iter = list; iter && *iter; iter++, i++) {
+ /* Ad-Hoc configurations cannot have pairwise ciphers, and can only
+ * have one group cipher. Ignore any additional group ciphers and
+ * any pairwise ciphers specified.
+ */
+ if (adhoc) {
+ if (group && (i > 0)) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ " warning: ignoring group cipher '%s' (only one group cipher allowed in Ad-Hoc mode)",
+ *iter);
+ continue;
+ } else if (!group) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ " warning: ignoring pairwise cipher '%s' (pairwise not used in Ad-Hoc mode)",
+ *iter);
+ continue;
+ }
+ }
+
+ if (!strcmp (*iter, "CCMP")) {
+ if (group)
+ nm_setting_wireless_security_add_group (wsec,
+ "ccmp");
+ else
+ nm_setting_wireless_security_add_pairwise (wsec,
+ "ccmp");
+ } else if (!strcmp (*iter, "TKIP")) {
+ if (group)
+ nm_setting_wireless_security_add_group (wsec,
+ "tkip");
+ else
+ nm_setting_wireless_security_add_pairwise (wsec,
+ "tkip");
+ } else if (group && !strcmp (*iter, "WEP104"))
+ nm_setting_wireless_security_add_group (wsec, "wep104");
+ else if (group && !strcmp (*iter, "WEP40"))
+ nm_setting_wireless_security_add_group (wsec, "wep40");
+ else {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ " warning: ignoring invalid %s cipher '%s'",
+ group ? "CIPHER_GROUP" : "CIPHER_PAIRWISE",
+ *iter);
+ }
+ }
+
+ if (list)
+ g_strfreev (list);
+ return TRUE;
+}
+
+static NMSetting8021x *
+fill_8021x (const char *ssid,
+ const char *key_mgmt,
+ gboolean wifi,
+ GError **error)
+{
+ NMSetting8021x *s_8021x;
+ const char *value;
+ char **list, **iter;
+
+ value = wpa_get_value (ssid, "eap");
+ if (!value) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Missing IEEE_8021X_EAP_METHODS for key management '%s'",
+ key_mgmt);
+ return NULL;
+ }
+
+ list = g_strsplit (value, " ", 0);
+
+ s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
+ /* Validate and handle each EAP method */
+ for (iter = list; iter && *iter; iter++) {
+ EAPReader *eap = &eap_readers[0];
+ gboolean found = FALSE;
+ char *lower = NULL;
+
+ lower = g_ascii_strdown (*iter, -1);
+ while (eap->method && !found) {
+ if (strcmp (eap->method, lower))
+ goto next;
+
+ /* Some EAP methods don't provide keying material, thus they
+ * cannot be used with WiFi unless they are an inner method
+ * used with TTLS or PEAP or whatever.
+ */
+ if (wifi && eap->wifi_phase2_only) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ " warning: ignored invalid "
+ "IEEE_8021X_EAP_METHOD '%s'; not allowed for wifi.",
+ lower);
+ goto next;
+ }
+
+ /* Parse EAP method specific options */
+ if (!(*eap->reader)
+ (lower, ssid, s_8021x, FALSE, error)) {
+ g_free (lower);
+ goto error;
+ }
+ nm_setting_802_1x_add_eap_method (s_8021x, lower);
+ found = TRUE;
+
+ next:
+ eap++;
+ }
+
+ if (!found) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ " warning: ignored unknown"
+ "IEEE_8021X_EAP_METHOD '%s'.", lower);
+ }
+ g_free (lower);
+ }
+ g_strfreev (list);
+
+ if (nm_setting_802_1x_get_num_eap_methods (s_8021x) == 0) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "No valid EAP methods found in IEEE_8021X_EAP_METHODS.");
+ goto error;
+ }
+
+ return s_8021x;
+
+error:
+ g_object_unref (s_8021x);
+ return NULL;
+}
+
+static NMSettingWirelessSecurity *
+make_wpa_setting (const char *ssid,
+ NMSetting8021x **s_8021x,
+ GError **error)
+{
+ NMSettingWirelessSecurity *wsec;
+ const char *value;
+ char *lower;
+ gboolean adhoc = FALSE;
+
+ if (!exist_ssid (ssid)) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "No security info found for ssid: %s", ssid);
+ return NULL;
+ }
+
+ wsec =
+ NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ());
+
+ /* mode=1: adhoc
+ * mode=0: infrastructure */
+ value = wpa_get_value (ssid, "mode");
+ if (value)
+ adhoc = strcmp (value, "1") == 0 ? TRUE : FALSE;
+
+ value = wpa_get_value (ssid, "key_mgmt");
+ /* Not WPA or Dynamic WEP */
+ if (!value)
+ goto error;
+ if (strcmp (value, "WPA-PSK") && strcmp (value, "WPA-EAP"))
+ goto error;
+ /* Pairwise and Group ciphers */
+ fill_wpa_ciphers (ssid, wsec, FALSE, adhoc);
+ fill_wpa_ciphers (ssid, wsec, TRUE, adhoc);
+
+ /* WPA and/or RSN */
+ if (adhoc) {
+ /* Ad-Hoc mode only supports WPA proto for now */
+ nm_setting_wireless_security_add_proto (wsec, "wpa");
+ } else {
+ nm_setting_wireless_security_add_proto (wsec, "wpa");
+ nm_setting_wireless_security_add_proto (wsec, "rsn");
+
+ }
+
+ if (!strcmp (value, "WPA-PSK")) {
+ char *psk = parse_wpa_psk (wpa_get_value (ssid, "psk"), error);
+
+ if (!psk)
+ goto error;
+ g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_PSK, psk,
+ NULL);
+ g_free (psk);
+
+ if (adhoc)
+ g_object_set (wsec,
+ NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
+ "wpa-none", NULL);
+ else
+ g_object_set (wsec,
+ NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
+ "wpa-psk", NULL);
+ } else if (!strcmp (value, "WPA-EAP") || !strcmp (value, "IEEE8021X")) {
+ if (adhoc) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Ad-Hoc mode cannot be used with KEY_MGMT type '%s'",
+ value);
+ goto error;
+ }
+ *s_8021x = fill_8021x (ssid, value, TRUE, error);
+ if (!*s_8021x)
+ goto error;
+
+ lower = g_ascii_strdown (value, -1);
+ g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT,
+ lower, NULL);
+ g_free (lower);
+ } else {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Unknown wireless KEY_MGMT type '%s'", value);
+ goto error;
+ }
+ return wsec;
+error:
+ if (wsec)
+ g_object_unref (wsec);
+ return NULL;
+}
+
+static NMSettingWirelessSecurity *
+make_wireless_security_setting (const char *conn_name,
+ NMSetting8021x **s_8021x,
+ GError ** error)
+{
+ NMSettingWirelessSecurity *wsec = NULL;
+ const char *ssid;
+ gboolean adhoc = FALSE;
+ const char *value;
+
+ g_return_val_if_fail (conn_name != NULL
+ && strcmp (ifnet_get_data (conn_name, "type"),
+ "ppp") != 0, NULL);
+ if (!wpa_get_value (conn_name, "ssid"))
+ return NULL;
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+ "updating wireless security settings (%s).", conn_name);
+
+ ssid = conn_name;
+ value = wpa_get_value (ssid, "mode");
+ if (value)
+ adhoc = strcmp (value, "1") == 0 ? TRUE : FALSE;
+
+ if (!adhoc) {
+ wsec = make_leap_setting (ssid, error);
+ if (error && *error)
+ goto error;
+ }
+ if (!wsec) {
+ wsec = make_wpa_setting (ssid, s_8021x, error);
+ if (error && *error)
+ goto error;
+ }
+ if (!wsec) {
+ wsec = make_wep_setting (ssid, error);
+ if (error && *error)
+ goto error;
+ }
+
+ if (!wsec) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Can't handle security information for ssid: %s",
+ conn_name);
+ }
+
+ return wsec;
+error:
+ return NULL;
+}
+
+/* Currently only support username and password */
+static void
+make_pppoe_connection_setting (NMConnection *connection,
+ const char *conn_name,
+ GError **error)
+{
+ NMSettingPPPOE *s_pppoe;
+ NMSettingPPP *s_ppp;
+ const char *value;
+
+ s_pppoe = NM_SETTING_PPPOE (nm_setting_pppoe_new ());
+
+ /* username */
+ value = ifnet_get_data (conn_name, "username");
+ if (!value) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "ppp requires at lease a username");
+ return;
+ }
+ g_object_set (s_pppoe, NM_SETTING_PPPOE_USERNAME, value, NULL);
+
+ /* password */
+ value = ifnet_get_data (conn_name, "password");
+ if (!value) {
+ value = "";
+ }
+
+ g_object_set (s_pppoe, NM_SETTING_PPPOE_PASSWORD, value, NULL);
+ nm_connection_add_setting (connection, NM_SETTING (s_pppoe));
+
+ /* PPP setting */
+ s_ppp = (NMSettingPPP *) nm_setting_ppp_new ();
+ nm_connection_add_setting (connection, NM_SETTING (s_ppp));
+}
+
+NMConnection *
+ifnet_update_connection_from_config_block (const char *conn_name, GError **error)
+{
+ const gchar *type = NULL;
+ NMConnection *connection = NULL;
+ NMSettingConnection *setting = NULL;
+ NMSetting8021x *s_8021x = NULL;
+ NMSettingWirelessSecurity *wsec = NULL;
+ gboolean auto_conn = TRUE;
+ const char *value = NULL;
+ gboolean success = FALSE;
+
+ connection = nm_connection_new ();
+ if (!connection)
+ return NULL;
+ setting =
+ (NMSettingConnection *) nm_connection_get_setting (connection,
+ NM_TYPE_SETTING_CONNECTION);
+ if (!setting) {
+ setting = NM_SETTING_CONNECTION (nm_setting_connection_new ());
+ g_assert (setting);
+ nm_connection_add_setting (connection, NM_SETTING (setting));
+ }
+
+ type = guess_connection_type (conn_name);
+ value = ifnet_get_data (conn_name, "auto");
+ if (value && !strcmp (value, "false"))
+ auto_conn = FALSE;
+ update_connection_id (connection, conn_name);
+ g_object_set (setting, NM_SETTING_CONNECTION_TYPE, type,
+ NM_SETTING_CONNECTION_READ_ONLY, FALSE,
+ NM_SETTING_CONNECTION_AUTOCONNECT, auto_conn, NULL);
+
+ if (!strcmp (NM_SETTING_WIRED_SETTING_NAME, type)
+ || !strcmp (NM_SETTING_PPPOE_SETTING_NAME, type)) {
+ /* wired setting */
+ make_wired_connection_setting (connection, conn_name, error);
+ if (error && *error) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "Found error: %s", (*error)->message);
+ goto error;
+ }
+ /* pppoe setting */
+ if (!strcmp (NM_SETTING_PPPOE_SETTING_NAME, type))
+ make_pppoe_connection_setting (connection, conn_name,
+ error);
+ if (error && *error) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "Found error: %s", (*error)->message);
+ goto error;
+ }
+ } else if (!strcmp (NM_SETTING_WIRELESS_SETTING_NAME, type)) {
+ /* wireless setting */
+ NMSetting *wireless_setting;
+
+ wireless_setting = make_wireless_connection_setting (conn_name, &s_8021x, error);
+ if (!wireless_setting)
+ goto error;
+ nm_connection_add_setting (connection, wireless_setting);
+
+ if (error && *error) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "Found error: %s", (*error)->message);
+ goto error;
+ }
+
+ /* wireless security setting */
+ wsec = make_wireless_security_setting (conn_name, &s_8021x, error);
+ if (wsec) {
+ nm_connection_add_setting (connection,
+ NM_SETTING (wsec));
+ if (s_8021x)
+ nm_connection_add_setting (connection,
+ NM_SETTING
+ (s_8021x));
+ g_object_set (wireless_setting, NM_SETTING_WIRELESS_SEC,
+ NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+ NULL);
+ }
+
+ if (error && *error) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "Found error: %s", (*error)->message);
+ goto error;
+ }
+
+ } else
+ goto error;
+
+ /* IPv4 setting */
+ make_ip4_setting (connection, conn_name, error);
+ if (error && *error)
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "Found error: %s", (*error)->message);
+
+ /* IPv6 setting */
+ make_ip6_setting (connection, conn_name, error);
+ if (error && *error)
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "Found error: %s", (*error)->message);
+
+ success = nm_connection_verify (connection, error);
+ if (error && *error)
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "Found error: %s", (*error)->message);
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Connection verified %s:%d", conn_name, success);
+ if (!success)
+ goto error;
+ return connection;
+
+error:
+ g_object_unref (setting);
+ g_object_unref (connection);
+ return NULL;
+}
+
+typedef NMSetting8021xCKScheme (*SchemeFunc) (NMSetting8021x * setting);
+typedef const char *(*PathFunc) (NMSetting8021x * setting);
+typedef const GByteArray *(*BlobFunc) (NMSetting8021x * setting);
+
+typedef struct ObjectType {
+ const char *setting_key;
+ SchemeFunc scheme_func;
+ PathFunc path_func;
+ BlobFunc blob_func;
+ const char *conn_name_key;
+ const char *suffix;
+} ObjectType;
+
+static const ObjectType ca_type = {
+ NM_SETTING_802_1X_CA_CERT,
+ nm_setting_802_1x_get_ca_cert_scheme,
+ nm_setting_802_1x_get_ca_cert_path,
+ nm_setting_802_1x_get_ca_cert_blob,
+ "ca_cert",
+ "ca-cert.der"
+};
+
+static const ObjectType phase2_ca_type = {
+ NM_SETTING_802_1X_PHASE2_CA_CERT,
+ nm_setting_802_1x_get_phase2_ca_cert_scheme,
+ nm_setting_802_1x_get_phase2_ca_cert_path,
+ nm_setting_802_1x_get_phase2_ca_cert_blob,
+ "ca_cert2",
+ "inner-ca-cert.der"
+};
+
+static const ObjectType client_type = {
+ NM_SETTING_802_1X_CLIENT_CERT,
+ nm_setting_802_1x_get_client_cert_scheme,
+ nm_setting_802_1x_get_client_cert_path,
+ nm_setting_802_1x_get_client_cert_blob,
+ "client_cert",
+ "client-cert.der"
+};
+
+static const ObjectType phase2_client_type = {
+ NM_SETTING_802_1X_PHASE2_CLIENT_CERT,
+ nm_setting_802_1x_get_phase2_client_cert_scheme,
+ nm_setting_802_1x_get_phase2_client_cert_path,
+ nm_setting_802_1x_get_phase2_client_cert_blob,
+ "client_cert2",
+ "inner-client-cert.der"
+};
+
+static const ObjectType pk_type = {
+ NM_SETTING_802_1X_PRIVATE_KEY,
+ nm_setting_802_1x_get_private_key_scheme,
+ nm_setting_802_1x_get_private_key_path,
+ nm_setting_802_1x_get_private_key_blob,
+ "private_key",
+ "private-key.pem"
+};
+
+static const ObjectType phase2_pk_type = {
+ NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
+ nm_setting_802_1x_get_phase2_private_key_scheme,
+ nm_setting_802_1x_get_phase2_private_key_path,
+ nm_setting_802_1x_get_phase2_private_key_blob,
+ "private_key2",
+ "inner-private-key.pem"
+};
+
+static const ObjectType p12_type = {
+ NM_SETTING_802_1X_PRIVATE_KEY,
+ nm_setting_802_1x_get_private_key_scheme,
+ nm_setting_802_1x_get_private_key_path,
+ nm_setting_802_1x_get_private_key_blob,
+ "private_key",
+ "private-key.p12"
+};
+
+static const ObjectType phase2_p12_type = {
+ NM_SETTING_802_1X_PHASE2_PRIVATE_KEY,
+ nm_setting_802_1x_get_phase2_private_key_scheme,
+ nm_setting_802_1x_get_phase2_private_key_path,
+ nm_setting_802_1x_get_phase2_private_key_blob,
+ "private_key2",
+ "inner-private-key.p12"
+};
+
+static gboolean
+write_object (NMSetting8021x *s_8021x,
+ const char *conn_name,
+ const GByteArray *override_data,
+ const ObjectType *objtype,
+ GError **error)
+{
+ NMSetting8021xCKScheme scheme;
+ const char *path = NULL;
+ const GByteArray *blob = NULL;
+
+ g_return_val_if_fail (conn_name != NULL, FALSE);
+ g_return_val_if_fail (objtype != NULL, FALSE);
+ if (override_data)
+ /* if given explicit data to save, always use that instead of asking
+ * the setting what to do.
+ */
+ blob = override_data;
+ else {
+ scheme = (*(objtype->scheme_func)) (s_8021x);
+ switch (scheme) {
+ case NM_SETTING_802_1X_CK_SCHEME_BLOB:
+ blob = (*(objtype->blob_func)) (s_8021x);
+ break;
+ case NM_SETTING_802_1X_CK_SCHEME_PATH:
+ path = (*(objtype->path_func)) (s_8021x);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* If the object path was specified, prefer that over any raw cert data that
+ * may have been sent.
+ */
+ if (path) {
+ wpa_set_data (conn_name, (gchar *) objtype->conn_name_key,
+ (gchar *) path);
+ return TRUE;
+ }
+
+ /* does not support writing encryption data now */
+ if (blob) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ " warning: Currently we do not support certs writing.");
+ }
+
+ return TRUE;
+}
+
+static gboolean
+write_8021x_certs (NMSetting8021x *s_8021x,
+ gboolean phase2,
+ const char *conn_name,
+ GError **error)
+{
+ char *password = NULL;
+ const ObjectType *otype = NULL;
+ gboolean is_pkcs12 = FALSE, success = FALSE;
+ const GByteArray *blob = NULL;
+ GByteArray *enc_key = NULL;
+ gchar *generated_pw = NULL;
+
+ /* CA certificate */
+ if (phase2)
+ otype = &phase2_ca_type;
+ else
+ otype = &ca_type;
+
+ if (!write_object (s_8021x, conn_name, NULL, otype, error))
+ return FALSE;
+
+ /* Private key */
+ if (phase2) {
+ if (nm_setting_802_1x_get_phase2_private_key_scheme (s_8021x) !=
+ NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) {
+ if (nm_setting_802_1x_get_phase2_private_key_format
+ (s_8021x) == NM_SETTING_802_1X_CK_FORMAT_PKCS12)
+ is_pkcs12 = TRUE;
+ }
+ password = (char *)
+ nm_setting_802_1x_get_phase2_private_key_password (s_8021x);
+ } else {
+ if (nm_setting_802_1x_get_private_key_scheme (s_8021x) !=
+ NM_SETTING_802_1X_CK_SCHEME_UNKNOWN) {
+ if (nm_setting_802_1x_get_private_key_format (s_8021x)
+ == NM_SETTING_802_1X_CK_FORMAT_PKCS12)
+ is_pkcs12 = TRUE;
+ }
+ password = (char *)
+ nm_setting_802_1x_get_private_key_password (s_8021x);
+ }
+
+ if (is_pkcs12)
+ otype = phase2 ? &phase2_p12_type : &p12_type;
+ else
+ otype = phase2 ? &phase2_pk_type : &pk_type;
+
+ if ((*(otype->scheme_func)) (s_8021x) ==
+ NM_SETTING_802_1X_CK_SCHEME_BLOB)
+ blob = (*(otype->blob_func)) (s_8021x);
+
+ /* Only do the private key re-encrypt dance if we got the raw key data, which
+ * by definition will be unencrypted. If we're given a direct path to the
+ * private key file, it'll be encrypted, so we don't need to re-encrypt.
+ */
+ if (blob && !is_pkcs12) {
+ /* Encrypt the unencrypted private key with the fake password */
+ enc_key =
+ nm_utils_rsa_key_encrypt (blob, password, &generated_pw,
+ error);
+ if (!enc_key)
+ goto out;
+
+ if (generated_pw)
+ password = generated_pw;
+ }
+
+ /* Save the private key */
+ if (!write_object
+ (s_8021x, conn_name, enc_key ? enc_key : blob, otype, error))
+ goto out;
+
+ if (phase2)
+ wpa_set_data (conn_name, "private_key_passwd2", password);
+ else
+ wpa_set_data (conn_name, "private_key_passwd", password);
+
+ /* Client certificate */
+ if (is_pkcs12) {
+ wpa_set_data (conn_name,
+ phase2 ? "client_cert2" : "client_cert", NULL);
+ } else {
+ if (phase2)
+ otype = &phase2_client_type;
+ else
+ otype = &client_type;
+
+ /* Save the client certificate */
+ if (!write_object (s_8021x, conn_name, NULL, otype, error))
+ goto out;
+ }
+
+ success = TRUE;
+out:
+ if (generated_pw) {
+ memset (generated_pw, 0, strlen (generated_pw));
+ g_free (generated_pw);
+ }
+ if (enc_key) {
+ memset (enc_key->data, 0, enc_key->len);
+ g_byte_array_free (enc_key, TRUE);
+ }
+ return success;
+}
+
+static gboolean
+write_8021x_setting (NMConnection *connection,
+ const char *conn_name,
+ gboolean wired,
+ GError **error)
+{
+ NMSetting8021x *s_8021x;
+ const char *value;
+ char *tmp = NULL;
+ gboolean success = FALSE;
+ GString *phase2_auth;
+ GString *phase1;
+
+ s_8021x =
+ (NMSetting8021x *) nm_connection_get_setting (connection,
+ NM_TYPE_SETTING_802_1X);
+
+ if (!s_8021x) {
+ return TRUE;
+ }
+
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Adding 8021x setting for %s",
+ conn_name);
+
+ /* If wired, write KEY_MGMT */
+ if (wired)
+ wpa_set_data (conn_name, "key_mgmt", "IEEE8021X");
+
+ /* EAP method */
+ if (nm_setting_802_1x_get_num_eap_methods (s_8021x)) {
+ value = nm_setting_802_1x_get_eap_method (s_8021x, 0);
+ if (value)
+ tmp = g_ascii_strup (value, -1);
+ }
+ wpa_set_data (conn_name, "eap", tmp ? tmp : NULL);
+ g_free (tmp);
+
+ wpa_set_data (conn_name, "identity",
+ (gchar *) nm_setting_802_1x_get_identity (s_8021x));
+
+ wpa_set_data (conn_name, "anonymous_identity", (gchar *)
+ nm_setting_802_1x_get_anonymous_identity (s_8021x));
+
+ wpa_set_data (conn_name, "password",
+ (gchar *) nm_setting_802_1x_get_password (s_8021x));
+
+ phase1 = g_string_new (NULL);
+
+ /* PEAP version */
+ wpa_set_data (conn_name, "phase1", NULL);
+ value = nm_setting_802_1x_get_phase1_peapver (s_8021x);
+ if (value && (!strcmp (value, "0") || !strcmp (value, "1")))
+ g_string_append_printf (phase1, "peapver=%s ", value);
+
+ /* PEAP label */
+ value = nm_setting_802_1x_get_phase1_peaplabel (s_8021x);
+ if (value && !strcmp (value, "1"))
+ g_string_append_printf (phase1, "peaplabel=%s ", value);
+ if (phase1->len) {
+ tmp = g_strstrip (g_strdup (phase1->str));
+ wpa_set_data (conn_name, "phase1", tmp);
+ g_free (tmp);
+ }
+
+ /* Phase2 auth methods */
+ wpa_set_data (conn_name, "phase2", NULL);
+ phase2_auth = g_string_new (NULL);
+
+ value = nm_setting_802_1x_get_phase2_auth (s_8021x);
+ if (value) {
+ tmp = g_ascii_strup (value, -1);
+ g_string_append_printf (phase2_auth, "auth=%s ", tmp);
+ g_free (tmp);
+ }
+
+ /* Phase2 auth heap */
+ value = nm_setting_802_1x_get_phase2_autheap (s_8021x);
+ if (value) {
+ tmp = g_ascii_strup (value, -1);
+ g_string_append_printf (phase2_auth, "autheap=%s ", tmp);
+ g_free (tmp);
+ }
+ tmp = g_strstrip (g_strdup (phase2_auth->str));
+ wpa_set_data (conn_name, "phase2", phase2_auth->len ? tmp : NULL);
+ g_free (tmp);
+
+ g_string_free (phase2_auth, TRUE);
+ g_string_free (phase1, TRUE);
+
+ success = write_8021x_certs (s_8021x, FALSE, conn_name, error);
+ if (success) {
+ /* phase2/inner certs */
+ success = write_8021x_certs (s_8021x, TRUE, conn_name, error);
+ }
+
+ return success;
+}
+
+static gboolean
+write_wireless_security_setting (NMConnection * connection,
+ gchar * conn_name,
+ gboolean adhoc,
+ gboolean * no_8021x, GError ** error)
+{
+ NMSettingWirelessSecurity *s_wsec;
+ const char *key_mgmt, *auth_alg, *key, *cipher, *psk;
+ gboolean wep = FALSE, wpa = FALSE;
+ char *tmp;
+ guint32 i, num;
+ GString *str;
+
+ s_wsec =
+ (NMSettingWirelessSecurity *) nm_connection_get_setting (connection,
+ NM_TYPE_SETTING_WIRELESS_SECURITY);
+ if (!s_wsec) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Missing '%s' setting",
+ NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
+ return FALSE;
+ }
+
+ key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec);
+ g_assert (key_mgmt);
+
+ auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec);
+
+ if (!strcmp (key_mgmt, "none")) {
+ wpa_set_data (conn_name, "key_mgmt", "NONE");
+ wep = TRUE;
+ *no_8021x = TRUE;
+ } else if (!strcmp (key_mgmt, "wpa-none")
+ || !strcmp (key_mgmt, "wpa-psk")) {
+ wpa_set_data (conn_name, "key_mgmt", "WPA-PSK");
+ wpa = TRUE;
+ *no_8021x = TRUE;
+ } else if (!strcmp (key_mgmt, "ieee8021x")) {
+ wpa_set_data (conn_name, "key_mgmt", "IEEE8021X");
+ } else if (!strcmp (key_mgmt, "wpa-eap")) {
+ wpa_set_data (conn_name, "key_mgmt", "WPA-EAP");
+ wpa = TRUE;
+ } else
+ PLUGIN_WARN (IFNET_PLUGIN_NAME, "Unknown key_mgmt: %s", key_mgmt);
+
+ if (auth_alg) {
+ if (!strcmp (auth_alg, "shared"))
+ wpa_set_data (conn_name, "auth_alg", "SHARED");
+ else if (!strcmp (auth_alg, "open"))
+ wpa_set_data (conn_name, "auth_alg", "OPEN");
+ else if (!strcmp (auth_alg, "leap")) {
+ wpa_set_data (conn_name, "auth_alg", "LEAP");
+ wpa_set_data (conn_name, "eap", "LEAP");
+ wpa_set_data (conn_name, "identity", (gchar *)
+ nm_setting_wireless_security_get_leap_username
+ (s_wsec));
+ wpa_set_data (conn_name, "password", (gchar *)
+ nm_setting_wireless_security_get_leap_password
+ (s_wsec));
+ *no_8021x = TRUE;
+ }
+ } else
+ wpa_set_data (conn_name, "auth_alg", NULL);
+
+ /* Default WEP TX key index */
+ wpa_set_data (conn_name, "wep_tx_keyidx", NULL);
+ if (wep) {
+ tmp =
+ g_strdup_printf ("%d",
+ nm_setting_wireless_security_get_wep_tx_keyidx
+ (s_wsec));
+ wpa_set_data (conn_name, "wep_tx_keyidx", tmp);
+ g_free (tmp);
+ }
+
+ /* WEP keys */
+ for (i = 0; i < 4; i++) {
+ int length;
+
+ key = nm_setting_wireless_security_get_wep_key (s_wsec, i);
+ if (!key)
+ continue;
+ tmp = g_strdup_printf ("wep_key%d", i);
+ length = strlen (key);
+ if (length == 10 || length == 26 || length == 58)
+ wpa_set_data (conn_name, tmp, (gchar *) key);
+ else {
+ gchar *tmp_key = g_strdup_printf ("\"%s\"", key);
+
+ wpa_set_data (conn_name, tmp, tmp_key);
+ g_free (tmp_key);
+ }
+ g_free (tmp);
+ }
+
+ /* WPA Pairwise ciphers */
+ wpa_set_data (conn_name, "pairwise", NULL);
+ str = g_string_new (NULL);
+ num = nm_setting_wireless_security_get_num_pairwise (s_wsec);
+ for (i = 0; i < num; i++) {
+ if (i > 0)
+ g_string_append_c (str, ' ');
+ cipher = nm_setting_wireless_security_get_pairwise (s_wsec, i);
+ tmp = g_ascii_strup (cipher, -1);
+ g_string_append (str, tmp);
+ g_free (tmp);
+ }
+ if (strlen (str->str))
+ wpa_set_data (conn_name, "pairwise", str->str);
+ g_string_free (str, TRUE);
+
+ /* WPA Group ciphers */
+ wpa_set_data (conn_name, "group", NULL);
+ str = g_string_new (NULL);
+ num = nm_setting_wireless_security_get_num_groups (s_wsec);
+ for (i = 0; i < num; i++) {
+ if (i > 0)
+ g_string_append_c (str, ' ');
+ cipher = nm_setting_wireless_security_get_group (s_wsec, i);
+ tmp = g_ascii_strup (cipher, -1);
+ g_string_append (str, tmp);
+ g_free (tmp);
+ }
+ if (strlen (str->str))
+ wpa_set_data (conn_name, "group", str->str);
+ g_string_free (str, TRUE);
+
+ /* WPA Passphrase */
+ if (wpa) {
+ GString *quoted = NULL;
+
+ psk = nm_setting_wireless_security_get_psk (s_wsec);
+ if (psk && (strlen (psk) != 64)) {
+ quoted = g_string_sized_new (strlen (psk) + 2);
+ g_string_append_c (quoted, '"');
+ g_string_append (quoted, psk);
+ g_string_append_c (quoted, '"');
+ }
+ /* psk will be lost here if we don't check it for NULL */
+ if (psk)
+ wpa_set_data (conn_name, "psk",
+ quoted ? quoted->str : (gchar *) psk);
+ if (quoted)
+ g_string_free (quoted, TRUE);
+ } else
+ wpa_set_data (conn_name, "psk", NULL);
+
+ return TRUE;
+}
+
+/* remove old ssid and add new one*/
+static void
+update_wireless_ssid (NMConnection *connection,
+ const char *conn_name,
+ const char *ssid,
+ gboolean hex)
+{
+ if(strcmp (conn_name, ssid)){
+ ifnet_delete_network (conn_name);
+ wpa_delete_security (conn_name);
+ }
+
+ ifnet_add_network (ssid, "wireless");
+ wpa_add_security (ssid);
+}
+
+static gboolean
+write_wireless_setting (NMConnection *connection,
+ const char *conn_name,
+ gboolean *no_8021x,
+ const char **out_new_name,
+ GError **error)
+{
+ NMSettingWireless *s_wireless;
+ const GByteArray *ssid, *mac, *bssid;
+ const char *mode;
+ char buf[33];
+ guint32 mtu, i;
+ gboolean adhoc = FALSE, hex_ssid = FALSE;
+ gchar *ssid_str, *tmp;
+
+ s_wireless = (NMSettingWireless *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS);
+ if (!s_wireless) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Missing '%s' setting",
+ NM_SETTING_WIRELESS_SETTING_NAME);
+ return FALSE;
+ }
+
+ ssid = nm_setting_wireless_get_ssid (s_wireless);
+ if (!ssid) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Missing SSID in '%s' setting",
+ NM_SETTING_WIRELESS_SETTING_NAME);
+ return FALSE;
+ }
+ if (!ssid->len || ssid->len > 32) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Invalid SSID in '%s' setting",
+ NM_SETTING_WIRELESS_SETTING_NAME);
+ return FALSE;
+ }
+
+ /* If the SSID contains any non-alnum characters, we need to use
+ * the hex notation of the SSID instead. (Because openrc doesn't
+ * support these characters, see bug #356337)
+ */
+ for (i = 0; i < ssid->len; i++) {
+ if (!isalnum (ssid->data[i])) {
+ hex_ssid = TRUE;
+ break;
+ }
+ }
+
+ if (hex_ssid) {
+ GString *str;
+
+ /* Hex SSIDs don't get quoted */
+ str = g_string_sized_new (ssid->len * 2 + 3);
+ g_string_append (str, "0x");
+ for (i = 0; i < ssid->len; i++)
+ g_string_append_printf (str, "%02X", ssid->data[i]);
+ update_wireless_ssid (connection, conn_name, str->str, hex_ssid);
+ ssid_str = g_string_free (str, FALSE);
+ } else {
+ /* Printable SSIDs get quoted */
+ memset (buf, 0, sizeof (buf));
+ memcpy (buf, ssid->data, ssid->len);
+ g_strstrip (buf);
+ update_wireless_ssid (connection, conn_name, buf, hex_ssid);
+ ssid_str = g_strdup (buf);
+ }
+
+ ifnet_set_data (ssid_str, "mac", NULL);
+ mac = nm_setting_wireless_get_mac_address (s_wireless);
+ if (mac) {
+ tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
+ mac->data[0], mac->data[1], mac->data[2],
+ mac->data[3], mac->data[4],
+ mac->data[5]);
+ ifnet_set_data (ssid_str, "mac", tmp);
+ g_free (tmp);
+ }
+
+ ifnet_set_data (ssid_str, "mtu", NULL);
+ mtu = nm_setting_wireless_get_mtu (s_wireless);
+ if (mtu) {
+ tmp = g_strdup_printf ("%u", mtu);
+ ifnet_set_data (ssid_str, "mtu", tmp);
+ g_free (tmp);
+ }
+
+ ifnet_set_data (ssid_str, "mode", NULL);
+ mode = nm_setting_wireless_get_mode (s_wireless);
+ if (!mode || !strcmp (mode, "infrastructure")) {
+ wpa_set_data (ssid_str, "mode", "0");
+ } else if (!strcmp (mode, "adhoc")) {
+ wpa_set_data (ssid_str, "mode", "1");
+ adhoc = TRUE;
+ } else {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "Invalid mode '%s' in '%s' setting",
+ mode, NM_SETTING_WIRELESS_SETTING_NAME);
+ return FALSE;
+ }
+
+ wpa_set_data (ssid_str, "bssid", NULL);
+ bssid = nm_setting_wireless_get_bssid (s_wireless);
+ if (bssid) {
+ tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
+ bssid->data[0], bssid->data[1],
+ bssid->data[2], bssid->data[3],
+ bssid->data[4], bssid->data[5]);
+ wpa_set_data (ssid_str, "bssid", tmp);
+ g_free (tmp);
+ }
+
+ if (nm_setting_wireless_get_security (s_wireless)) {
+ if (!write_wireless_security_setting
+ (connection, ssid_str, adhoc, no_8021x, error))
+ return FALSE;
+ } else
+ wpa_delete_security (ssid_str);
+
+ if (out_new_name)
+ *out_new_name = ifnet_get_data (ssid_str, "name");
+ g_free (ssid_str);
+ return TRUE;
+}
+
+static gboolean
+write_wired_setting (NMConnection *connection,
+ const char *conn_name,
+ GError **error)
+{
+ NMSettingWired *s_wired;
+ const GByteArray *mac;
+ char *tmp;
+ guint32 mtu;
+
+ s_wired =
+ (NMSettingWired *) nm_connection_get_setting (connection,
+ NM_TYPE_SETTING_WIRED);
+ if (!s_wired) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Missing '%s' setting",
+ NM_SETTING_WIRED_SETTING_NAME);
+ return FALSE;
+ }
+
+ ifnet_set_data (conn_name, "mac", NULL);
+ mac = nm_setting_wired_get_mac_address (s_wired);
+ if (mac) {
+ tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
+ mac->data[0], mac->data[1], mac->data[2],
+ mac->data[3], mac->data[4],
+ mac->data[5]);
+ ifnet_set_data (conn_name, "mac", tmp);
+ g_free (tmp);
+ }
+
+ ifnet_set_data (conn_name, "mtu", NULL);
+ mtu = nm_setting_wired_get_mtu (s_wired);
+ if (mtu) {
+ tmp = g_strdup_printf ("%u", mtu);
+ ifnet_set_data (conn_name, "mtu", tmp);
+ g_free (tmp);
+ }
+ //FIXME may add connection type in future
+ //ifnet_set_data (conn_name, "TYPE", TYPE_ETHERNET);
+
+ return TRUE;
+}
+
+static void
+write_connection_setting (NMSettingConnection *s_con, const char *conn_name)
+{
+ ifnet_set_data (conn_name, "auto",
+ nm_setting_connection_get_autoconnect (s_con) ? "true" :
+ "false");
+}
+
+static gboolean
+write_ip4_setting (NMConnection *connection, const char *conn_name, GError **error)
+{
+ NMSettingIP4Config *s_ip4;
+ const char *value;
+ char *tmp;
+ guint32 i, num;
+ GString *searches;
+ GString *ips;
+ GString *routes;
+ GString *dns;
+ gboolean has_def_route = FALSE;
+ gboolean success = FALSE;
+
+ s_ip4 =
+ (NMSettingIP4Config *) nm_connection_get_setting (connection,
+ NM_TYPE_SETTING_IP4_CONFIG);
+ if (!s_ip4) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Missing '%s' setting",
+ NM_SETTING_IP4_CONFIG_SETTING_NAME);
+ return FALSE;
+ }
+ routes = g_string_new (NULL);
+
+ value = nm_setting_ip4_config_get_method (s_ip4);
+ g_assert (value);
+ if (!strcmp (value, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) {
+
+ num = nm_setting_ip4_config_get_num_addresses (s_ip4);
+ ips = g_string_new (NULL);
+ /* IPv4 addresses */
+ for (i = 0; i < num; i++) {
+ char buf[INET_ADDRSTRLEN + 1];
+ NMIP4Address *addr;
+ guint32 ip;
+
+ addr = nm_setting_ip4_config_get_address (s_ip4, i);
+
+ memset (buf, 0, sizeof (buf));
+ ip = nm_ip4_address_get_address (addr);
+ inet_ntop (AF_INET, (const void *) &ip, &buf[0],
+ sizeof (buf));
+ g_string_append_printf (ips, "\"%s", &buf[0]);
+
+ tmp =
+ g_strdup_printf ("%u",
+ nm_ip4_address_get_prefix (addr));
+ g_string_append_printf (ips, "/%s\" ", tmp);
+ g_free (tmp);
+
+ /* only the first gateway will be written */
+ if (!has_def_route && nm_ip4_address_get_gateway (addr)) {
+ memset (buf, 0, sizeof (buf));
+ ip = nm_ip4_address_get_gateway (addr);
+ inet_ntop (AF_INET, (const void *) &ip, &buf[0],
+ sizeof (buf));
+ g_string_append_printf (routes,
+ "\"default via %s\" ",
+ &buf[0]);
+ has_def_route = TRUE;
+ }
+ }
+ ifnet_set_data (conn_name, "config", ips->str);
+ g_string_free (ips, TRUE);
+ } else if (!strcmp (value, NM_SETTING_IP4_CONFIG_METHOD_SHARED))
+ ifnet_set_data (conn_name, "config", "shared");
+ else if (!strcmp (value, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL))
+ ifnet_set_data (conn_name, "config", "autoip");
+ else
+ ifnet_set_data (conn_name, "config", "dhcp");
+
+ /* DNS Servers */
+ num = nm_setting_ip4_config_get_num_dns (s_ip4);
+ if (num > 0) {
+ dns = g_string_new (NULL);
+ for (i = 0; i < num; i++) {
+ char buf[INET_ADDRSTRLEN + 1];
+ guint32 ip;
+
+ ip = nm_setting_ip4_config_get_dns (s_ip4, i);
+
+ memset (buf, 0, sizeof (buf));
+ inet_ntop (AF_INET, (const void *) &ip, &buf[0],
+ sizeof (buf));
+ g_string_append_printf (dns, " %s", buf);
+ }
+ ifnet_set_data (conn_name, "dns_servers", dns->str);
+ g_string_free (dns, TRUE);
+ } else
+ ifnet_set_data (conn_name, "dns_servers", NULL);
+
+ /* DNS Searches */
+ num = nm_setting_ip4_config_get_num_dns_searches (s_ip4);
+ if (num > 0) {
+ searches = g_string_new (NULL);
+ for (i = 0; i < num; i++) {
+ if (i > 0)
+ g_string_append_c (searches, ' ');
+ g_string_append (searches,
+ nm_setting_ip4_config_get_dns_search
+ (s_ip4, i));
+ }
+ ifnet_set_data (conn_name, "dns_search", searches->str);
+ g_string_free (searches, TRUE);
+ } else
+ ifnet_set_data (conn_name, "dns_search", NULL);
+ /* FIXME Will be implemented when configuration supports it
+ if (!strcmp(value, NM_SETTING_IP4_CONFIG_METHOD_AUTO)) {
+ value = nm_setting_ip4_config_get_dhcp_hostname(s_ip4);
+ if (value)
+ ifnet_set_data(conn_name, "DHCP_HOSTNAME", value,
+ FALSE);
+
+ value = nm_setting_ip4_config_get_dhcp_client_id(s_ip4);
+ if (value)
+ ifnet_set_data(conn_name, "DHCP_CLIENT_ID", value,
+ FALSE);
+ }
+ */
+
+ /* Static routes */
+ num = nm_setting_ip4_config_get_num_routes (s_ip4);
+ if (num > 0) {
+ for (i = 0; i < num; i++) {
+ char buf[INET_ADDRSTRLEN + 1];
+ NMIP4Route *route;
+ guint32 ip;
+
+ route = nm_setting_ip4_config_get_route (s_ip4, i);
+
+ memset (buf, 0, sizeof (buf));
+ ip = nm_ip4_route_get_dest (route);
+ inet_ntop (AF_INET, (const void *) &ip, &buf[0],
+ sizeof (buf));
+ g_string_append_printf (routes, "\"%s", buf);
+
+ tmp =
+ g_strdup_printf ("%u",
+ nm_ip4_route_get_prefix (route));
+ g_string_append_printf (routes, "/%s via ", tmp);
+ g_free (tmp);
+
+ memset (buf, 0, sizeof (buf));
+ ip = nm_ip4_route_get_next_hop (route);
+ inet_ntop (AF_INET, (const void *) &ip, &buf[0],
+ sizeof (buf));
+ g_string_append_printf (routes, "%s\" ", buf);
+ }
+ }
+ if (routes->len > 0)
+ ifnet_set_data (conn_name, "routes", routes->str);
+ else
+ ifnet_set_data (conn_name, "routes", NULL);
+ g_string_free (routes, TRUE);
+
+ success = TRUE;
+
+ return success;
+}
+
+static gboolean
+write_route6_file (NMSettingIP6Config *s_ip6, const char *conn_name, GError **error)
+{
+ char dest[INET6_ADDRSTRLEN + 1];
+ char next_hop[INET6_ADDRSTRLEN + 1];
+ NMIP6Route *route;
+ const struct in6_addr *ip;
+ guint32 prefix;
+ guint32 i, num;
+ GString *routes_string;
+ const char *old_routes;
+
+ g_return_val_if_fail (s_ip6 != NULL, FALSE);
+ num = nm_setting_ip6_config_get_num_routes (s_ip6);
+ if (num == 0) {
+ return TRUE;
+ }
+
+ old_routes = ifnet_get_data (conn_name, "routes");
+ routes_string = g_string_new (old_routes);
+ if (old_routes)
+ g_string_append (routes_string, "\" ");
+ for (i = 0; i < num; i++) {
+ route = nm_setting_ip6_config_get_route (s_ip6, i);
+
+ memset (dest, 0, sizeof (dest));
+ ip = nm_ip6_route_get_dest (route);
+ inet_ntop (AF_INET6, (const void *) ip, &dest[0],
+ sizeof (dest));
+
+ prefix = nm_ip6_route_get_prefix (route);
+
+ memset (next_hop, 0, sizeof (next_hop));
+ ip = nm_ip6_route_get_next_hop (route);
+ inet_ntop (AF_INET6, (const void *) ip, &next_hop[0],
+ sizeof (next_hop));
+
+ g_string_append_printf (routes_string, "\"%s/%u via %s\" ",
+ dest, prefix, next_hop);
+ }
+ if (num > 0)
+ ifnet_set_data (conn_name, "routes", routes_string->str);
+ g_string_free (routes_string, TRUE);
+
+ return TRUE;
+}
+
+static gboolean
+write_ip6_setting (NMConnection *connection, const char *conn_name, GError **error)
+{
+ NMSettingIP6Config *s_ip6;
+ const char *value;
+ char *prefix;
+ guint32 i, num;
+ GString *searches;
+ char buf[INET6_ADDRSTRLEN + 1];
+ NMIP6Address *addr;
+ const struct in6_addr *ip;
+
+ s_ip6 =
+ (NMSettingIP6Config *) nm_connection_get_setting (connection,
+ NM_TYPE_SETTING_IP6_CONFIG);
+ if (!s_ip6) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Missing '%s' setting",
+ NM_SETTING_IP6_CONFIG_SETTING_NAME);
+ return FALSE;
+ }
+
+ value = nm_setting_ip6_config_get_method (s_ip6);
+ g_assert (value);
+ if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_IGNORE)) {
+ ifnet_set_data (conn_name, "enable_ipv6", "false");
+ return TRUE;
+ } else if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
+ /* nothing to do now */
+ } else {
+ // if (!strcmp(value, NM_SETTING_IP6_CONFIG_METHOD_AUTO)) {
+ const char *config = ifnet_get_data (conn_name, "config");
+ gchar *tmp;
+
+ if (!config)
+ tmp = g_strdup_printf ("dhcp6");
+ else
+ tmp = g_strdup_printf ("%s\" \"dhcp6\"", config);
+ ifnet_set_data (conn_name, "config", tmp);
+ g_free (tmp);
+ }
+ /* else if (!strcmp(value, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
+ } else if (!strcmp(value, NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL)) {
+ } else if (!strcmp(value, NM_SETTING_IP6_CONFIG_METHOD_SHARED)) {
+ } */
+
+ /* Remember to set IPv6 enabled */
+ ifnet_set_data (conn_name, "enable_ipv6", "true");
+
+ if (!strcmp (value, NM_SETTING_IP6_CONFIG_METHOD_MANUAL)) {
+ const char *config = ifnet_get_data (conn_name, "config");
+ gchar *tmp;
+ GString *ip_str;
+
+ if (!config)
+ config = "";
+ num = nm_setting_ip6_config_get_num_addresses (s_ip6);
+
+ /* IPv6 addresses */
+ ip_str = g_string_new (NULL);
+ for (i = 0; i < num; i++) {
+ addr = nm_setting_ip6_config_get_address (s_ip6, i);
+ ip = nm_ip6_address_get_address (addr);
+ prefix =
+ g_strdup_printf ("%u",
+ nm_ip6_address_get_prefix (addr));
+ memset (buf, 0, sizeof (buf));
+ inet_ntop (AF_INET6, (const void *) ip, buf,
+ sizeof (buf));
+ g_string_append_printf (ip_str, "\"%s/", buf);
+ g_string_append_printf (ip_str, "%s\" ", prefix);
+ g_free (prefix);
+ }
+ tmp = g_strdup_printf ("%s\" %s", config, ip_str->str);
+ ifnet_set_data (conn_name, "config", tmp);
+ g_free (tmp);
+ g_string_free (ip_str, TRUE);
+ }
+
+ /* DNS Servers */
+ num = nm_setting_ip6_config_get_num_dns (s_ip6);
+ if (num > 0) {
+ const char *dns_servers = ifnet_get_data (conn_name, "dns_servers");
+ gchar *tmp;
+ GString *dns_string = g_string_new (NULL);
+
+ if (!dns_servers)
+ dns_servers = "";
+ for (i = 0; i < num; i++) {
+ ip = nm_setting_ip6_config_get_dns (s_ip6, i);
+
+ memset (buf, 0, sizeof (buf));
+ inet_ntop (AF_INET6, (const void *) ip, buf,
+ sizeof (buf));
+ if (!strstr (dns_servers, buf))
+ g_string_append_printf (dns_string, "%s ", buf);
+ }
+ tmp = g_strdup_printf ("%s %s", dns_servers, dns_string->str);
+ ifnet_set_data (conn_name, "dns_servers", tmp);
+ g_free (tmp);
+ g_string_free (dns_string, TRUE);
+
+ } else
+ /* DNS Searches */
+ num = nm_setting_ip6_config_get_num_dns_searches (s_ip6);
+ if (num > 0) {
+ const char *ip4_domains;
+
+ ip4_domains = ifnet_get_data (conn_name, "dns_search");
+ if (!ip4_domains)
+ ip4_domains = "";
+ searches = g_string_new (ip4_domains);
+ for (i = 0; i < num; i++) {
+ const gchar *search = NULL;
+
+ search =
+ nm_setting_ip6_config_get_dns_search (s_ip6, i);
+ if (search && !strstr (searches->str, search)) {
+ if (searches->len > 0)
+ g_string_append_c (searches, ' ');
+ g_string_append (searches, search);
+ }
+ }
+ ifnet_set_data (conn_name, "dns_search", searches->str);
+ g_string_free (searches, TRUE);
+ }
+
+ write_route6_file (s_ip6, conn_name, error);
+ if (error && *error)
+ return FALSE;
+ return TRUE;
+}
+
+static gboolean
+write_pppoe_setting (const char *conn_name, NMSettingPPPOE * s_pppoe)
+{
+ const gchar *value;
+
+ value = nm_setting_pppoe_get_username (s_pppoe);
+ if (!value) {
+ return FALSE;
+ }
+ ifnet_set_data (conn_name, "username", (gchar *) value);
+
+ value = nm_setting_pppoe_get_password (s_pppoe);
+ /* password could be NULL here */
+ if (value) {
+ ifnet_set_data (conn_name, "password", (gchar *) value);
+ }
+ return TRUE;
+}
+
+gboolean
+ifnet_update_parsers_by_connection (NMConnection *connection,
+ const char *conn_name,
+ const char *config_file,
+ const char *wpa_file,
+ gchar **out_new_name,
+ GError **error)
+{
+ NMSettingConnection *s_con;
+ NMSettingIP6Config *s_ip6;
+ gboolean success = FALSE;
+ const char *type;
+ gboolean no_8021x = FALSE;
+ gboolean wired = FALSE, pppoe = TRUE;
+ const char *new_name = NULL;
+
+ s_con =
+ NM_SETTING_CONNECTION (nm_connection_get_setting
+ (connection, NM_TYPE_SETTING_CONNECTION));
+ if (!s_con) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Missing '%s' setting",
+ NM_SETTING_CONNECTION_SETTING_NAME);
+ return FALSE;
+ }
+
+
+ type = nm_setting_connection_get_connection_type (s_con);
+ if (!type) {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Missing connection type!");
+ goto out;
+ }
+
+ if (!strcmp (type, NM_SETTING_WIRED_SETTING_NAME)) {
+ /* Writing wired setting */
+ if (!write_wired_setting (connection, conn_name, error))
+ goto out;
+ wired = TRUE;
+ no_8021x = TRUE;
+ } else if (!strcmp (type, NM_SETTING_WIRELESS_SETTING_NAME)) {
+ /* Writing wireless setting */
+ if (!write_wireless_setting (connection, conn_name, &no_8021x, &new_name, error))
+ goto out;
+ } else if (!strcmp (type, NM_SETTING_PPPOE_SETTING_NAME)) {
+ NMSettingPPPOE *s_pppoe;
+
+ /* Writing pppoe setting */
+ s_pppoe = NM_SETTING_PPPOE (nm_connection_get_setting (connection, NM_TYPE_SETTING_PPPOE));
+ if (!write_pppoe_setting (conn_name, s_pppoe))
+ goto out;
+ pppoe = TRUE;
+ wired = TRUE;
+ no_8021x = TRUE;
+ } else {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Can't write connection type '%s'", type);
+ goto out;
+ }
+
+ /* connection name may have been updated; use it when writing out
+ * the rest of the settings.
+ */
+ if (new_name)
+ conn_name = new_name;
+
+ //FIXME wired connection doesn't support 8021x now
+ if (!no_8021x) {
+ if (!write_8021x_setting (connection, conn_name, wired, error))
+ goto out;
+ }
+
+ /* IPv4 Setting */
+ if (!write_ip4_setting (connection, conn_name, error))
+ goto out;
+
+ s_ip6 = (NMSettingIP6Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP6_CONFIG);
+ if (s_ip6) {
+ /* IPv6 Setting */
+ if (!write_ip6_setting (connection, conn_name, error))
+ goto out;
+ }
+
+ /* Connection Setting */
+ write_connection_setting (s_con, conn_name);
+
+ /* connection id will be displayed in nm-applet */
+ update_connection_id (connection, conn_name);
+
+ success = ifnet_flush_to_file (config_file);
+ if (success)
+ wpa_flush_to_file (wpa_file);
+
+ if (out_new_name)
+ *out_new_name = g_strdup (conn_name);
+
+out:
+ return success;
+}
+
+gboolean
+ifnet_delete_connection_in_parsers (const char *conn_name,
+ const char *config_file,
+ const char *wpa_file)
+{
+ gboolean result = FALSE;
+
+ ifnet_delete_network (conn_name);
+ result = ifnet_flush_to_file (config_file);
+ if (result) {
+ /* connection may not have security information
+ * so simply ignore the return value*/
+ wpa_delete_security (conn_name);
+ wpa_flush_to_file (wpa_file);
+ }
+
+ return result;
+}
+
+/* get the available wired name(eth*). */
+static gchar *
+get_wired_name ()
+{
+ int i = 0;
+
+ for (; i < 256; i++) {
+ gchar *conn_name = g_strdup_printf ("eth%d", i);
+
+ if (!ifnet_has_network (conn_name)) {
+ return conn_name;
+ } else
+ g_free (conn_name);
+ }
+ return NULL;
+}
+
+/* get the available pppoe name(ppp*). */
+static gchar *
+get_ppp_name ()
+{
+ int i = 0;
+
+ for (; i < 256; i++) {
+ gchar *conn_name = g_strdup_printf ("ppp%d", i);
+
+ if (!ifnet_has_network (conn_name)) {
+ return conn_name;
+ } else
+ g_free (conn_name);
+ }
+ return NULL;
+}
+
+/* get wireless ssid */
+static gchar *
+get_wireless_name (NMConnection * connection)
+{
+ NMSettingWireless *s_wireless;
+ const GByteArray *ssid;
+ gboolean hex_ssid = FALSE;
+ gchar *result = NULL;
+ char buf[33];
+ int i = 0;
+
+ s_wireless =
+ (NMSettingWireless *) nm_connection_get_setting (connection,
+ NM_TYPE_SETTING_WIRELESS);
+ if (!s_wireless)
+ return NULL;
+
+ ssid = nm_setting_wireless_get_ssid (s_wireless);
+ if (!ssid->len || ssid->len > 32) {
+ return NULL;
+ }
+
+ for (i = 0; i < ssid->len; i++) {
+ if (!isprint (ssid->data[i])) {
+ hex_ssid = TRUE;
+ break;
+ }
+ }
+
+ if (hex_ssid) {
+ GString *str;
+
+ str = g_string_sized_new (ssid->len * 2 + 3);
+ g_string_append (str, "0x");
+ for (i = 0; i < ssid->len; i++)
+ g_string_append_printf (str, "%02X", ssid->data[i]);
+ result = g_strdup (str->str);
+ g_string_free (str, TRUE);
+ } else {
+ memset (buf, 0, sizeof (buf));
+ memcpy (buf, ssid->data, ssid->len);
+ result = g_strdup_printf ("%s", buf);
+ g_strstrip (result);
+ }
+
+ return result;
+}
+
+char *
+ifnet_add_new_connection (NMConnection *connection,
+ const char *config_file,
+ const char *wpa_file,
+ GError **error)
+{
+ NMSettingConnection *s_con;
+ gboolean success = FALSE;
+ const char *type;
+ gchar *new_type, *new_name = NULL;
+
+ s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
+ g_assert (s_con);
+ type = nm_setting_connection_get_connection_type (s_con);
+ g_assert (type);
+
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Adding %s connection", type);
+
+ /* get name and type
+ * Wireless type: wireless
+ * Wired type: wired
+ * PPPoE type: ppp*/
+ if (!strcmp (type, NM_SETTING_WIRED_SETTING_NAME)) {
+ new_name = get_wired_name ();
+ if (!new_name)
+ goto out;
+ new_type = "wired";
+ } else if (!strcmp (type, NM_SETTING_WIRELESS_SETTING_NAME)) {
+ new_name = get_wireless_name (connection);
+ new_type = "wireless";
+ } else if (!strcmp (type, NM_SETTING_PPPOE_SETTING_NAME)) {
+ new_name = get_ppp_name ();
+ if (!new_name)
+ goto out;
+ new_type = "ppp";
+ } else {
+ g_set_error (error, ifnet_plugin_error_quark (), 0,
+ "Can't write connection type '%s'", type);
+ goto out;
+ }
+
+ if (ifnet_add_network (new_name, new_type)) {
+ success = ifnet_update_parsers_by_connection (connection,
+ new_name,
+ config_file,
+ wpa_file,
+ NULL,
+ error);
+ }
+
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Added new connection: %s, result: %s",
+ new_name, success ? "success" : "fail");
+
+out:
+ if (!success)
+ g_free (new_name);
+ return success ? new_name : NULL;
+}
diff --git a/src/settings/plugins/ifnet/connection_parser.h b/src/settings/plugins/ifnet/connection_parser.h
new file mode 100644
index 000000000..b617b6051
--- /dev/null
+++ b/src/settings/plugins/ifnet/connection_parser.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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 (C) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#ifndef _CONNECTION_PARSER_H
+#define _CONNECTION_PARSER_H
+#include <nm-connection.h>
+#include "net_parser.h"
+
+NMConnection *ifnet_update_connection_from_config_block (const char *conn_name,
+ GError **error);
+
+/* nm_conn_name is used to update nm_ifnet_connection's priv data */
+gboolean ifnet_update_parsers_by_connection (NMConnection *connection,
+ const char *conn_name,
+ const char *config_file,
+ const char *wpa_file,
+ gchar **out_new_name,
+ GError **error);
+
+gboolean ifnet_delete_connection_in_parsers (const char *conn_name,
+ const char *config_file,
+ const char *wpa_file);
+
+char * ifnet_add_new_connection (NMConnection *connection,
+ const char *config_file,
+ const char *wpa_file,
+ GError ** error);
+#endif
diff --git a/src/settings/plugins/ifnet/net_parser.c b/src/settings/plugins/ifnet/net_parser.c
new file mode 100644
index 000000000..a48103db8
--- /dev/null
+++ b/src/settings/plugins/ifnet/net_parser.c
@@ -0,0 +1,639 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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 (C) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#include <string.h>
+#include <nm-system-config-interface.h>
+#include <stdio.h>
+#include "net_parser.h"
+#include "net_utils.h"
+
+/* Save all the connection information */
+static GHashTable *conn_table;
+
+/* Save global settings which are used for writing*/
+static GHashTable *global_settings_table;
+
+/* Save functions */
+static GList *functions_list;
+
+/* Used to decide whether to write changes to file*/
+static gboolean net_parser_data_changed = FALSE;
+
+static GHashTable *
+add_new_connection_config (const gchar * type, const gchar * name)
+{
+ GHashTable *new_conn;
+ gchar *new_name;
+
+ if (!name)
+ return NULL;
+
+ /* Return existing connection */
+ if ((new_conn = g_hash_table_lookup (conn_table, name)) != NULL)
+ return new_conn;
+ new_conn = g_hash_table_new (g_str_hash, g_str_equal);
+ new_name = g_strdup (name);
+ g_hash_table_insert (new_conn, g_strdup ("name"), new_name);
+ g_hash_table_insert (new_conn, g_strdup ("type"), g_strdup (type));
+ g_hash_table_insert (conn_table, new_name, new_conn);
+ return new_conn;
+}
+
+gboolean
+ifnet_add_network (const char *name, const char *type)
+{
+ if (ifnet_has_network (name))
+ return TRUE;
+ if (add_new_connection_config (type, name)) {
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Adding network for %s", name);
+ net_parser_data_changed = TRUE;
+ return TRUE;
+ }
+ return FALSE;
+}
+
+gboolean
+ifnet_has_network (const char *conn_name)
+{
+ return g_hash_table_lookup (conn_table, conn_name) != NULL;
+}
+
+static GHashTable *
+get_connection_config (const char *name)
+{
+ return g_hash_table_lookup (conn_table, name);
+}
+
+/* Ignored name won't be treated as wireless ssid */
+static gchar *ignore_name[] = {
+ "vlan", "bond", "atm", "ath", "ippp", "vpn", "tap", "tun", "1",
+ "br", "nas", "6to4", "timeout", "kvm", "force", NULL
+};
+
+static gboolean
+ignore_connection_name (const char *name)
+{
+ gboolean result = FALSE;
+ guint i = 0;
+
+ /* check ignore_name list */
+ while (ignore_name[i] != NULL) {
+ if (g_ascii_strncasecmp
+ (name, ignore_name[i], strlen (ignore_name[i])) == 0) {
+ return TRUE;
+ }
+ i++;
+ }
+ /* Ignore mac address based configuration */
+ if (strlen (name) == 12 && is_hex (name))
+ result = TRUE;
+ return result;
+
+}
+
+static gboolean
+is_global_setting (char *key)
+{
+ static gchar *global_settings[] = { "wpa_supplicant_", NULL };
+ int i;
+
+ for (i = 0; global_settings[i] != NULL; i++) {
+ if (strstr (key, global_settings[i]))
+ return 1;
+ }
+ return 0;
+}
+
+/* Parse a complete line */
+/* Connection type is determined here */
+static void
+init_block_by_line (gchar * buf)
+{
+ gchar **key_value;
+ gchar *pos;
+ gchar *data;
+ gchar *tmp;
+ GHashTable *conn;
+
+ key_value = g_strsplit (buf, "=", 2);
+ if (g_strv_length (key_value) != 2) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME, "Can't handle this line: %s\n",
+ buf);
+ g_strfreev (key_value);
+ return;
+ }
+ pos = g_strrstr (key_value[0], "_");
+ if (pos == NULL || is_global_setting (key_value[0])) {
+ /* global data */
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "global:%s-%s\n", key_value[0],
+ key_value[1]);
+ g_hash_table_insert (global_settings_table,
+ g_strdup (key_value[0]),
+ g_strdup (key_value[1]));
+ g_strfreev (key_value);
+ return;
+ }
+ *pos++ = '\0';
+ if ((conn = get_connection_config (pos)) == NULL) {
+ if (g_ascii_strncasecmp (pos, "eth", 3) == 0
+ && strlen (pos) == 4)
+ /* wired connection */
+ conn = add_new_connection_config ("wired", pos);
+ else if (g_ascii_strncasecmp (pos, "ppp", 3) == 0
+ && strlen (pos) == 4)
+ /* pppoe connection */
+ conn = add_new_connection_config ("ppp", pos);
+ else if (ignore_connection_name (pos)) {
+ /* ignored connection */
+ conn = add_new_connection_config ("ignore", pos);
+ } else
+ /* wireless connection */
+ conn = add_new_connection_config ("wireless", pos);
+ }
+ data = g_strdup (key_value[1]);
+ tmp = strip_string (data, '(');
+ tmp = strip_string (tmp, ')');
+ strip_string (tmp, '"');
+ strip_string (tmp, '\'');
+ if (conn)
+ g_hash_table_insert (conn, g_strdup (key_value[0]),
+ g_strdup (tmp));
+ g_free (data);
+ g_strfreev (key_value);
+}
+
+static void
+destroy_connection_config (GHashTable * conn)
+{
+ gpointer key, value;
+ GHashTableIter iter;
+
+ g_hash_table_iter_init (&iter, conn);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ g_free (key);
+ g_free (value);
+ }
+
+ g_hash_table_destroy (conn);
+}
+
+// read settings from /etc/NetworkManager/nm-system-settings.conf
+const char *
+ifnet_get_global_setting (const char *group, const char *key)
+{
+ GError *error = NULL;
+ GKeyFile *keyfile = g_key_file_new ();
+ gchar *result = NULL;
+
+ if (!g_key_file_load_from_file (keyfile,
+ IFNET_SYSTEM_SETTINGS_KEY_FILE,
+ G_KEY_FILE_NONE, &error)) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "loading system config file (%s) caused error: (%d) %s",
+ IFNET_SYSTEM_SETTINGS_KEY_FILE,
+ error ? error->code : -1, error
+ && error->message ? error->message : "(unknown)");
+ } else {
+ result = g_key_file_get_string (keyfile, group, key, &error);
+ }
+ g_key_file_free (keyfile);
+ return result;
+}
+
+static void
+strip_function (GIOChannel * channel, gchar * line)
+{
+
+ int counter = 0;
+ gchar *p, *tmp;
+ gboolean begin = FALSE;
+ GString *function_str = g_string_new (line);
+
+ g_string_append (function_str, "\n");
+ while (1) {
+ p = line;
+ while (*p != '\0') {
+ if (*p == '{') {
+ counter++;
+ begin = TRUE;
+ } else if (*p == '}')
+ counter--;
+ p++;
+ }
+ if (begin && counter == 0) {
+ g_free (line);
+ goto done;
+ }
+ while (1) {
+ g_free (line);
+ if (g_io_channel_read_line
+ (channel, &line, NULL, NULL,
+ NULL) == G_IO_STATUS_EOF)
+ goto done;
+ g_string_append (function_str, line);
+ tmp = g_strdup (line);
+ g_strstrip (tmp);
+ if (tmp[0] != '#' && tmp[0] != '\0') {
+ g_free (tmp);
+ break;
+ } else
+ g_free (tmp);
+ }
+ }
+done:
+ functions_list =
+ g_list_append (functions_list, g_strdup (function_str->str));
+ g_string_free (function_str, TRUE);
+}
+
+static gboolean
+is_function (gchar * line)
+{
+ static gchar *func_names[] =
+ { "preup", "predown", "postup", "postdown", "failup", "faildown",
+ NULL,
+ };
+ int i;
+
+ for (i = 0; func_names[i]; i++) {
+ if (g_str_has_prefix (line, func_names[i])) {
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+ "Ignoring function: %s", func_names[i]);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+gboolean
+ifnet_init (gchar * config_file)
+{
+ GIOChannel *channel = NULL;
+ gchar *line;
+
+ /* Handle multiple lines with brackets */
+ gboolean complete = TRUE;
+
+ /* line buffer */
+ GString *buf;
+
+ net_parser_data_changed = FALSE;
+
+ conn_table = g_hash_table_new (g_str_hash, g_str_equal);
+ global_settings_table = g_hash_table_new (g_str_hash, g_str_equal);
+ functions_list = NULL;
+
+ if (g_file_test (config_file, G_FILE_TEST_IS_REGULAR))
+ channel = g_io_channel_new_file (config_file, "r", NULL);
+ if (channel == NULL) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "Error: Can't open %s\n", config_file);
+ return FALSE;
+ }
+
+ buf = g_string_new (NULL);
+ while (g_io_channel_read_line
+ (channel, &line, NULL, NULL, NULL) != G_IO_STATUS_EOF) {
+ g_strstrip (line);
+ /* convert multiple lines to a complete line and
+ * pass it to init_block_by_line() */
+ if (is_function (line)) {
+ strip_function (channel, line);
+ continue;
+ }
+ if (line[0] != '#' && line[0] != '\0') {
+ gchar *pos = NULL;
+
+ if (!complete) {
+ complete =
+ g_strrstr (line,
+ ")") == NULL ? FALSE : TRUE;
+ if ((pos = strchr (line, '#')) != NULL)
+ *pos = '\0';
+ g_strstrip (line);
+ if (line[0] != '\0') {
+ g_string_append_printf (buf,
+ " %s", line);
+ }
+ g_free (line);
+ if (!complete)
+ continue;
+ } else {
+ complete =
+ (g_strrstr (line, "(") != NULL
+ && g_strrstr (line, ")") != NULL)
+ || g_strrstr (line, "(") == NULL;
+ if ((pos = strchr (line, '#')) != NULL)
+ *pos = '\0';
+ g_strstrip (line);
+ if (line[0] != '\0')
+ g_string_append (buf, line);
+ g_free (line);
+ if (!complete)
+ continue;
+ }
+ init_block_by_line (buf->str);
+ g_string_free (buf, TRUE);
+ buf = g_string_new (NULL);
+ } else
+ /* Blank line or comment line */
+ g_free (line);
+ }
+
+ g_string_free (buf, TRUE);
+ g_io_channel_shutdown (channel, FALSE, NULL);
+ g_io_channel_unref (channel);
+ return TRUE;
+}
+
+const char *
+ifnet_get_data (const char *conn_name, const char *key)
+{
+ GHashTable *conn = g_hash_table_lookup (conn_table, conn_name);
+
+ if (conn)
+ return g_hash_table_lookup (conn, key);
+ return NULL;
+}
+
+void
+ifnet_set_data (const char *conn_name, const char *key, const char *value)
+{
+ gpointer old_key = NULL, old_value = NULL;
+ GHashTable *conn = g_hash_table_lookup (conn_table, conn_name);
+ gchar * stripped = NULL;
+
+ if (!conn) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME, "%s does not exsit!", conn_name);
+ return;
+ }
+ if (value){
+ stripped = g_strdup (value);
+ strip_string (stripped, '"');
+ }
+ /* Remove existing key value pair */
+ if (g_hash_table_lookup_extended (conn, key, &old_key, &old_value)) {
+ if (stripped && !strcmp(old_value, stripped)){
+ g_free (stripped);
+ return;
+ }
+ g_hash_table_remove (conn, old_key);
+ g_free (old_key);
+ g_free (old_value);
+ } else if (!value)
+ return;
+ if (stripped)
+ g_hash_table_insert (conn, g_strdup (key), stripped);
+ net_parser_data_changed = TRUE;
+}
+
+// Remember to free return value
+const char *
+ifnet_get_global_data (const gchar * key)
+{
+ return g_hash_table_lookup (global_settings_table, key);
+}
+
+// Return names of legal connections
+GList *
+ifnet_get_connection_names (void)
+{
+ GList *names = g_hash_table_get_keys (conn_table);
+ GList *result = NULL;
+
+ while (names) {
+ if (!ignore_connection_name (names->data))
+ result = g_list_prepend (result, names->data);
+ names = names->next;
+ }
+ g_list_free (names);
+ return g_list_reverse (result);
+}
+
+/* format IP and route for writing */
+static void
+format_ips (gchar * value, gchar ** out_line, gchar * key, gchar * name)
+{
+ gchar **ipset;
+ guint length, i;
+ GString *formated_string = g_string_new (NULL);
+
+ strip_string (value, '"');
+ ipset = g_strsplit (value, "\" \"", 0);
+ length = g_strv_length (ipset);
+
+ //only one line
+ if (length < 2) {
+ *out_line =
+ g_strdup_printf ("%s_%s=( \"%s\" )\n", key, name, value);
+ goto done;
+ }
+ // Multiple lines
+ g_string_append_printf (formated_string, "%s_%s=(\n", key, name);
+ for (i = 0; i < length; i++)
+ g_string_append_printf (formated_string,
+ "\t\"%s\"\n", ipset[i]);
+ g_string_append (formated_string, ")\n");
+ *out_line = g_strdup (formated_string->str);
+done:
+ g_string_free (formated_string, TRUE);
+ g_strfreev (ipset);
+}
+
+gboolean
+ifnet_flush_to_file (const char *config_file)
+{
+ GIOChannel *channel;
+ GError **error = NULL;
+ gpointer key, value, name, network;
+ GHashTableIter iter, iter_network;
+ GList *list_iter;
+ gchar *out_line;
+ gsize bytes_written;
+ gboolean result = FALSE;
+
+ if (!net_parser_data_changed)
+ return TRUE;
+ if (!conn_table || !global_settings_table)
+ return FALSE;
+
+ channel = g_io_channel_new_file (config_file, "w", NULL);
+ if (!channel) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "Can't open file %s for writing", config_file);
+ return FALSE;
+ }
+ g_hash_table_iter_init (&iter, global_settings_table);
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Writing to %s", config_file);
+ g_io_channel_write_chars (channel,
+ "#Generated by NetworkManager\n"
+ "###### Global Configuration ######\n",
+ -1, &bytes_written, error);
+ /* Writing global data */
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ out_line =
+ g_strdup_printf ("%s=%s\n", (gchar *) key, (gchar *) value);
+ g_io_channel_write_chars (channel, out_line, -1,
+ &bytes_written, error);
+ if (bytes_written == 0 || (error && *error))
+ break;
+ g_free (out_line);
+ }
+ if (error && *error) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "Found error: %s", (*error)->message);
+ goto done;
+ }
+
+ /* Writing connection data */
+ g_io_channel_write_chars (channel,
+ "\n###### Connection Configuration ######\n",
+ -1, &bytes_written, error);
+ g_hash_table_iter_init (&iter, conn_table);
+ while (g_hash_table_iter_next (&iter, &name, &network)) {
+ g_hash_table_iter_init (&iter_network, (GHashTable *) network);
+ g_io_channel_write_chars (channel,
+ "#----------------------------------\n",
+ -1, &bytes_written, error);
+
+ while (g_hash_table_iter_next (&iter_network, &key, &value)) {
+ if (!g_str_has_prefix ((gchar *) key, "name")
+ && !g_str_has_prefix ((gchar *) key, "type")) {
+ /* These keys contain brackets */
+ if (strcmp
+ ((gchar *) key,
+ "config") == 0
+ || strcmp ((gchar *) key,
+ "routes") == 0
+ || strcmp ((gchar *) key,
+ "pppd") == 0
+ || strcmp ((gchar *) key, "chat") == 0)
+ format_ips (value, &out_line, (gchar *)
+ key, (gchar *)
+ name);
+ else
+ out_line =
+ g_strdup_printf
+ ("%s_%s=\"%s\"\n",
+ (gchar *) key,
+ (gchar *) name, (gchar *) value);
+ g_io_channel_write_chars
+ (channel, out_line, -1,
+ &bytes_written, error);
+ if (bytes_written == 0 || (error && *error))
+ break;
+ g_free (out_line);
+ }
+ }
+ }
+ if (error && *error) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "Found error: %s", (*error)->message);
+ goto done;
+ }
+
+ /* Writing reserved functions */
+ if (functions_list) {
+ g_io_channel_write_chars (channel,
+ "\n###### Reserved Functions ######\n",
+ -1, &bytes_written, error);
+ /* Writing functions */
+ for (list_iter = functions_list; list_iter;
+ list_iter = g_list_next (list_iter)) {
+ out_line =
+ g_strdup_printf ("%s\n", (gchar *) list_iter->data);
+ g_io_channel_write_chars (channel, out_line, -1,
+ &bytes_written, error);
+ if (bytes_written == 0 || (error && *error))
+ break;
+ g_free (out_line);
+ }
+ if (error && *error) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "Found error: %s", (*error)->message);
+ goto done;
+ }
+ }
+
+ g_io_channel_flush (channel, error);
+ if (error && *error) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "Found error: %s", (*error)->message);
+ goto done;
+ }
+ result = TRUE;
+ net_parser_data_changed = FALSE;
+done:
+ g_io_channel_shutdown (channel, FALSE, NULL);
+ g_io_channel_unref (channel);
+ return result;
+}
+
+gboolean
+ifnet_delete_network (const char *conn_name)
+{
+ GHashTable *network = NULL;
+
+ g_return_val_if_fail (conn_table != NULL && conn_name != NULL, FALSE);
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Deleting network for %s", conn_name);
+ network = g_hash_table_lookup (conn_table, conn_name);
+ if (!network)
+ return FALSE;
+ g_hash_table_remove (conn_table, conn_name);
+ destroy_connection_config (network);
+ net_parser_data_changed = TRUE;
+ return TRUE;
+}
+
+void
+ifnet_destroy (void)
+{
+ GHashTableIter iter;
+ gpointer key;
+ gpointer value;
+ GList *list_iter;
+
+ /* Destroy connection setting */
+ if (conn_table) {
+ g_hash_table_iter_init (&iter, conn_table);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ destroy_connection_config ((GHashTable *)
+ value);
+ }
+ g_hash_table_destroy (conn_table);
+ conn_table = NULL;
+ }
+
+ /* Destroy global data */
+ if (global_settings_table) {
+ g_hash_table_iter_init (&iter, global_settings_table);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ g_free (key);
+ g_free (value);
+ }
+ g_hash_table_destroy (global_settings_table);
+ global_settings_table = NULL;
+ }
+ for (list_iter = functions_list; list_iter;
+ list_iter = g_list_next (list_iter))
+ g_free (list_iter->data);
+ g_list_free (functions_list);
+}
diff --git a/src/settings/plugins/ifnet/net_parser.h b/src/settings/plugins/ifnet/net_parser.h
new file mode 100644
index 000000000..0411e939e
--- /dev/null
+++ b/src/settings/plugins/ifnet/net_parser.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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 (C) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#ifndef _NET_PARSER_H
+#define _NET_PARSER_H
+
+#include <glib.h>
+
+#define CONF_NET_FILE "/etc/conf.d/net"
+#define IFNET_SYSTEM_SETTINGS_KEY_FILE "/etc/NetworkManager/nm-system-settings.conf"
+#define IFNET_KEY_FILE_GROUP "ifnet"
+
+gboolean ifnet_init (gchar * config_file);
+void ifnet_destroy (void);
+
+/* Reader functions */
+GList *ifnet_get_connection_names (void);
+const char *ifnet_get_data (const char *conn_name, const char *key);
+const char *ifnet_get_global_data (const char *key);
+const char *ifnet_get_global_setting (const char *group, const char *key);
+gboolean ifnet_has_network (const char *conn_name);
+
+/* Writer functions */
+gboolean ifnet_flush_to_file (const char *config_file);
+void ifnet_set_data (const char *conn_name, const char *key, const char *value);
+gboolean ifnet_add_network (const char *name, const char *type);
+gboolean ifnet_delete_network (const char *conn_name);
+#endif
diff --git a/src/settings/plugins/ifnet/net_utils.c b/src/settings/plugins/ifnet/net_utils.c
new file mode 100644
index 000000000..83f86ab50
--- /dev/null
+++ b/src/settings/plugins/ifnet/net_utils.c
@@ -0,0 +1,974 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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 (C) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <nm-utils.h>
+#include <nm-system-config-interface.h>
+#include "net_utils.h"
+#include "wpa_parser.h"
+#include "net_parser.h"
+
+/* emit heading and tailing blank space, tab, character t */
+gchar *
+strip_string (gchar * str, gchar t)
+{
+ gchar *ret = str;
+ gint length = 0;
+ guint i = 0;
+
+ while (ret[i] != '\0'
+ && (ret[i] == '\t' || ret[i] == ' ' || ret[i] == t)) {
+ length++;
+ i++;
+ }
+ i = 0;
+ while (ret[i + length] != '\0') {
+ ret[i] = ret[i + length];
+ i++;
+ }
+ ret[i] = '\0';
+ length = strlen (ret);
+ while ((length - 1) >= 0
+ && (ret[length - 1] == ' ' || ret[length - 1] == '\n'
+ || ret[length - 1] == '\t' || ret[length - 1] == t))
+ length--;
+ ret[length] = '\0';
+ return ret;
+}
+
+gboolean
+is_hex (const char *value)
+{
+ const char *p = value;
+
+ if (!p)
+ return FALSE;
+ while (*p) {
+ if (!isxdigit (*p++))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+gboolean
+is_ascii (const char *value)
+{
+ const char *p = value;
+
+ while (*p) {
+ if (!isascii (*p++))
+ return FALSE;
+ }
+ return TRUE;
+
+}
+
+gboolean
+is_true (const char *str)
+{
+ if (!g_ascii_strcasecmp (str, "yes")
+ || !g_ascii_strcasecmp (str, "true"))
+ return TRUE;
+ return FALSE;
+}
+
+static int
+hex2num (char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ return -1;
+}
+
+static int
+hex2byte (const char *hex)
+{
+ int a, b;
+
+ a = hex2num (*hex++);
+ if (a < 0)
+ return -1;
+ b = hex2num (*hex++);
+ if (b < 0)
+ return -1;
+ return (a << 4) | b;
+}
+
+/* free return value by caller */
+gchar *
+utils_hexstr2bin (const gchar * hex, size_t len)
+{
+ size_t i;
+ int a;
+ const gchar *ipos = hex;
+ gchar *buf = NULL;
+ gchar *opos;
+
+ /* Length must be a multiple of 2 */
+ if ((len % 2) != 0)
+ return NULL;
+
+ opos = buf = g_malloc0 ((len / 2) + 1);
+ for (i = 0; i < len; i += 2) {
+ a = hex2byte (ipos);
+ if (a < 0) {
+ g_free (buf);
+ return NULL;
+ }
+ *opos++ = a;
+ ipos += 2;
+ }
+ return buf;
+}
+
+/* free return value by caller */
+gchar *
+utils_bin2hexstr (const gchar * bytes, int len, int final_len)
+{
+ static gchar hex_digits[] = "0123456789abcdef";
+ gchar *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;
+}
+
+GQuark
+ifnet_plugin_error_quark (void)
+{
+ static GQuark error_quark = 0;
+
+ if (G_UNLIKELY (error_quark == 0))
+ error_quark =
+ g_quark_from_static_string ("ifnet-plugin-error-quark");
+ return error_quark;
+}
+
+static char *
+find_default_gateway_str (char *str)
+{
+ char *tmp;
+
+ if ((tmp = strstr (str, "default via ")) != NULL) {
+ return tmp + strlen ("default via ");
+ } else if ((tmp = strstr (str, "default gw ")) != NULL) {
+ return tmp + strlen ("default gw ");
+ }
+ return NULL;
+}
+
+static char *
+find_gateway_str (char *str)
+{
+ char *tmp;
+
+ if ((tmp = strstr (str, "via ")) != NULL) {
+ return tmp + strlen ("via ");
+ } else if ((tmp = strstr (str, "gw ")) != NULL) {
+ return tmp + strlen ("gw ");
+ }
+ return NULL;
+}
+
+gboolean
+reload_parsers (void)
+{
+ ifnet_destroy ();
+ wpa_parser_destroy ();
+ if (!ifnet_init (CONF_NET_FILE))
+ return FALSE;
+ wpa_parser_init (WPA_SUPPLICANT_CONF);
+ return TRUE;
+}
+
+gchar *
+read_hostname (const char *path)
+{
+ gchar *contents = NULL, *result = NULL, *tmp;
+ gchar **all_lines = NULL;
+ guint line_num, i;
+
+ if (!g_file_get_contents (path, &contents, NULL, NULL))
+ return NULL;
+ all_lines = g_strsplit (contents, "\n", 0);
+ line_num = g_strv_length (all_lines);
+ for (i = 0; i < line_num; i++) {
+ g_strstrip (all_lines[i]);
+ if (all_lines[i][0] == '#' || all_lines[i][0] == '\0')
+ continue;
+ if (g_str_has_prefix (all_lines[i], "hostname")) {
+ tmp = strstr (all_lines[i], "=");
+ tmp++;
+ tmp = strip_string (tmp, '"');
+ result = g_strdup (tmp);
+ break;
+ }
+
+ }
+ g_strfreev (all_lines);
+ g_free (contents);
+ return result;
+}
+
+gboolean
+write_hostname (const gchar *hostname, const char *path)
+{
+ gboolean result;
+ char *contents;
+
+ contents = g_strdup_printf ("#Generated by NetworkManager\n"
+ "hostname=\"%s\"\n", hostname);
+ result = g_file_set_contents (path, contents, -1, NULL);
+ g_free (contents);
+ return result;
+}
+
+gboolean
+is_static_ip4 (const char *conn_name)
+{
+ const char *data = ifnet_get_data (conn_name, "config");
+ const char *dhcp6;
+
+ if (!data)
+ return FALSE;
+ if (!strcmp (data, "shared"))
+ return FALSE;
+ if (!strcmp (data, "autoip"))
+ return FALSE;
+ dhcp6 = strstr (data, "dhcp6");
+ if (dhcp6) {
+ gchar *dhcp4;
+
+ if (strstr (data, "dhcp "))
+ return FALSE;
+ dhcp4 = strstr (data, "dhcp");
+ if (!dhcp4)
+ return TRUE;
+ if (dhcp4[4] == '\0')
+ return FALSE;
+ return TRUE;
+ }
+ return strstr (data, "dhcp") == NULL ? TRUE : FALSE;
+}
+
+gboolean
+is_static_ip6 (const char *conn_name)
+{
+ const char *data = ifnet_get_data (conn_name, "config");
+
+ if (!data)
+ return TRUE;
+ return strstr (data, "dhcp6") == NULL ? TRUE : FALSE;
+}
+
+gboolean
+is_ip4_address (const char *in_address)
+{
+ const char *pattern =
+ "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.((\\{\\d{1,3}\\.\\.\\d{1,3}\\})|\\d{1,3})$";
+ gchar *address = g_strdup (in_address);
+ gboolean result = FALSE;
+ gchar *tmp;
+ GRegex *regex = g_regex_new (pattern, 0, 0, NULL);
+ GMatchInfo *match_info;
+
+ if (!address)
+ goto done;
+ g_strstrip (address);
+ if ((tmp = strstr (address, "/")) != NULL)
+ *tmp = '\0';
+ if ((tmp = strstr (address, " ")) != NULL)
+ *tmp = '\0';
+ g_regex_match (regex, address, 0, &match_info);
+ result = g_match_info_matches (match_info);
+done:
+ if (match_info)
+ g_match_info_free (match_info);
+ g_regex_unref (regex);
+ g_free (address);
+ return result;
+}
+
+gboolean
+is_ip6_address (const char *in_address)
+{
+ struct in6_addr tmp_ip6_addr;
+ gchar *tmp, *address;
+ gboolean result = FALSE;
+
+ if (!in_address)
+ return FALSE;
+ address = g_strdup (in_address);
+ g_strstrip (address);
+ if ((tmp = strchr (address, '/')) != NULL)
+ *tmp = '\0';
+ if (inet_pton (AF_INET6, address, &tmp_ip6_addr))
+ result = TRUE;
+ g_free (address);
+ return result;
+
+}
+
+gboolean
+has_ip6_address (const char *conn_name)
+{
+ gchar **ipset;
+ guint length;
+ guint i;
+
+ g_return_val_if_fail (conn_name != NULL, FALSE);
+ ipset = g_strsplit (ifnet_get_data (conn_name, "config"), "\" \"", 0);
+ length = g_strv_length (ipset);
+ for (i = 0; i < length; i++) {
+ if (!is_ip6_address (ipset[i]))
+ continue;
+ else {
+ g_strfreev (ipset);
+ return TRUE;
+ }
+
+ }
+ g_strfreev (ipset);
+ return FALSE;
+}
+
+gboolean
+has_default_route (const char *conn_name, gboolean (*check_fn) (const char *))
+{
+ char *routes = NULL, *end, *tmp;
+ gboolean success = FALSE;
+
+ g_return_val_if_fail (conn_name != NULL, FALSE);
+
+ routes = g_strdup (ifnet_get_data (conn_name, "routes"));
+ if (!routes)
+ return FALSE;
+ tmp = find_default_gateway_str (routes);
+ if (tmp) {
+ g_strstrip (tmp);
+ if ((end = strstr (tmp, "\"")) != NULL)
+ *end = '\0';
+ if (check_fn (tmp))
+ success = TRUE;
+ }
+
+ g_free (routes);
+ return success;
+}
+
+static ip_block *
+create_ip4_block (gchar * ip)
+{
+ ip_block *iblock = g_slice_new0 (ip_block);
+ struct in_addr tmp_ip4_addr;
+ int i;
+ guint length;
+ gchar **ip_mask;
+
+ /* prefix format */
+ if (strstr (ip, "/")) {
+ gchar *prefix;
+
+ ip_mask = g_strsplit (ip, "/", 0);
+ length = g_strv_length (ip_mask);
+ if (!inet_pton (AF_INET, ip_mask[0], &tmp_ip4_addr))
+ goto error;
+ iblock->ip = tmp_ip4_addr.s_addr;
+ prefix = ip_mask[1];
+ i = 0;
+ while (i < length && isdigit (prefix[i]))
+ i++;
+ prefix[i] = '\0';
+ iblock->netmask = nm_utils_ip4_prefix_to_netmask ((guint32)
+ atoi (ip_mask
+ [1]));
+ } else if (strstr (ip, "netmask")) {
+ ip_mask = g_strsplit (ip, " ", 0);
+ length = g_strv_length (ip_mask);
+ if (!inet_pton (AF_INET, ip_mask[0], &tmp_ip4_addr))
+ goto error;
+ iblock->ip = tmp_ip4_addr.s_addr;
+ i = 0;
+ while (i < length && !strstr (ip_mask[++i], "netmask")) ;
+ while (i < length && ip_mask[++i][0] == '\0') ;
+ if (i >= length)
+ goto error;
+ if (!inet_pton (AF_INET, ip_mask[i], &tmp_ip4_addr))
+ goto error;
+ iblock->netmask = tmp_ip4_addr.s_addr;
+ } else {
+ g_slice_free (ip_block, iblock);
+ if (!is_ip6_address (ip) && !strstr (ip, "dhcp"))
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "Can't handle ipv4 address: %s, missing netmask or prefix",
+ ip);
+ return NULL;
+ }
+ g_strfreev (ip_mask);
+ return iblock;
+error:
+ if (!is_ip6_address (ip))
+ PLUGIN_WARN (IFNET_PLUGIN_NAME, "Can't handle IPv4 address: %s",
+ ip);
+ g_strfreev (ip_mask);
+ g_slice_free (ip_block, iblock);
+ return NULL;
+}
+
+static ip6_block *
+create_ip6_block (gchar * ip)
+{
+ ip6_block *iblock = g_slice_new0 (ip6_block);
+ gchar *dup_ip = g_strdup (ip);
+ struct in6_addr *tmp_ip6_addr = g_slice_new0 (struct in6_addr);
+ gchar *prefix = NULL;
+
+ if ((prefix = strstr (dup_ip, "/")) != NULL) {
+ *prefix = '\0';
+ prefix++;
+ }
+ if (!inet_pton (AF_INET6, dup_ip, tmp_ip6_addr)) {
+ goto error;
+ }
+ iblock->ip = tmp_ip6_addr;
+ if (prefix) {
+ errno = 0;
+ iblock->prefix = strtol (prefix, NULL, 10);
+ if (errno || iblock->prefix <= 0 || iblock->prefix > 128) {
+ goto error;
+ }
+ } else
+ iblock->prefix = 64;
+ g_free (dup_ip);
+ return iblock;
+error:
+ if (!is_ip4_address (ip))
+ PLUGIN_WARN (IFNET_PLUGIN_NAME, "Can't handle IPv6 address: %s",
+ ip);
+ g_slice_free (ip6_block, iblock);
+ g_slice_free (struct in6_addr, tmp_ip6_addr);
+
+ g_free (dup_ip);
+ return NULL;
+}
+
+static guint32
+get_ip4_gateway (gchar * gateway)
+{
+ gchar *tmp, *split;
+ struct in_addr tmp_ip4_addr;
+
+ if (!gateway)
+ return 0;
+ tmp = find_gateway_str (gateway);
+ if (!tmp) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "Couldn't obtain gateway in \"%s\"", gateway);
+ return 0;
+ }
+ tmp = g_strdup (tmp);
+ strip_string (tmp, ' ');
+ strip_string (tmp, '"');
+ if ((split = strstr (tmp, "\"")) != NULL)
+ *split = '\0';
+ if (!inet_pton (AF_INET, tmp, &tmp_ip4_addr))
+ goto error;
+ g_free (tmp);
+ return tmp_ip4_addr.s_addr;
+error:
+ if (!is_ip6_address (tmp))
+ PLUGIN_WARN (IFNET_PLUGIN_NAME, "Can't handle IPv4 gateway: %s",
+ tmp);
+ g_free (tmp);
+ return 0;
+}
+
+static struct in6_addr *
+get_ip6_next_hop (gchar * next_hop)
+{
+ gchar *tmp;
+ struct in6_addr *tmp_ip6_addr = g_slice_new0 (struct in6_addr);
+
+ if (!next_hop)
+ return 0;
+ tmp = find_gateway_str (next_hop);
+ if (!tmp) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "Couldn't obtain next_hop in \"%s\"", next_hop);
+ return 0;
+ }
+ tmp = g_strdup (tmp);
+ strip_string (tmp, ' ');
+ strip_string (tmp, '"');
+ g_strstrip (tmp);
+ if (!inet_pton (AF_INET6, tmp, tmp_ip6_addr))
+ goto error;
+ g_free (tmp);
+ return tmp_ip6_addr;
+error:
+ if (!is_ip4_address (tmp))
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "Can't handle IPv6 next_hop: %s", tmp);
+ g_free (tmp);
+ g_slice_free (struct in6_addr, tmp_ip6_addr);
+
+ return NULL;
+}
+
+ip_block *
+convert_ip4_config_block (const char *conn_name)
+{
+ gchar **ipset;
+ guint length;
+ guint i;
+ gchar *ip;
+ guint32 def_gateway = 0;
+ const char *routes;
+ gchar *pos;
+ ip_block *start = NULL, *current = NULL, *iblock = NULL;
+ const char *pattern =
+ "((\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.)\\{(\\d{1,3})\\.\\.(\\d{1,3})\\}(/\\d{1,2}))";
+
+ g_return_val_if_fail (conn_name != NULL, NULL);
+
+ ipset = g_strsplit (ifnet_get_data (conn_name, "config"), "\" \"", 0);
+ length = g_strv_length (ipset);
+
+ routes = ifnet_get_data (conn_name, "routes");
+ if (routes)
+ def_gateway = get_ip4_gateway (strstr (routes, "default"));
+
+ for (i = 0; i < length; i++) {
+ ip = ipset[i];
+ ip = strip_string (ip, '"');
+ //Handle ip like 192.168.4.{1..3}
+ if ((pos = strchr (ip, '{')) != NULL) {
+ gchar *ip_start, *ip_prefix;
+ gchar *begin_str, *end_str;
+ int begin, end, j;
+ GRegex *regex;
+ GMatchInfo *match_info;
+
+ regex = g_regex_new (pattern, 0, 0, NULL);
+ g_regex_match (regex, ip, 0, &match_info);
+ g_regex_unref (regex);
+
+ if (!g_match_info_matches (match_info)) {
+ g_match_info_free (match_info);
+ continue;
+ }
+ begin_str = g_match_info_fetch (match_info, 3);
+ end_str = g_match_info_fetch (match_info, 4);
+ begin = atoi (begin_str);
+ end = atoi (end_str);
+ ip_start = g_match_info_fetch (match_info, 2);
+ ip_prefix = g_match_info_fetch (match_info, 5);
+ if (end < begin || begin < 1 || end > 254) {
+ g_match_info_free (match_info);
+ continue;
+ }
+
+ for (j = begin; j <= end; j++) {
+ char suf[4];
+ gchar *newip;
+
+ sprintf (suf, "%d", j);
+ newip =
+ g_strconcat (ip_start, suf, ip_prefix,
+ NULL);
+ iblock = create_ip4_block (newip);
+ if (iblock == NULL) {
+ g_free (newip);
+ continue;
+ }
+ if (!iblock->gateway && def_gateway != 0)
+ iblock->gateway = def_gateway;
+ if (start == NULL)
+ start = current = iblock;
+ else {
+ current->next = iblock;
+ current = iblock;
+ }
+ g_free (newip);
+ }
+ g_free (begin_str);
+ g_free (end_str);
+ g_free (ip_start);
+ g_free (ip_prefix);
+ g_match_info_free (match_info);
+ } else {
+ iblock = create_ip4_block (ip);
+ if (iblock == NULL)
+ continue;
+ if (!iblock->gateway && def_gateway != 0)
+ iblock->gateway = def_gateway;
+ if (start == NULL)
+ start = current = iblock;
+ else {
+ current->next = iblock;
+ current = iblock;
+ }
+ }
+ }
+ g_strfreev (ipset);
+ return start;
+}
+
+ip6_block *
+convert_ip6_config_block (const char *conn_name)
+{
+ gchar **ipset;
+ guint length;
+ guint i;
+ gchar *ip;
+ ip6_block *start = NULL, *current = NULL, *iblock = NULL;
+
+ g_return_val_if_fail (conn_name != NULL, NULL);
+ ipset = g_strsplit (ifnet_get_data (conn_name, "config"), "\" \"", 0);
+ length = g_strv_length (ipset);
+ for (i = 0; i < length; i++) {
+ ip = ipset[i];
+ ip = strip_string (ip, '"');
+ iblock = create_ip6_block (ip);
+ if (iblock == NULL)
+ continue;
+ if (start == NULL)
+ start = current = iblock;
+ else {
+ current->next = iblock;
+ current = iblock;
+ }
+ }
+ g_strfreev (ipset);
+ return start;
+}
+
+ip_block *
+convert_ip4_routes_block (const char *conn_name)
+{
+ gchar **ipset;
+ guint length;
+ guint i;
+ gchar *ip;
+ const char *routes;
+ ip_block *start = NULL, *current = NULL, *iblock = NULL;
+
+ g_return_val_if_fail (conn_name != NULL, NULL);
+
+ routes = ifnet_get_data (conn_name, "routes");
+ if (!routes)
+ return NULL;
+ ipset = g_strsplit (routes, "\" \"", 0);
+ length = g_strv_length (ipset);
+ for (i = 0; i < length; i++) {
+ ip = ipset[i];
+ if (find_default_gateway_str (ip) || strstr (ip, "::")
+ || !find_gateway_str (ip))
+ continue;
+ ip = strip_string (ip, '"');
+ iblock = create_ip4_block (ip);
+ if (iblock == NULL)
+ continue;
+ iblock->gateway = get_ip4_gateway (ip);
+ if (start == NULL)
+ start = current = iblock;
+ else {
+ current->next = iblock;
+ current = iblock;
+ }
+ }
+ g_strfreev (ipset);
+ return start;
+}
+
+ip6_block *
+convert_ip6_routes_block (const char *conn_name)
+{
+ gchar **ipset;
+ guint length;
+ guint i;
+ gchar *ip, *tmp_addr;
+ const char *routes;
+ ip6_block *start = NULL, *current = NULL, *iblock = NULL;
+ struct in6_addr *tmp_ip6_addr;
+
+ g_return_val_if_fail (conn_name != NULL, NULL);
+ routes = ifnet_get_data (conn_name, "routes");
+ if (!routes)
+ return NULL;
+ ipset = g_strsplit (routes, "\" \"", 0);
+ length = g_strv_length (ipset);
+ for (i = 0; i < length; i++) {
+ ip = ipset[i];
+ ip = strip_string (ip, '"');
+ if (ip[0] == '\0')
+ continue;
+ if ((tmp_addr = find_default_gateway_str (ip)) != NULL) {
+ if (!is_ip6_address (tmp_addr))
+ continue;
+ else {
+ tmp_ip6_addr = g_slice_new0 (struct in6_addr);
+
+ if (inet_pton (AF_INET6, "::", tmp_ip6_addr)) {
+ iblock = g_slice_new0 (ip6_block);
+ iblock->ip = tmp_ip6_addr;
+ iblock->prefix = 128;
+ } else {
+ g_slice_free (struct in6_addr,
+ tmp_ip6_addr);
+ continue;
+ }
+ }
+ } else
+ iblock = create_ip6_block (ip);
+ if (iblock == NULL)
+ continue;
+ iblock->next_hop = get_ip6_next_hop (ip);
+ if (iblock->next_hop == NULL) {
+ destroy_ip6_block (iblock);
+ continue;
+ }
+ if (start == NULL)
+ start = current = iblock;
+ else {
+ current->next = iblock;
+ current = iblock;
+ }
+ }
+ g_strfreev (ipset);
+ return start;
+}
+
+void
+destroy_ip_block (ip_block * iblock)
+{
+ g_slice_free (ip_block, iblock);
+}
+
+void
+destroy_ip6_block (ip6_block * iblock)
+{
+ g_slice_free (struct in6_addr, iblock->ip);
+ g_slice_free (struct in6_addr, iblock->next_hop);
+
+ g_slice_free (ip6_block, iblock);
+}
+
+void
+set_ip4_dns_servers (NMSettingIP4Config *s_ip4, const char *conn_name)
+{
+ const char *dns_servers;
+ gchar **server_list, *stripped;
+ guint length, i;
+ struct in_addr tmp_ip4_addr;
+ guint32 new_dns;
+
+ dns_servers = ifnet_get_data (conn_name, "dns_servers");
+ if (!dns_servers)
+ return;
+ stripped = g_strdup (dns_servers);
+ strip_string (stripped, '"');
+ server_list = g_strsplit (stripped, " ", 0);
+ g_free (stripped);
+
+ length = g_strv_length (server_list);
+ if (length)
+ g_object_set (s_ip4, NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS,
+ TRUE, NULL);
+ for (i = 0; i < length; i++) {
+ g_strstrip (server_list[i]);
+ if (server_list[i][0] == '\0')
+ continue;
+ if (!inet_pton (AF_INET, server_list[i], &tmp_ip4_addr)) {
+ if (!is_ip6_address (server_list[i]))
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "ignored dns: %s\n",
+ server_list[i]);
+ continue;
+ }
+ new_dns = tmp_ip4_addr.s_addr;
+ if (new_dns && !nm_setting_ip4_config_add_dns (s_ip4, new_dns))
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "warning: duplicate DNS server %s",
+ server_list[i]);
+ }
+ g_strfreev (server_list);
+}
+
+void
+set_ip6_dns_servers (NMSettingIP6Config *s_ip6, const char *conn_name)
+{
+ const char *dns_servers;
+ gchar **server_list, *stripped;
+ guint length, i;
+ struct in6_addr tmp_ip6_addr;
+
+ dns_servers = ifnet_get_data (conn_name, "dns_servers");
+ if (!dns_servers)
+ return;
+
+ stripped = g_strdup (dns_servers);
+ strip_string (stripped, '"');
+ server_list = g_strsplit (stripped, " ", 0);
+ g_free (stripped);
+
+ length = g_strv_length (server_list);
+ if (length)
+ g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS,
+ TRUE, NULL);
+ for (i = 0; i < length; i++) {
+ g_strstrip (server_list[i]);
+ if (server_list[i][0] == '\0')
+ continue;
+ if (!inet_pton (AF_INET6, server_list[i], &tmp_ip6_addr)) {
+ if (is_ip6_address (server_list[i]))
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "ignored dns: %s\n",
+ server_list[i]);
+ continue;
+ }
+ if (!IN6_IS_ADDR_UNSPECIFIED (&tmp_ip6_addr)
+ && !nm_setting_ip6_config_add_dns (s_ip6, &tmp_ip6_addr))
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "warning: duplicate DNS server %s",
+ server_list[i]);
+ }
+ g_strfreev (server_list);
+}
+
+gboolean
+is_managed (const char *conn_name)
+{
+ gchar *config;
+
+ g_return_val_if_fail (conn_name != NULL, FALSE);
+ config = (gchar *) ifnet_get_data (conn_name, "managed");
+ if (!config)
+ return TRUE;
+ if (strcmp (config, "false") == 0)
+ return FALSE;
+ return TRUE;
+}
+
+void
+get_dhcp_hostname_and_client_id (char **hostname, char **client_id)
+{
+ const char *dhcp_client;
+ const gchar *dhcpcd_conf = "/etc/dhcpcd.conf";
+ const gchar *dhclient_conf = "/etc/dhcp/dhclient.conf";
+ gchar *line = NULL, *tmp = NULL, *contents = NULL;
+ gchar **all_lines;
+ guint line_num, i;
+
+ *hostname = NULL;
+ *client_id = NULL;
+ dhcp_client = ifnet_get_global_setting ("main", "dhcp");
+ if (dhcp_client) {
+ if (!strcmp (dhcp_client, "dhclient"))
+ g_file_get_contents (dhclient_conf, &contents, NULL,
+ NULL);
+ else if (!strcmp (dhcp_client, "dhcpcd"))
+ g_file_get_contents (dhcpcd_conf, &contents, NULL,
+ NULL);
+ } else {
+ if (g_file_test (dhclient_conf, G_FILE_TEST_IS_REGULAR))
+ g_file_get_contents (dhclient_conf, &contents, NULL,
+ NULL);
+ else if (g_file_test (dhcpcd_conf, G_FILE_TEST_IS_REGULAR))
+ g_file_get_contents (dhcpcd_conf, &contents, NULL,
+ NULL);
+ }
+ if (!contents)
+ return;
+ all_lines = g_strsplit (contents, "\n", 0);
+ line_num = g_strv_length (all_lines);
+ for (i = 0; i < line_num; i++) {
+ line = all_lines[i];
+ // dhcpcd.conf
+ g_strstrip (line);
+ if (g_str_has_prefix (line, "hostname")) {
+ tmp = line + strlen ("hostname");
+ g_strstrip (tmp);
+ if (tmp[0] != '\0')
+ *hostname = g_strdup (tmp);
+ else
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+ "dhcpcd hostname not defined, ignoring");
+ } else if (g_str_has_prefix (line, "clientid")) {
+ tmp = line + strlen ("clientid");
+ g_strstrip (tmp);
+ if (tmp[0] != '\0')
+ *client_id = g_strdup (tmp);
+ else
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+ "dhcpcd clientid not defined, ignoring");
+ }
+ // dhclient.conf
+ else if ((tmp = strstr (line, "send host-name")) != NULL) {
+ tmp += strlen ("send host-name");
+ g_strstrip (tmp);
+ strip_string (tmp, ';');
+ strip_string (tmp, '"');
+ if (tmp[0] != '\0')
+ *hostname = g_strdup (tmp);
+ else
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+ "dhclient hostname not defined, ignoring");
+ } else if ((tmp = strstr (line, "send dhcp-client-identifier"))
+ != NULL) {
+ tmp += strlen ("send dhcp-client-identifier");
+ g_strstrip (tmp);
+ strip_string (tmp, ';');
+ if (tmp[0] != '\0')
+ *client_id = g_strdup (tmp);
+ else
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+ "dhclient clientid not defined, ignoring");
+ }
+ }
+ g_strfreev (all_lines);
+ g_free (contents);
+}
diff --git a/src/settings/plugins/ifnet/net_utils.h b/src/settings/plugins/ifnet/net_utils.h
new file mode 100644
index 000000000..42f8d6725
--- /dev/null
+++ b/src/settings/plugins/ifnet/net_utils.h
@@ -0,0 +1,80 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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 (C) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#ifndef _IFNET_UTILS_H
+#define _IFNET_UTILS_H
+#define IFNET_PLUGIN_NAME "SCPlugin-Ifnet"
+#include <glib.h>
+#include <arpa/inet.h>
+#include <nm-setting-ip6-config.h>
+#include <nm-setting-ip4-config.h>
+#include "net_parser.h"
+#define has_default_ip4_route(conn_name) has_default_route((conn_name), &is_ip4_address)
+#define has_default_ip6_route(conn_name) has_default_route((conn_name), &is_ip6_address)
+
+typedef struct _ip_block {
+ guint32 ip;
+ guint32 netmask;
+ guint32 gateway;
+ struct _ip_block *next;
+} ip_block;
+
+typedef struct _ip6_block {
+ struct in6_addr *ip;
+ long int prefix;
+ struct in6_addr *next_hop;
+ struct _ip6_block *next;
+} ip6_block;
+
+gchar *read_hostname (const char *path);
+gboolean write_hostname (const char *hostname, const char *path);
+gboolean is_static_ip4 (const char *conn_name);
+gboolean is_static_ip6 (const char *conn_name);
+gboolean is_ip4_address (const char *in_address);
+gboolean is_ip6_address (const char *in_address);
+gboolean has_ip6_address (const char *conn_name);
+gboolean has_default_route (const char *conn_name, gboolean (*check_fn) (const char *));
+gboolean reload_parsers (void);
+
+ip_block *convert_ip4_config_block (const char *conn_name);
+ip6_block *convert_ip6_config_block (const char *conn_name);
+ip_block *convert_ip4_routes_block (const char *conn_name);
+ip6_block *convert_ip6_routes_block (const char *conn_name);
+void destroy_ip_block (ip_block * iblock);
+void destroy_ip6_block (ip6_block * iblock);
+
+void set_ip4_dns_servers (NMSettingIP4Config * s_ip4, const char *conn_name);
+void set_ip6_dns_servers (NMSettingIP6Config * s_ip6, const char *conn_name);
+
+gchar *strip_string (gchar *str, gchar t);
+gboolean is_managed (const char *conn_name);
+
+GQuark ifnet_plugin_error_quark (void);
+gchar *utils_hexstr2bin (const gchar * hex, size_t len);
+gchar *utils_bin2hexstr (const gchar * bytes, int len, int final_len);
+
+gboolean is_hex (const char *value);
+gboolean is_ascii (const char *value);
+gboolean is_true (const char *str);
+
+void get_dhcp_hostname_and_client_id (char **hostname, char **client_id);
+
+#endif
diff --git a/src/settings/plugins/ifnet/nm-ifnet-connection.c b/src/settings/plugins/ifnet/nm-ifnet-connection.c
new file mode 100644
index 000000000..8b7a153cc
--- /dev/null
+++ b/src/settings/plugins/ifnet/nm-ifnet-connection.c
@@ -0,0 +1,191 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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 (C) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#include <string.h>
+#include <glib/gstdio.h>
+#include <NetworkManager.h>
+#include <nm-utils.h>
+#include <nm-setting-wireless-security.h>
+#include <nm-settings-connection.h>
+#include <nm-system-config-interface.h>
+#include <nm-settings-error.h>
+#include "nm-ifnet-connection.h"
+#include "connection_parser.h"
+#include "net_parser.h"
+#include "net_utils.h"
+#include "wpa_parser.h"
+#include "plugin.h"
+
+G_DEFINE_TYPE (NMIfnetConnection, nm_ifnet_connection, NM_TYPE_SETTINGS_CONNECTION)
+
+#define NM_IFNET_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_IFNET_CONNECTION, NMIfnetConnectionPrivate))
+enum {
+ PROP_ZERO,
+ PROP_CONN_NAME,
+ _PROP_END,
+};
+
+enum {
+ IFNET_SETUP_MONITORS,
+ IFNET_CANCEL_MONITORS,
+ IFNET_LAST_SIGNAL
+};
+
+static guint signals[IFNET_LAST_SIGNAL] = { 0 };
+
+typedef struct {
+ gchar *conn_name;
+ NMSystemConfigInterface *config;
+} NMIfnetConnectionPrivate;
+
+NMIfnetConnection *
+nm_ifnet_connection_new (const char *conn_name, NMConnection *source)
+{
+ NMConnection *tmp;
+ GObject *object;
+ GError *error = NULL;
+
+ g_return_val_if_fail (conn_name != NULL, NULL);
+
+ if (source)
+ tmp = g_object_ref (source);
+ else {
+ tmp = ifnet_update_connection_from_config_block (conn_name, &error);
+ if (!tmp){
+ g_error_free (error);
+ return NULL;
+ }
+ }
+
+ object = (GObject *) g_object_new (NM_TYPE_IFNET_CONNECTION, NULL);
+ if (!object) {
+ g_object_unref (tmp);
+ return NULL;
+ }
+
+ NM_IFNET_CONNECTION_GET_PRIVATE (object)->conn_name = g_strdup (conn_name);
+ nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (object), tmp, NULL);
+ g_object_unref (tmp);
+
+ return NM_IFNET_CONNECTION (object);
+}
+
+static void
+nm_ifnet_connection_init (NMIfnetConnection * connection)
+{
+}
+
+static void
+commit_changes (NMSettingsConnection *connection,
+ NMSettingsConnectionCommitFunc callback,
+ gpointer user_data)
+{
+ GError *error = NULL;
+ NMIfnetConnectionPrivate *priv = NM_IFNET_CONNECTION_GET_PRIVATE (connection);
+ gchar *new_name = NULL;
+
+ g_signal_emit (connection, signals[IFNET_CANCEL_MONITORS], 0);
+ if (!ifnet_update_parsers_by_connection (NM_CONNECTION (connection),
+ priv->conn_name,
+ CONF_NET_FILE,
+ WPA_SUPPLICANT_CONF,
+ &new_name,
+ &error)) {
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Failed to update %s", priv->conn_name);
+ reload_parsers ();
+ callback (connection, error, user_data);
+ g_error_free (error);
+ g_signal_emit (connection, signals[IFNET_SETUP_MONITORS], 0);
+ return;
+ }
+
+ g_free (priv->conn_name);
+ priv->conn_name = new_name;
+
+ NM_SETTINGS_CONNECTION_CLASS (nm_ifnet_connection_parent_class)->commit_changes (connection, callback, user_data);
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Successfully updated %s", priv->conn_name);
+
+ g_signal_emit (connection, signals[IFNET_SETUP_MONITORS], 0);
+}
+
+static void
+do_delete (NMSettingsConnection *connection,
+ NMSettingsConnectionDeleteFunc callback,
+ gpointer user_data)
+{
+ GError *error = NULL;
+ NMIfnetConnectionPrivate *priv = NM_IFNET_CONNECTION_GET_PRIVATE (connection);
+
+ g_signal_emit (connection, signals[IFNET_CANCEL_MONITORS], 0);
+ if (!ifnet_delete_connection_in_parsers
+ (priv->conn_name, CONF_NET_FILE, WPA_SUPPLICANT_CONF)) {
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Failed to delete %s",
+ priv->conn_name);
+ reload_parsers ();
+ callback (connection, error, user_data);
+ g_error_free (error);
+ g_signal_emit (connection, signals[IFNET_SETUP_MONITORS], 0);
+ return;
+ }
+
+ NM_SETTINGS_CONNECTION_CLASS (nm_ifnet_connection_parent_class)->delete (connection, callback, user_data);
+
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Successfully deleted %s",
+ priv->conn_name);
+ g_signal_emit (connection, signals[IFNET_SETUP_MONITORS], 0);
+}
+
+static void
+finalize (GObject * object)
+{
+ NMIfnetConnectionPrivate *priv =
+ NM_IFNET_CONNECTION_GET_PRIVATE (object);
+ g_return_if_fail (priv);
+
+ g_free (priv->conn_name);
+ G_OBJECT_CLASS (nm_ifnet_connection_parent_class)->finalize (object);
+}
+
+static void
+nm_ifnet_connection_class_init (NMIfnetConnectionClass * ifnet_connection_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (ifnet_connection_class);
+ NMSettingsConnectionClass *settings_class = NM_SETTINGS_CONNECTION_CLASS (ifnet_connection_class);
+
+ g_type_class_add_private (ifnet_connection_class,
+ sizeof (NMIfnetConnectionPrivate));
+
+ object_class->finalize = finalize;
+ settings_class->delete = do_delete;
+ settings_class->commit_changes = commit_changes;
+
+ signals[IFNET_SETUP_MONITORS] =
+ g_signal_new ("ifnet_setup_monitors",
+ G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ signals[IFNET_CANCEL_MONITORS] =
+ g_signal_new ("ifnet_cancel_monitors",
+ G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+}
diff --git a/src/settings/plugins/ifnet/nm-ifnet-connection.h b/src/settings/plugins/ifnet/nm-ifnet-connection.h
new file mode 100644
index 000000000..9423f20d7
--- /dev/null
+++ b/src/settings/plugins/ifnet/nm-ifnet-connection.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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 (C) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#ifndef NM_IFNET_CONNECTION_H
+#define NM_IFNET_CONNECTION_H
+
+#include <nm-settings-connection.h>
+#include "net_parser.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_IFNET_CONNECTION (nm_ifnet_connection_get_type ())
+#define NM_IFNET_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IFNET_CONNECTION, NMIfnetConnection))
+#define NM_IFNET_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_IFNET_CONNECTION, NMIfnetConnectionClass))
+#define NM_IS_IFNET_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_IFNET_CONNECTION))
+#define NM_IS_IFNET_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_IFNET_CONNECTION))
+#define NM_IFNET_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_IFNET_CONNECTION, NMIfnetConnectionClass))
+
+typedef struct {
+ NMSettingsConnection parent;
+} NMIfnetConnection;
+
+typedef struct {
+ NMSettingsConnectionClass parent;
+} NMIfnetConnectionClass;
+
+GType nm_ifnet_connection_get_type (void);
+
+NMIfnetConnection *nm_ifnet_connection_new (const char *conn_name,
+ NMConnection *source);
+
+G_END_DECLS
+#endif /* NM_IFNET_CONNECTION_H */
diff --git a/src/settings/plugins/ifnet/plugin.c b/src/settings/plugins/ifnet/plugin.c
new file mode 100644
index 000000000..69b7bc803
--- /dev/null
+++ b/src/settings/plugins/ifnet/plugin.c
@@ -0,0 +1,541 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service (ifnet)
+ *
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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 (C) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#include <string.h>
+
+#include <gmodule.h>
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <nm-utils.h>
+#include <nm-setting-connection.h>
+
+#include "NetworkManager.h"
+#include "nm-system-config-interface.h"
+#include "nm-ifnet-connection.h"
+
+#include "plugin.h"
+#include "net_utils.h"
+#include "net_parser.h"
+#include "wpa_parser.h"
+#include "connection_parser.h"
+
+#define IFNET_PLUGIN_NAME_PRINT "ifnet"
+#define IFNET_PLUGIN_INFO "(C) 1999-2010 Gentoo Foundation, Inc. To report bugs please use bugs.gentoo.org with [networkmanager] or [qiaomuf] prefix."
+#define IFNET_SYSTEM_HOSTNAME_FILE "/etc/conf.d/hostname"
+#define IFNET_MANAGE_WELL_KNOWN_DEFAULT TRUE
+#define IFNET_KEY_FILE_KEY_MANAGED "managed"
+
+typedef struct {
+ GHashTable *config_connections;
+ gchar *hostname;
+ gboolean unmanaged_well_known;
+
+ GFileMonitor *hostname_monitor;
+ GFileMonitor *net_monitor;
+ GFileMonitor *wpa_monitor;
+
+} SCPluginIfnetPrivate;
+
+typedef void (*FileChangedFn) (gpointer user_data);
+
+typedef struct {
+ FileChangedFn callback;
+ gpointer user_data;
+} FileMonitorInfo;
+
+static void system_config_interface_init (NMSystemConfigInterface *class);
+
+static void reload_connections (gpointer config);
+
+G_DEFINE_TYPE_EXTENDED (SCPluginIfnet, sc_plugin_ifnet, G_TYPE_OBJECT, 0,
+ G_IMPLEMENT_INTERFACE (NM_TYPE_SYSTEM_CONFIG_INTERFACE, system_config_interface_init))
+#define SC_PLUGIN_IFNET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SC_TYPE_PLUGIN_IFNET, SCPluginIfnetPrivate))
+/*
+static void
+ignore_cb(NMSettingsConnectionInterface * connection,
+ GError * error, gpointer user_data)
+{
+}
+*/
+static const char *
+get_hostname (NMSystemConfigInterface * config)
+{
+ return SC_PLUGIN_IFNET_GET_PRIVATE (config)->hostname;
+}
+
+static void
+update_system_hostname (gpointer config)
+{
+ SCPluginIfnetPrivate *priv = SC_PLUGIN_IFNET_GET_PRIVATE (config);
+
+ if (priv->hostname)
+ g_free (priv->hostname);
+ priv->hostname = read_hostname (IFNET_SYSTEM_HOSTNAME_FILE);
+
+ g_object_notify (G_OBJECT (config),
+ NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME);
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Hostname updated to: %s",
+ priv->hostname);
+}
+
+static void
+write_system_hostname (NMSystemConfigInterface * config,
+ const gchar * newhostname)
+{
+ SCPluginIfnetPrivate *priv = SC_PLUGIN_IFNET_GET_PRIVATE (config);
+
+ g_return_if_fail (newhostname);
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Write system hostname: %s",
+ newhostname);
+ if (write_hostname (newhostname, IFNET_SYSTEM_HOSTNAME_FILE)) {
+ g_free (priv->hostname);
+ priv->hostname = g_strdup (newhostname);
+ g_object_notify (G_OBJECT (config),
+ NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME);
+ } else
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "Write system hostname: %s failed", newhostname);
+}
+
+static gboolean
+is_managed_plugin ()
+{
+ const char *result = NULL;
+
+ result = ifnet_get_global_setting (IFNET_KEY_FILE_GROUP, IFNET_KEY_FILE_KEY_MANAGED);
+ if (result)
+ return is_true (result);
+ return IFNET_MANAGE_WELL_KNOWN_DEFAULT;
+}
+
+static void
+file_changed (GFileMonitor * monitor,
+ GFile * file,
+ GFile * other_file,
+ GFileMonitorEvent event_type, gpointer user_data)
+{
+ FileMonitorInfo *info;
+
+ switch (event_type) {
+ case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
+ info = (FileMonitorInfo *) user_data;
+ info->callback (info->user_data);
+ break;
+ default:
+ break;
+ }
+}
+
+static GFileMonitor *
+monitor_file_changes (const char *filename,
+ FileChangedFn callback, gpointer user_data)
+{
+ GFile *file;
+ GFileMonitor *monitor;
+ FileMonitorInfo *info;
+ GError **error = NULL;
+
+ if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR))
+ return NULL;
+ file = g_file_new_for_path (filename);
+ monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, error);
+ g_object_unref (file);
+
+ if (monitor) {
+ info = g_new0 (FileMonitorInfo, 1);
+ info->callback = callback;
+ info->user_data = user_data;
+ g_object_weak_ref (G_OBJECT (monitor), (GWeakNotify) g_free,
+ info);
+ g_signal_connect (monitor, "changed", G_CALLBACK (file_changed),
+ info);
+ } else
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "Monitoring %s failed, error: %s", filename,
+ error == NULL ? "nothing" : (*error)->message);
+
+ return monitor;
+}
+
+/* Callback for nm_settings_connection_replace_and_commit. Report any errors
+ * encountered when commiting connection settings updates. */
+static void
+commit_cb (NMSettingsConnection *connection, GError *error, gpointer unused)
+{
+ if (error) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME, " error updating: %s",
+ (error && error->message) ? error->message : "(unknown)");
+ } else {
+ NMSettingConnection *s_con;
+
+ s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (connection),
+ NM_TYPE_SETTING_CONNECTION);
+ g_assert (s_con);
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Connection %s updated",
+ nm_setting_connection_get_id (s_con));
+ }
+}
+
+static void
+setup_monitors (NMIfnetConnection * connection, gpointer user_data)
+{
+ SCPluginIfnet *self = SC_PLUGIN_IFNET (user_data);
+ SCPluginIfnetPrivate *priv = SC_PLUGIN_IFNET_GET_PRIVATE (self);
+
+ priv->hostname_monitor =
+ monitor_file_changes (IFNET_SYSTEM_HOSTNAME_FILE,
+ update_system_hostname, user_data);
+ priv->net_monitor =
+ monitor_file_changes (CONF_NET_FILE, reload_connections, user_data);
+ priv->wpa_monitor =
+ monitor_file_changes (WPA_SUPPLICANT_CONF, reload_connections,
+ user_data);
+}
+
+static void
+cancel_monitors (NMIfnetConnection * connection, gpointer user_data)
+{
+ SCPluginIfnet *self = SC_PLUGIN_IFNET (user_data);
+ SCPluginIfnetPrivate *priv = SC_PLUGIN_IFNET_GET_PRIVATE (self);
+
+ if (priv->hostname_monitor) {
+ g_file_monitor_cancel (priv->hostname_monitor);
+ g_object_unref (priv->hostname_monitor);
+ }
+ if (priv->net_monitor) {
+ g_file_monitor_cancel (priv->net_monitor);
+ g_object_unref (priv->net_monitor);
+ }
+ if (priv->wpa_monitor) {
+ g_file_monitor_cancel (priv->wpa_monitor);
+ g_object_unref (priv->wpa_monitor);
+ }
+}
+
+static void
+reload_connections (gpointer config)
+{
+ SCPluginIfnet *self = SC_PLUGIN_IFNET (config);
+ SCPluginIfnetPrivate *priv = SC_PLUGIN_IFNET_GET_PRIVATE (self);
+ GList *conn_names = NULL, *n_iter = NULL;
+
+ /* save names for removing unused connections */
+ GHashTable *new_conn_names = NULL;
+ GHashTableIter iter;
+ gpointer key;
+ gpointer value;
+
+ if (priv->unmanaged_well_known)
+ return;
+
+ if (!reload_parsers ())
+ return;
+
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Loading connections");
+
+ conn_names = ifnet_get_connection_names ();
+ new_conn_names = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
+ for (n_iter = conn_names; n_iter; n_iter = g_list_next (n_iter)) {
+ NMIfnetConnection *new;
+ NMIfnetConnection *old;
+ const char *conn_name = n_iter->data;
+
+ /* read the new connection */
+ new = nm_ifnet_connection_new (conn_name, NULL);
+ if (!new)
+ continue;
+
+ g_signal_connect (G_OBJECT (new), "ifnet_setup_monitors",
+ G_CALLBACK (setup_monitors), config);
+ g_signal_connect (G_OBJECT (new), "ifnet_cancel_monitors",
+ G_CALLBACK (cancel_monitors), config);
+
+ old = g_hash_table_lookup (priv->config_connections, conn_name);
+ if (old && new) {
+ const char *auto_refresh;
+
+ auto_refresh = ifnet_get_global_setting (IFNET_KEY_FILE_GROUP, "auto_refresh");
+ if (auto_refresh && is_true (auto_refresh)) {
+ if (!nm_connection_compare (NM_CONNECTION (old),
+ NM_CONNECTION (new),
+ NM_SETTING_COMPARE_FLAG_EXACT)) {
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Auto refreshing %s", conn_name);
+
+ /* Remove and re-add to disconnect and reconnect with new settings */
+ nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (old));
+ g_hash_table_remove (priv->config_connections, conn_name);
+ g_hash_table_insert (priv->config_connections, g_strdup (conn_name), new);
+ if (is_managed_plugin () && is_managed (conn_name))
+ g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, new);
+ }
+ } else {
+ /* Update existing connection with new settings */
+ nm_settings_connection_replace_and_commit (NM_SETTINGS_CONNECTION (old),
+ NM_CONNECTION (new),
+ commit_cb, NULL);
+ g_object_unref (new);
+ }
+ g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED);
+ } else if (new) {
+ g_hash_table_insert (priv->config_connections, g_strdup (conn_name), new);
+ if (is_managed_plugin () && is_managed (conn_name))
+ g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, new);
+ }
+ g_hash_table_insert (new_conn_names, (gpointer) conn_name, (gpointer) conn_name);
+ }
+
+ /* remove unused connections */
+ g_hash_table_iter_init (&iter, priv->config_connections);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ if (!g_hash_table_lookup (new_conn_names, key)) {
+ nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (value));
+ g_hash_table_remove (priv->config_connections, key);
+ }
+ }
+ g_hash_table_destroy (new_conn_names);
+ g_list_free (conn_names);
+}
+
+static NMSettingsConnection *
+add_connection (NMSystemConfigInterface *config,
+ NMConnection *source,
+ GError **error)
+{
+ NMIfnetConnection *connection = NULL;
+ char *conn_name;
+
+ conn_name = ifnet_add_new_connection (source, CONF_NET_FILE, WPA_SUPPLICANT_CONF, error);
+ if (conn_name)
+ connection = nm_ifnet_connection_new (conn_name, source);
+ reload_connections (config);
+ return connection ? NM_SETTINGS_CONNECTION (connection) : NULL;
+}
+
+static void
+check_unmanaged (gpointer key, gpointer data, gpointer user_data)
+{
+ GSList **list = (GSList **) user_data;
+ gchar *conn_name = (gchar *) key;
+ const char *unmanaged_spec;
+ GSList *iter;
+
+ if (is_managed (conn_name))
+ return;
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Checking unmanaged: %s", conn_name);
+ unmanaged_spec = ifnet_get_data (conn_name, "mac");
+ if (!unmanaged_spec)
+ return;
+
+ /* Just return if the unmanaged spec is already in the list */
+ for (iter = *list; iter; iter = g_slist_next (iter)) {
+ if (!strcmp ((char *) iter->data, unmanaged_spec))
+ return;
+ }
+
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Add unmanaged: %s", unmanaged_spec);
+ *list =
+ g_slist_prepend (*list, g_strdup_printf ("mac:%s", unmanaged_spec));
+}
+
+static GSList *
+get_unmanaged_specs (NMSystemConfigInterface * config)
+{
+ SCPluginIfnetPrivate *priv = SC_PLUGIN_IFNET_GET_PRIVATE (config);
+ GSList *list = NULL;
+
+ g_return_val_if_fail (priv->config_connections != NULL, NULL);
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "getting unmanaged specs...");
+ g_hash_table_foreach (priv->config_connections, check_unmanaged, &list);
+ return list;
+}
+
+static void
+SCPluginIfnet_init (NMSystemConfigInterface * config)
+{
+ SCPluginIfnet *self = SC_PLUGIN_IFNET (config);
+ SCPluginIfnetPrivate *priv = SC_PLUGIN_IFNET_GET_PRIVATE (self);
+
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Initializing!");
+ if (!priv->config_connections)
+ priv->config_connections =
+ g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
+ g_object_unref);
+ priv->unmanaged_well_known = !is_managed_plugin ();
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "management mode: %s",
+ priv->unmanaged_well_known ? "unmanaged" : "managed");
+ // GFileMonitor setup
+ setup_monitors (NULL, config);
+ reload_connections (config);
+ /* Read hostname */
+ update_system_hostname (self);
+
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Initialzation complete!");
+}
+
+static GSList *
+get_connections (NMSystemConfigInterface * config)
+{
+ SCPluginIfnetPrivate *priv = SC_PLUGIN_IFNET_GET_PRIVATE (config);
+ GSList *connections = NULL;
+ GHashTableIter iter;
+ gpointer key, value;
+
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "(%d) ... get_connections.",
+ GPOINTER_TO_UINT (config));
+ if (priv->unmanaged_well_known) {
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME,
+ "(%d) ... get_connections (managed=false): return empty list.",
+ GPOINTER_TO_UINT (config));
+ return NULL;
+ }
+
+ g_hash_table_iter_init (&iter, priv->config_connections);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ if (is_managed ((gchar *) key))
+ connections = g_slist_prepend (connections, value);
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "(%d) connections count: %d",
+ GPOINTER_TO_UINT (config), g_slist_length (connections));
+ return connections;
+}
+
+static void
+system_config_interface_init (NMSystemConfigInterface *class)
+{
+ class->init = SCPluginIfnet_init;
+ class->get_connections = get_connections;
+ class->get_unmanaged_specs = get_unmanaged_specs;
+ class->add_connection = add_connection;
+}
+
+static void
+sc_plugin_ifnet_init (SCPluginIfnet * plugin)
+{
+}
+
+static void
+get_property (GObject * object, guint prop_id, GValue * value,
+ GParamSpec * pspec)
+{
+ NMSystemConfigInterface *self = NM_SYSTEM_CONFIG_INTERFACE (object);
+
+ switch (prop_id) {
+ case NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME:
+ g_value_set_string (value, IFNET_PLUGIN_NAME_PRINT);
+ break;
+ case NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO:
+ g_value_set_string (value, IFNET_PLUGIN_INFO);
+ break;
+ case NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES:
+ g_value_set_uint (value,
+ NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS
+ |
+ NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME);
+ break;
+ case NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME:
+ g_value_set_string (value, get_hostname (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+set_property (GObject * object, guint prop_id, const GValue * value,
+ GParamSpec * pspec)
+{
+ switch (prop_id) {
+ case NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME:{
+ const gchar *hostname = g_value_get_string (value);
+
+ if (hostname && strlen (hostname) < 1)
+ hostname = NULL;
+ write_system_hostname (NM_SYSTEM_CONFIG_INTERFACE
+ (object), hostname);
+ break;
+ }
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+dispose (GObject * object)
+{
+ SCPluginIfnet *plugin = SC_PLUGIN_IFNET (object);
+ SCPluginIfnetPrivate *priv = SC_PLUGIN_IFNET_GET_PRIVATE (plugin);
+
+ cancel_monitors (NULL, object);
+ if (priv->config_connections) {
+ g_hash_table_remove_all (priv->config_connections);
+ g_hash_table_destroy (priv->config_connections);
+ }
+
+ g_free (priv->hostname);
+ ifnet_destroy ();
+ wpa_parser_destroy ();
+ G_OBJECT_CLASS (sc_plugin_ifnet_parent_class)->dispose (object);
+}
+
+static void
+sc_plugin_ifnet_class_init (SCPluginIfnetClass * req_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (req_class);
+
+ g_type_class_add_private (req_class, sizeof (SCPluginIfnetPrivate));
+
+ object_class->dispose = dispose;
+ object_class->get_property = get_property;
+ object_class->set_property = set_property;
+
+ g_object_class_override_property (object_class,
+ NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME,
+ NM_SYSTEM_CONFIG_INTERFACE_NAME);
+
+ g_object_class_override_property (object_class,
+ NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO,
+ NM_SYSTEM_CONFIG_INTERFACE_INFO);
+
+ g_object_class_override_property (object_class,
+ NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES,
+ NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES);
+
+ g_object_class_override_property (object_class,
+ NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME,
+ NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME);
+}
+
+G_MODULE_EXPORT GObject *
+nm_system_config_factory (void)
+{
+ static SCPluginIfnet *singleton = NULL;
+
+ if (!singleton)
+ singleton
+ =
+ SC_PLUGIN_IFNET (g_object_new (SC_TYPE_PLUGIN_IFNET, NULL));
+ else
+ g_object_ref (singleton);
+ return G_OBJECT (singleton);
+}
diff --git a/src/settings/plugins/ifnet/plugin.h b/src/settings/plugins/ifnet/plugin.h
new file mode 100644
index 000000000..83099b63a
--- /dev/null
+++ b/src/settings/plugins/ifnet/plugin.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service (ifnet)
+ *
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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 (C) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#ifndef _PLUGIN_H_
+#define _PLUGIN_H_
+
+#include <glib-object.h>
+
+#define SC_TYPE_PLUGIN_IFNET (sc_plugin_ifnet_get_type ())
+#define SC_PLUGIN_IFNET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SC_TYPE_PLUGIN_IFNET, SCPluginIfnet))
+#define SC_PLUGIN_IFNET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SC_TYPE_PLUGIN_IFNET, SCPluginIfnetClass))
+#define SC_IS_PLUGIN_IFNET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SC_TYPE_PLUGIN_IFNET))
+#define SC_IS_PLUGIN_IFNET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SC_TYPE_PLUGIN_IFNET))
+#define SC_PLUGIN_IFNET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SC_TYPE_PLUGIN_IFNET, SCPluginIfnetClass))
+
+typedef struct _SCPluginIfnet SCPluginIfnet;
+typedef struct _SCPluginIfnetClass SCPluginIfnetClass;
+
+struct _SCPluginIfnet {
+ GObject parent;
+};
+
+struct _SCPluginIfnetClass {
+ GObjectClass parent;
+};
+
+GType sc_plugin_ifnet_get_type (void);
+#endif
diff --git a/src/settings/plugins/ifnet/tests/Makefile.am b/src/settings/plugins/ifnet/tests/Makefile.am
new file mode 100644
index 000000000..20a268052
--- /dev/null
+++ b/src/settings/plugins/ifnet/tests/Makefile.am
@@ -0,0 +1,18 @@
+INCLUDES=-I$(srcdir)/../ \
+ -I$(top_srcdir)/libnm-glib \
+ -I$(top_srcdir)/libnm-util \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/src/settings
+TESTS = check_ifnet
+check_PROGRAMS = check_ifnet
+check_ifnet_SOURCES = test_all.c
+check_ifnet_CPPFLAGS = $(CHECK_CFLAGS) $(GLIB_CFLAGS)
+check_ifnet_LDADD = $(top_builddir)/libnm-util/libnm-util.la \
+ $(builddir)/../lib-ifnet-io.la \
+ $(CHECK_LIBS) \
+ $(GLIB_LIBS)
+EXTRA_DIST = hostname \
+ net \
+ net.all \
+ nm-system-settings.conf \
+ wpa_supplicant.conf
diff --git a/src/settings/plugins/ifnet/tests/Makefile.in b/src/settings/plugins/ifnet/tests/Makefile.in
new file mode 100644
index 000000000..adb1816c7
--- /dev/null
+++ b/src/settings/plugins/ifnet/tests/Makefile.in
@@ -0,0 +1,716 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@
+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@
+TESTS = check_ifnet$(EXEEXT)
+check_PROGRAMS = check_ifnet$(EXEEXT)
+subdir = src/settings/plugins/ifnet/tests
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \
+ $(top_srcdir)/m4/gettext.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/libnl-check.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)/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 =
+am_check_ifnet_OBJECTS = check_ifnet-test_all.$(OBJEXT)
+check_ifnet_OBJECTS = $(am_check_ifnet_OBJECTS)
+am__DEPENDENCIES_1 =
+check_ifnet_DEPENDENCIES = $(top_builddir)/libnm-util/libnm-util.la \
+ $(builddir)/../lib-ifnet-io.la $(am__DEPENDENCIES_1)
+AM_V_lt = $(am__v_lt_$(V))
+am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
+am__v_lt_0 = --silent
+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_$(V))
+am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_$(V))
+am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
+am__v_at_0 = @
+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_$(V))
+am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_$(V))
+am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(check_ifnet_SOURCES)
+DIST_SOURCES = $(check_ifnet_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors = \
+red=; grn=; lgn=; blu=; std=
+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@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_LIBS = @DBUS_LIBS@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DHCLIENT_PATH = @DHCLIENT_PATH@
+DHCLIENT_VERSION = @DHCLIENT_VERSION@
+DHCPCD_PATH = @DHCPCD_PATH@
+DISABLE_DEPRECATED = @DISABLE_DEPRECATED@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GIO_CFLAGS = @GIO_CFLAGS@
+GIO_LIBS = @GIO_LIBS@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GMODULE_CFLAGS = @GMODULE_CFLAGS@
+GMODULE_LIBS = @GMODULE_LIBS@
+GMSGFMT = @GMSGFMT@
+GMSGFMT_015 = @GMSGFMT_015@
+GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+GNUTLS_LIBS = @GNUTLS_LIBS@
+GREP = @GREP@
+GTKDOC_CHECK = @GTKDOC_CHECK@
+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@
+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@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBDL = @LIBDL@
+LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@
+LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@
+LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@
+LIBICONV = @LIBICONV@
+LIBINTL = @LIBINTL@
+LIBM = @LIBM@
+LIBNL_CFLAGS = @LIBNL_CFLAGS@
+LIBNL_LIBS = @LIBNL_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @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@
+MSGFMT = @MSGFMT@
+MSGFMT_015 = @MSGFMT_015@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NM_MAJOR_VERSION = @NM_MAJOR_VERSION@
+NM_MICRO_VERSION = @NM_MICRO_VERSION@
+NM_MINOR_VERSION = @NM_MINOR_VERSION@
+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@
+PKGCONFIG_PATH = @PKGCONFIG_PATH@
+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_PLUGIN_DIR = @PPPD_PLUGIN_DIR@
+RANLIB = @RANLIB@
+RESOLVCONF_PATH = @RESOLVCONF_PATH@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SYSTEM_CA_PATH = @SYSTEM_CA_PATH@
+UDEV_BASE_DIR = @UDEV_BASE_DIR@
+USE_NLS = @USE_NLS@
+UUID_CFLAGS = @UUID_CFLAGS@
+UUID_LIBS = @UUID_LIBS@
+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_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@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+systemdsystemunitdir = @systemdsystemunitdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+INCLUDES = -I$(srcdir)/../ \
+ -I$(top_srcdir)/libnm-glib \
+ -I$(top_srcdir)/libnm-util \
+ -I$(top_srcdir)/include \
+ -I$(top_srcdir)/src/settings
+
+check_ifnet_SOURCES = test_all.c
+check_ifnet_CPPFLAGS = $(CHECK_CFLAGS) $(GLIB_CFLAGS)
+check_ifnet_LDADD = $(top_builddir)/libnm-util/libnm-util.la \
+ $(builddir)/../lib-ifnet-io.la \
+ $(CHECK_LIBS) \
+ $(GLIB_LIBS)
+
+EXTRA_DIST = hostname \
+ net \
+ net.all \
+ nm-system-settings.conf \
+ wpa_supplicant.conf
+
+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 src/settings/plugins/ifnet/tests/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/settings/plugins/ifnet/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-checkPROGRAMS:
+ @list='$(check_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
+check_ifnet$(EXEEXT): $(check_ifnet_OBJECTS) $(check_ifnet_DEPENDENCIES)
+ @rm -f check_ifnet$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(check_ifnet_OBJECTS) $(check_ifnet_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_ifnet-test_all.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+check_ifnet-test_all.o: test_all.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(check_ifnet_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT check_ifnet-test_all.o -MD -MP -MF $(DEPDIR)/check_ifnet-test_all.Tpo -c -o check_ifnet-test_all.o `test -f 'test_all.c' || echo '$(srcdir)/'`test_all.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/check_ifnet-test_all.Tpo $(DEPDIR)/check_ifnet-test_all.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test_all.c' object='check_ifnet-test_all.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(check_ifnet_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o check_ifnet-test_all.o `test -f 'test_all.c' || echo '$(srcdir)/'`test_all.c
+
+check_ifnet-test_all.obj: test_all.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(check_ifnet_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT check_ifnet-test_all.obj -MD -MP -MF $(DEPDIR)/check_ifnet-test_all.Tpo -c -o check_ifnet-test_all.obj `if test -f 'test_all.c'; then $(CYGPATH_W) 'test_all.c'; else $(CYGPATH_W) '$(srcdir)/test_all.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/check_ifnet-test_all.Tpo $(DEPDIR)/check_ifnet-test_all.Po
+@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='test_all.c' object='check_ifnet-test_all.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(check_ifnet_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o check_ifnet-test_all.obj `if test -f 'test_all.c'; then $(CYGPATH_W) 'test_all.c'; else $(CYGPATH_W) '$(srcdir)/test_all.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ 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"
+
+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; 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 \
+ echo "$$grn$$dashes"; \
+ else \
+ echo "$$red$$dashes"; \
+ fi; \
+ echo "$$banner"; \
+ test -z "$$skipped" || echo "$$skipped"; \
+ test -z "$$report" || echo "$$report"; \
+ echo "$$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_PROGRAMS)
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile
+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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+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-checkPROGRAMS clean-generic clean-libtool \
+ 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 all all-am check check-TESTS check-am clean \
+ clean-checkPROGRAMS clean-generic clean-libtool ctags \
+ 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 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/src/settings/plugins/ifnet/tests/hostname b/src/settings/plugins/ifnet/tests/hostname
new file mode 100644
index 000000000..25c761655
--- /dev/null
+++ b/src/settings/plugins/ifnet/tests/hostname
@@ -0,0 +1,2 @@
+#Generated by NetworkManager
+hostname="gentoo"
diff --git a/src/settings/plugins/ifnet/tests/net b/src/settings/plugins/ifnet/tests/net
new file mode 100644
index 000000000..e75500023
--- /dev/null
+++ b/src/settings/plugins/ifnet/tests/net
@@ -0,0 +1,147 @@
+# This blank configuration will automatically use DHCP for any net.*
+# scripts in /etc/init.d. To create a more complete configuration,
+# please review /etc/conf.d/net.example and save your configuration
+# in /etc/conf.d/net (this file :]!).
+
+config_eth0=(
+"202.117.16.121 netmask 255.255.255.0 brd 202.117.16.255"
+"192.168.4.121/24"
+"dhcp6"
+)
+routes_eth0=( "default via 202.117.16.1"
+ "192.168.4.0/24 via 192.168.4.1")
+dns_servers_eth0="202.117.0.20 202.117.0.21"
+dns_search_eth0="p12.edu.cn p13.edu.cn"
+
+config_eth1=(
+ "dhcp"
+)
+enable_ipv6_eth1="true"
+routes_eth1=( "default via 202.117.16.1" )
+dns_servers_eth1="202.117.0.20 202.117.0.21"
+config_eth2=(
+"202.117.16.1211 netmask 255.255.255.0 brd 202.117.16.255"
+"192.168.4.121/24"
+"4321:0:1:2:3:4:567:89ab/64"
+)
+routes_eth2=("default via 4321:0:1:2:3:4:567:89ab")
+enable_ipv6_eth2="true"
+config_eth3=("nufjlsjlll")
+managed_eth4=("false")
+routes_eth4=("default via 4321:0:1:2:3:4:567:89ab")
+config_eth5=("dhcp")
+config_eth6=("192.168.4.{1..101}/24")
+
+config_eth7=( "dhcp" )
+auto_eth7="true"
+
+
+config_myxjtu2=("202.117.16.121/24 brd 202.117.16.255")
+routes_myxjtu2=("default via 202.117.16.1")
+dns_servers_myxjtu2="202.117.0.20 202.117.0.21"
+#key_myxjtu2="[1] s:xjtud key [1] enc restricted"
+#key_eth6="[1] aaaa-4444-3d [2] s:xjtudlc key [1] enc open"
+
+
+username_ppp0='user'
+password_ppp0='password'
+
+config_qiaomuf=("dhcp")
+
+config_1xtest=("dhcp")
+
+config_0xab3ace=("dhcp")
+
+modules=( "iproute2" )
+ config_kvm0=( "null" )
+ config_kvm1=( "null" )
+
+ tuntap_kvm0="tap"
+ tuntap_kvm1="tap"
+ tunctl_kvm0="-u user"
+ tunctl_kvm1="-u user"
+
+bridge_br0="eth0 kvm0 kvm1"
+config_br0=( "192.168.1.10/24" )
+ brctl_br0=( "setfd 0")
+ dhcp_eth1="nosendhost nontp -I"
+
+predown() {
+ # The default in the script is to test for NFS root and disallow
+ # downing interfaces in that case. Note that if you specify a
+ # predown() function you will override that logic. Here it is, in
+ # case you still want it...
+ if is_net_fs /; then
+ eerror "root filesystem is network mounted -- can't stop ${IFACE}"
+ return 1
+ fi
+
+ # Remember to return 0 on success
+ return 0
+}
+
+postup() {
+ # This function could be used, for example, to register with a
+ # dynamic DNS service. Another possibility would be to
+ # send/receive mail once the interface is brought up.
+
+ # Here is an example that allows the use of iproute rules
+ # which have been configured using the rules_eth0 variable.
+ #rules_eth0=" \
+ # 'from 24.80.102.112/32 to 192.168.1.0/24 table localnet priority 100' \
+ # 'from 216.113.223.51/32 to 192.168.1.0/24 table localnet priority 100' \
+ #"
+ eval set -- \$rules_${IFVAR}
+ if [ $# != 0 ]; then
+ einfo "Adding IP policy routing rules"
+ eindent
+ # Ensure that the kernel supports policy routing
+ if ! ip rule list | grep -q "^"; then
+ eerror "You need to enable IP Policy Routing (CONFIG_IP_MULTIPLE_TABLES)"
+ eerror "in your kernel to use ip rules"
+ else
+ for x; do
+ ebegin "${x}"
+ ip rule add ${x}
+ eend $?
+ done
+ fi
+ eoutdent
+ # Flush the cache
+ ip route flush cache dev "${IFACE}"
+ fi
+
+}
+
+postdown() {
+ # Enable Wake-On-LAN for every interface except for lo
+ # Probably a good idea to set ifdown="no" in /etc/conf.d/net
+ # as well ;)
+ [ "${IFACE}" != "lo" ] && ethtool -s "${IFACE}" wol g
+
+ Automatically erase any ip rules created in the example postup above
+ if interface_exists "${IFACE}"; then
+ # Remove any rules for this interface
+ local rule
+ ip rule list | grep " iif ${IFACE}[ ]*" | {
+ while read rule; do
+ rule="${rule#*:}"
+ ip rule del ${rule}
+ done
+ }
+ # Flush the route cache
+ ip route flush cache dev "${IFACE}"
+ fi
+
+ # Return 0 always
+ return 0
+}
+
+failup() {
+ # This function is mostly here for completeness... I haven't
+ # thought of anything nifty to do with it yet ;-)
+}
+
+faildown()
+{}
+
diff --git a/src/settings/plugins/ifnet/tests/net.all b/src/settings/plugins/ifnet/tests/net.all
new file mode 100644
index 000000000..a30a1b95e
--- /dev/null
+++ b/src/settings/plugins/ifnet/tests/net.all
@@ -0,0 +1,864 @@
+##############################################################################
+# QUICK-START
+#
+# The quickest start is if you want to use DHCP.
+# In that case, everything should work out of the box, no configuration
+# necessary, though the startup script will warn you that you haven't
+# specified anything.
+
+# WARNING :- some examples have a mixture of IPv4 (ie 192.168.0.1) and IPv6
+# (ie 4321:0:1:2:3:4:567:89ab) internet addresses. They only work if you have
+# the relevant kernel option enabled. So if you don't have an IPv6 enabled
+# kernel then remove the IPv6 address from your config.
+
+# If you want to use a static address or use DHCP explicitly, jump
+# down to the section labelled INTERFACE HANDLERS.
+#
+# If you want to do anything more fancy, you should take the time to
+# read through the rest of this file.
+
+##############################################################################
+# MODULES
+#
+# We now support modular networking scripts which means we can easily
+# add support for new interface types and modules while keeping
+# compatability with existing ones.
+#
+# Modules load by default if the package they need is installed. If
+# you specify a module here that doesn't have it's package installed
+# then you get an error stating which package you need to install.
+# Ideally, you only use the modules setting when you have two or more
+# packages installed that supply the same service.
+#
+# In other words, you probably should DO NOTHING HERE...
+
+# Prefer ifconfig over iproute2
+modules=( "ifconfig" )
+
+# You can also specify other modules for an interface
+# In this case we prefer udhcpc over dhcpcd
+modules_eth0=( "udhcpc" )
+
+# You can also specify which modules not to use - for example you may be
+# using a supplicant or linux-wlan-ng to control wireless configuration but
+# you still want to configure network settings per ESSID associated with.
+modules=( "!iwconfig" "!wpa_supplicant" )
+# IMPORTANT: If you need the above, please disable modules in that order
+
+
+##############################################################################
+# INTERFACE HANDLERS
+#
+# We provide two interface handlers presently: ifconfig and iproute2.
+# You need one of these to do any kind of network configuration.
+# For ifconfig support, emerge sys-apps/net-tools
+# For iproute2 support, emerge sys-apps/iproute2
+
+# If you don't specify an interface then we prefer iproute2 if it's installed
+# To prefer ifconfig over iproute2
+modules=( "ifconfig" )
+
+# For a static configuration, use something like this
+# (They all do exactly the same thing btw)
+config_eth0=( "192.168.0.2/24" )
+config_eth0=( "192.168.0.2 netmask 255.255.255.0" )
+
+# We can also specify a broadcast
+config_eth0=( "192.168.0.2/24 brd 192.168.0.255" )
+config_eth0=( "192.168.0.2 netmask 255.255.255.0 broadcast 192.168.0.255" )
+
+# If you need more than one address, you can use something like this
+# NOTE: ifconfig creates an aliased device for each extra IPv4 address
+# (eth0:1, eth0:2, etc)
+# iproute2 does not do this as there is no need to
+config_eth0=(
+ "192.168.0.2/24"
+ "192.168.0.3/24"
+ "192.168.0.4/24"
+)
+# Or you can use sequence expressions
+config_eth0=( "192.168.0.{2..4}/24" )
+# which does the same as above. Be careful though as if you use this and
+# fallbacks, you have to ensure that both end up with the same number of
+# values otherwise your fallback won't work correctly.
+
+# You can also use IPv6 addresses
+# (you should always specify a prefix length with IPv6 here)
+config_eth0=(
+ "192.168.0.2/24"
+ "4321:0:1:2:3:4:567:89ab/64"
+ "4321:0:1:2:3:4:567:89ac/64"
+)
+
+# If you wish to keep existing addresses + routing and the interface is up,
+# you can specify a noop (no operation). If the interface is down or there
+# are no addresses assigned, then we move onto the next step (default dhcp)
+# This is useful when configuring your interface with a kernel command line
+# or similar
+config_eth0=( "noop" "192.168.0.2/24" )
+
+# If you don't want ANY address (only useful when calling for advanced stuff)
+config_eth0=( "null" )
+
+# Here's how to do routing if you need it
+routes_eth0=(
+ "default via 192.168.0.1" # IPv4 default route
+ "10.0.0.0/8 via 192.168.0.1" # IPv4 subnet route
+ "::/0" # IPv6 unicast
+)
+
+# If a specified module fails (like dhcp - see below), you can specify a
+# fallback like so
+fallback_eth0=( "192.168.0.2 netmask 255.255.255.0" )
+fallback_route_eth0=( "default via 192.168.0.1" )
+
+# NOTE: fallback entry must match the entry location in config_eth0
+# As such you can only have one fallback route.
+
+# Some users may need to alter the MTU - here's how
+mtu_eth0="1500"
+
+# Each module described below can set a default base metric, lower is
+# preferred over higher. This is so we can prefer a wired route over a
+# wireless route automaticaly. You can override this by setting
+metric_eth0="100"
+# or on a global basis
+metric="100"
+# The only downside of the global setting is that you have to ensure that
+# there are no conflicting routes yourself. For users with large routing
+# tables you may have to set a global metric as the due to a simple read of
+# the routing table taking over a minute at a time.
+
+##############################################################################
+# OPTIONAL MODULES
+
+# INTERFACE RENAMING
+# There is no consistent device renaming scheme for Linux.
+# The preferred way of naming devices is via the kernel module directly or
+# by using udev (http://www.reactivated.net/udevrules.php)
+
+# If you are unable to write udev rules, then we do provide a way of renaming
+# the interface based on it's MAC address, but it is not optimal.
+# Here is how to rename an interface whose MAC address is 00:11:22:33:44:55
+# to foo1
+rename_001122334455="foo1"
+
+# You can also do this based on current device name - although this is not
+# recommended. Here we rename eth1 to foo2.
+rename_eth1="foo2"
+
+#-----------------------------------------------------------------------------
+# WIRELESS (802.11 support)
+# Wireless can be provided by iwconfig or wpa_supplicant
+
+# iwconfig
+# emerge net-wireless/wireless-tools
+# Wireless options are held in /etc/conf.d/wireless - but could be here too
+# Consult the sample file /etc/conf.d/wireless.example for instructions
+# iwconfig is the default
+
+# wpa_supplicant
+# emerge net-wireless/wpa-supplicant
+# Wireless options are held in /etc/wpa_supplicant.conf
+# Consult the sample file /etc/wpa_supplicant.conf.example for instructions
+# To choose wpa_supplicant over iwconfig
+modules=( "wpa_supplicant" )
+# To configure wpa_supplicant
+wpa_supplicant_eth0="-Dwext" # For generic wireless
+wpa_supplicant_ath0="-Dmadwifi" # For Atheros based cards
+# Consult wpa_supplicant for more drivers
+# By default don't wait for wpa_suppliant to associate and authenticate.
+# If you would like to, so can specify how long in seconds
+associate_timeout_eth0=60
+# A value of 0 means wait forever.
+
+# GENERIC WIRELESS OPTIONS
+# PLEASE READ THE INSTRUCTIONS IN /etc/conf.d/wireless.example FOR
+# HOW TO USE THIS ESSID VARIABLE
+# You can also override any settings found here per ESSID - which is very
+# handy if you use different networks a lot
+config_ESSID=( "dhcp" )
+dhcpcd_ESSID="-t 5"
+
+# Setting name/domain server causes /etc/resolv.conf to be overwritten
+# Note that if DHCP is used, and you want this to take precedence then
+ set dhcp_ESSID="nodns"
+dns_servers_ESSID=( "192.168.0.1" "192.168.0.2" )
+dns_domain_ESSID="some.domain"
+dns_search_ESSID="search.this.domain search.that.domain"
+# Please check the man page for resolv.conf for more information
+# as domain and search are mutually exclusive.
+
+# You can also override any settings found here per MAC address of the AP
+# in case you use Access Points with the same ESSID but need different
+# networking configs. Below is an example - of course you use the same
+# method with other variables
+mac_config_001122334455=( "dhcp" )
+mac_dhcpcd_001122334455="-t 10"
+mac_dns_servers_001122334455=( "192.168.0.1" "192.168.0.2" )
+
+# When an interface has been associated with an Access Point, a global
+# variable called ESSID is set to the Access Point's ESSID for use in the
+# pre/post user functions below (although it's not available in preup as you
+# won't have associated then)
+
+# If you're using anything else to configure wireless on your interface AND
+# you have installed any of the above packages, you need to disable them
+modules=( "!iwconfig" "!wpa_supplicant" )
+
+#-----------------------------------------------------------------------------
+# DHCP
+# DHCP can be provided by dhclient, dhcpcd, pump or udhcpc.
+#
+# dhclient: emerge net-misc/dhcp
+# dhcpcd: emerge net-misc/dhcpcd
+# pump: emerge net-misc/pump
+# udhcpc: emerge net-misc/udhcp
+
+# If you have more than one DHCP client installed, you need to specify which
+# one to use - otherwise we default to dhcpcd if available.
+modules=( "dhclient" ) # to select dhclient over dhcpcd
+#
+# Notes:
+# - All clients send the current hostname to the DHCP server by default
+# - dhcpcd does not daemonize when the lease time is infinite
+# - udhcp-0.9.3-r3 and earlier do not support getting NTP servers
+# - pump does not support getting NIS servers
+# - DHCP tends to erase any existing device information - so add
+# static addresses after dhcp if you need them
+# - dhclient and udhcpc can set other resolv.conf options such as "option"
+# and "sortlist"- see the System module for more details
+
+# Regardless of which DHCP client you prefer, you configure them the
+# same way using one of following depending on which interface modules
+# you're using.
+config_eth0=( "dhcp" )
+
+# For passing custom options to dhcpcd use something like the following. This
+# example reduces the timeout for retrieving an address from 60 seconds (the
+# default) to 10 seconds.
+dhcpcd_eth0="-t 10"
+
+# dhclient, udhcpc and pump don't have many runtime options
+# You can pass options to them in a similar manner to dhcpcd though
+dhclient_eth0="..."
+udhcpc_eth0="..."
+pump_eth0="..."
+
+# GENERIC DHCP OPTIONS
+# Set generic DHCP options like so
+dhcp_eth0="release nodns nontp nonis nogateway nosendhost"
+
+# This tells the dhcp client to release it's lease when it stops, not to
+# overwrite dns, ntp and nis settings, not to set a default route and not to
+# send the current hostname to the dhcp server and when it starts.
+# You can use any combination of the above options - the default is not to
+# use any of them.
+
+#-----------------------------------------------------------------------------
+# For APIPA support, emerge net-misc/iputils or net-analyzer/arping
+
+# APIPA is a module that tries to find a free address in the range
+# 169.254.0.0-169.254.255.255 by arping a random address in that range on the
+# interface. If no reply is found then we assign that address to the interface
+
+# This is only useful for LANs where there is no DHCP server and you don't
+# connect directly to the internet.
+config_eth0=( "dhcp" )
+fallback_eth0=( "apipa" )
+
+#-----------------------------------------------------------------------------
+# ARPING Gateway configuration
+# and
+# Automatic Private IP Addressing (APIPA)
+# For arpingnet / apipa support, emerge net-misc/iputils or net-analyzer/arping
+#
+# This is a module that tries to find a gateway IP. If it exists then we use
+# that gateways configuration for our own. For the configuration variables
+# simply ensure that each octet is zero padded and the dots are removed.
+# Below is an example.
+#
+gateways_eth0="192.168.0.1 10.0.0.1"
+config_192168000001=( "192.168.0.2/24" )
+routes_192168000001=( "default via 192.168.0.1" )
+dns_servers_192168000001=( "192.168.0.1" )
+config_010000000001=( "10.0.0.254/8" )
+routes_010000000001=( "default via 10.0.0.1" )
+dns_servers_010000000001=( "10.0.0.1" )
+
+# We can also specify a specific MAC address for each gateway if different
+# networks have the same gateway.
+gateways_eth0="192.168.0.1,00:11:22:AA:BB:CC 10.0.0.1,33:44:55:DD:EE:FF"
+config_192168000001_001122AABBCC=( "192.168.0.2/24" )
+routes_192168000001_001122AABBCC=( "default via 192.168.0.1" )
+dns_servers_192168000001_001122AABBCC=( "192.168.0.1" )
+config_010000000001_334455DDEEFF=( "10.0.0.254/8" )
+routes_010000000001_334455DDEEFF=( "default via 10.0.0.1" )
+dns_servers_010000000001_334455DDEEFF=( "10.0.0.1" )
+
+# If we don't find any gateways (or there are none configured) then we try and
+# use APIPA to find a free address in the range 169.254.0.0-169.254.255.255
+# by arping a random address in that range on the interface. If no reply is
+# found then we assign that address to the interface.
+
+# This is only useful for LANs where there is no DHCP server.
+config_eth0=( "arping" )
+
+# or if no DHCP server can be found
+config_eth0=( "dhcp" )
+fallback_eth0=( "arping" )
+
+# NOTE: We default to sleeping for 1 second the first time we attempt an
+# arping to give the interface time to settle on the LAN. This appears to
+# be a good default for most instances, but if not you can alter it here.
+arping_sleep=5
+arping_sleep_lan=7
+
+# NOTE: We default to waiting 3 seconds to get an arping response. You can
+# change the default wait like so.
+arping_wait=3
+arping_wait_lan=2
+
+#-----------------------------------------------------------------------------
+# VLAN (802.1q support)
+# For VLAN support, emerge net-misc/vconfig
+
+# Specify the VLAN numbers for the interface like so
+# Please ensure your VLAN IDs are NOT zero-padded
+vlans_eth0="1 2"
+
+# You may not want to assign an IP the the physical interface, but we still
+# need it up.
+config_eth0=( "null" )
+
+# You can also configure the VLAN - see for vconfig man page for more details
+vconfig_eth0=( "set_name_type VLAN_PLUS_VID_NO_PAD" )
+vconfig_vlan1=( "set_flag 1" "set_egress_map 2 6" )
+config_vlan1=( "172.16.3.1 netmask 255.255.254.0" )
+config_vlan2=( "172.16.2.1 netmask 255.255.254.0" )
+
+# NOTE: Vlans can be configured with a . in their interface names
+# When configuring vlans with this name type, you need to replace . with a _
+config_eth0.1=( "dhcp" ) - does not work
+config_eth0_1=( "dhcp" ) - does work
+
+# NOTE: Vlans are controlled by their physical interface and not per vlan
+# This means you do not need to create init scripts in /etc/init.d for each
+# vlan, you must need to create one for the physical interface.
+# If you wish to control the configuration of each vlan through a separate
+# script, or wish to rename the vlan interface to something that vconfig
+# cannot then you need to do this.
+vlan_start_eth0="no"
+
+# If you do the above then you may want to depend on eth0 like so
+ RC_NEED_vlan1="net.eth0"
+# NOTE: depend functions only work in /etc/conf.d/net
+# and not in profile configs such as /etc/conf.d/net.foo
+
+#-----------------------------------------------------------------------------
+# Bonding
+# For link bonding/trunking emerge net-misc/ifenslave
+
+# To bond interfaces together
+slaves_bond0="eth0 eth1 eth2"
+config_bond0=( "null" ) # You may not want to assign an IP the the bond
+
+# If any of the slaves require extra configuration - for example wireless or
+# ppp devices - we need to depend function on the bonded interfaces
+RC_NEED_bond0="net.eth0 net.eth1"
+
+
+#-----------------------------------------------------------------------------
+# Classical IP over ATM
+# For CLIP support emerge net-dialup/linux-atm
+
+# Ensure that you have /etc/atmsigd.conf setup correctly
+# Now setup each clip interface like so
+clip_atm0=( "peer_ip [if.]vpi.vci [opts]" ... )
+# where "peer_ip" is the IP address of a PVC peer (in case of an ATM connection
+# with your ISP, your only peer is usually the ISP gateway closest to you),
+# "if" is the number of the ATM interface which will carry the PVC, "vpi.vci"
+# is the ATM VC address, and "opts" may optionally specify VC parameters like
+# qos, pcr, and the like (see "atmarp -s" for further reference). Please also
+# note quoting: it is meant to distinguish the VCs you want to create. You may,
+# in example, create an atm0 interface to more peers, like this:
+clip_atm0=( "1.1.1.254 0.8.35" "1.1.1.253 1.8.35" )
+
+# By default, the PVC will use the LLC/SNAP encapsulation. If you rather need a
+# null encapsulation (aka "VC mode"), please add the keyword "null" to opts.
+
+
+#-----------------------------------------------------------------------------
+# PPP
+# For PPP support, emerge net-dialup/ppp
+# PPP is used for most dialup connections, including ADSL.
+# The older ADSL module is documented below, but you are encouraged to try
+# this module first.
+#
+# You need to create the PPP net script yourself. Make it like so
+#ln -s net.lo /etc/init.d/net.ppp0
+#
+# We have to instruct ppp0 to actually use ppp
+config_ppp0=( "ppp" )
+#
+# Each PPP interface requires an interface to use as a "Link"
+link_ppp0="/dev/ttyS0" # Most PPP links will use a serial port
+link_ppp0="eth0" # PPPoE requires an ethernet interface
+link_ppp0="[itf.]vpi.vci" # PPPoA requires the ATM VC's address
+link_ppp0="/dev/null" # ISDN links should have this
+link_ppp0="pty 'your_link_command'" # PPP links over ssh, rsh, etc
+#
+# Here you should specify what pppd plugins you want to use
+# Available plugins are: pppoe, pppoa, capi, dhcpc, minconn, radius,
+# radattr, radrealms and winbind
+plugins_ppp0=(
+ "pppoe" # Required plugin for PPPoE
+ "pppoa vc-encaps" # Required plugin for PPPoA with an option
+ "capi" # Required plugin for ISDN
+)
+#
+# PPP requires at least a username. You can optionally set a password here too
+# If you don't, then it will use the password specified in /etc/ppp/*-secrets
+# against the specified username
+username_ppp0='user'
+password_ppp0='password'
+# NOTE: You can set a blank password like so
+password_ppp0=
+#
+# The PPP daemon has many options you can specify - although there are many
+# and may seem daunting, it is recommended that you read the pppd man page
+# before enabling any of them
+pppd_ppp0=(
+ "maxfail 0" # WARNING: It's not recommended you use this
+ # if you don't specify maxfail then we assume 0
+ "updetach" # If not set, "/etc/init.d/net.ppp0 start" will return
+ # immediately, without waiting the link to come up
+ # for the first time.
+ # Do not use it for dial-on-demand links!
+ "debug" # Enables syslog debugging
+ "noauth" # Do not require the peer to authenticate itself
+ "defaultroute" # Make this PPP interface the default route
+ "usepeerdns" # Use the DNS settings provided by PPP
+
+# On demand options
+ "demand" # Enable dial on demand
+ "idle 30" # Link goes down after 30 seconds of inactivity
+ "10.112.112.112:10.112.112.113" # Phony IP addresses
+ "ipcp-accept-remote" # Accept the peers idea of remote address
+ "ipcp-accept-local" # Accept the peers idea of local address
+ "holdoff 3" # Wait 3 seconds after link dies before re-starting
+
+# Dead peer detection
+ "lcp-echo-interval 15" # Send a LCP echo every 15 seconds
+ "lcp-echo-failure 3" # Make peer dead after 3 consective
+ # echo-requests
+
+# Compression options - use these to completely disable compression
+# noaccomp noccp nobsdcomp nodeflate nopcomp novj novjccomp
+
+# Dial-up settings
+ "lock" # Lock serial port
+ "115200" # Set the serial port baud rate
+ "modem crtscts" # Enable hardware flow control
+ "192.168.0.1:192.168.0.2" # Local and remote IP addresses
+)
+#
+# Dial-up PPP users need to specify at least one telephone number
+phone_number_ppp0=( "12345689" ) # Maximum 2 phone numbers are supported
+# They will also need a chat script - here's a good one
+chat_ppp0=(
+# 'ABORT' 'BUSY'
+# 'ABORT' 'ERROR'
+# 'ABORT' 'NO ANSWER'
+# 'ABORT' 'NO CARRIER'
+# 'ABORT' 'NO DIALTONE'
+# 'ABORT' 'Invalid Login'
+# 'ABORT' 'Login incorrect'
+# 'TIMEOUT' '5'
+# '' 'ATZ'
+# 'OK' 'AT' # Put your modem initialization string here
+# 'OK' 'ATDT\T'
+# 'TIMEOUT' '60'
+# 'CONNECT' ''
+# 'TIMEOUT' '5'
+# '~--' ''
+)
+
+# If the link require extra configuration - for example wireless or
+# RFC 268 bridge - we need to depend on the bridge so they get
+# configured correctly.
+RC_NEED_ppp0="net.nas0"
+
+#WARNING: if MTU of the PPP interface is less than 1500 and you use this
+#machine as a router, you should add the following rule to your firewall
+#
+#iptables -I FORWARD 1 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
+
+#-----------------------------------------------------------------------------
+# ADSL
+# For ADSL support, emerge net-dialup/rp-pppoe
+# WARNING: This ADSL module is being deprecated in favour of the PPP module
+# above.
+# You should make the following settings and also put your
+# username/password information in /etc/ppp/pap-secrets
+
+# Configure the interface to use ADSL
+config_eth0=( "adsl" )
+
+# You probably won't need to edit /etc/ppp/pppoe.conf if you set this
+adsl_user_eth0="my-adsl-username"
+
+#-----------------------------------------------------------------------------
+# ISDN
+# For ISDN support, emerge net-dialup/isdn4k-utils
+# You should make the following settings and also put your
+# username/password information in /etc/ppp/pap-secrets
+
+# Configure the interface to use ISDN
+config_ippp0=( "dhcp" )
+# It's important to specify dhcp if you need it!
+config_ippp0=( "192.168.0.1/24" )
+# Otherwise, you can use a static IP
+
+# NOTE: The interface name must be either ippp or isdn followed by a number
+
+# You may need this option to set the default route
+ipppd_eth0="defaultroute"
+
+#-----------------------------------------------------------------------------
+# MAC changer
+# To set a specific MAC address
+mac_eth0="00:11:22:33:44:55"
+
+# For changing MAC addresses using the below, emerge net-analyzer/macchanger
+# - to randomize the last 3 bytes only
+mac_eth0="random-ending"
+# - to randomize between the same physical type of connection (e.g. fibre,
+# copper, wireless) , all vendors
+mac_eth0="random-samekind"
+# - to randomize between any physical type of connection (e.g. fibre, copper,
+# wireless) , all vendors
+mac_eth0="random-anykind"
+# - full randomization - WARNING: some MAC addresses generated by this may NOT
+# act as expected
+mac_eth0="random-full"
+# custom - passes all parameters directly to net-analyzer/macchanger
+mac_eth0="some custom set of parameters"
+
+# You can also set other options based on the MAC address of your network card
+# Handy if you use different docking stations with laptops
+config_001122334455=( "dhcp" )
+
+#-----------------------------------------------------------------------------
+# TUN/TAP
+# For TUN/TAP support emerge net-misc/openvpn or sys-apps/usermode-utilities
+#
+# You must specify if we're a tun or tap device. Then you can give it any
+# name you like - such as vpn
+tuntap_vpn="tun"
+config_vpn=( "192.168.0.1/24")
+
+# Or stick wit the generic names - like tap0
+tuntap_tap0="tap"
+config_tap0=( "192.168.0.1/24")
+
+# For passing custom options to tunctl use something like the following. This
+# example sets the owner to adm
+tunctl_tun1="-u adm"
+# When using openvpn, there are no options
+
+#-----------------------------------------------------------------------------
+# Bridging (802.1d)
+# For bridging support emerge net-misc/bridge-utils
+
+# To add ports to bridge br0
+bridge_br0="eth0 eth1"
+# or dynamically add them when the interface comes up
+bridge_add_eth0="br0"
+bridge_add_eth1="br0"
+
+# You need to configure the ports to null values so dhcp does not get started
+config_eth0=( "null" )
+config_eth1=( "null" )
+
+# Finally give the bridge an address - dhcp or a static IP
+config_br0=( "dhcp" ) # may not work when adding ports dynamically
+config_br0=( "192.168.0.1/24" )
+
+# If any of the ports require extra configuration - for example wireless or
+# ppp devices - we need to depend on them like so.
+RC_NEED_br0="net.eth0 net.eth1"
+
+# Below is an example of configuring the bridge
+# Consult "man brctl" for more details
+brctl_br0=( "setfd 0" "sethello 0" "stp off" )
+
+#-----------------------------------------------------------------------------
+# RFC 2684 Bridge Support
+# For RFC 2684 bridge support emerge net-misc/br2684ctl
+
+# Interface names have to be of the form nas0, nas1, nas2, etc.
+# You have to specify a VPI and VCI for the interface like so
+br2684ctl_nas0="-a 0.38" # UK VPI and VCI
+
+# You may want to configure the encapsulation method as well by adding the -e
+# option to the command above (may need to be before the -a command)
+# -e 0 # LLC (default)
+# -e 1 # VC mux
+
+# Then you can configure the interface as normal
+config_nas0=( "192.168.0.1/24" )
+
+#-----------------------------------------------------------------------------
+# Tunnelling
+# WARNING: For tunnelling it is highly recommended that you
+# emerge sys-apps/iproute2
+#
+# For GRE tunnels
+iptunnel_vpn0="mode gre remote 207.170.82.1 key 0xffffffff ttl 255"
+
+# For IPIP tunnels
+iptunnel_vpn0="mode ipip remote 207.170.82.2 ttl 255"
+
+# To configure the interface
+config_vpn0=( "192.168.0.2 pointopoint 192.168.1.2" ) # ifconfig style
+config_vpn0=( "192.168.0.2 peer 192.168.1.1" ) # iproute2 style
+
+# 6to4 Tunnels allow IPv6 to work over IPv4 addresses, provided you
+# have a non-private address configured on an interface.
+ link_6to4="eth0" # Interface to base it's addresses on
+ config_6to4=( "ip6to4" )
+# You may want to depend on eth0 like so
+RC_NEED_6to4="net.eth0"
+# To ensure that eth0 is configured before 6to4. Of course, the tunnel could be
+# any name and this also works for any configured interface.
+# NOTE: If you're not using iproute2 then your 6to4 tunnel has to be called
+# sit0 - otherwise use a different name like 6to4 in the example above.
+
+
+#-----------------------------------------------------------------------------
+# System
+# For configuring system specifics such as domain, dns, ntp and nis servers
+# It's rare that you would need todo this, but you can anyway.
+# This is most benefit to wireless users who don't use DHCP so they can change
+# their configs based on ESSID. See wireless.example for more details
+
+# To use dns settings such as these, dns_servers_eth0 must be set!
+# If you omit the _eth0 suffix, then it applies to all interfaces unless
+# overridden by the interface suffix.
+dns_domain_eth0="your.domain"
+dns_servers_eth0="192.168.0.2 192.168.0.3"
+dns_search_eth0="this.domain that.domain"
+dns_options_eth0=( "timeout 1" "rotate" )
+dns_sortlist_eth0="130.155.160.0/255.255.240.0 130.155.0.0"
+# See the man page for resolv.conf for details about the options and sortlist
+# directives
+
+ntp_servers_eth0="192.168.0.2 192.168.0.3"
+
+nis_domain_eth0="domain"
+nis_servers_eth0="192.168.0.2 192.168.0.3"
+
+# NOTE: Setting any of these will stamp on the files in question. So if you
+# don't specify dns_servers but you do specify dns_domain then no nameservers
+# will be listed in /etc/resolv.conf even if there were any there to start
+# with.
+# If this is an issue for you then maybe you should look into a resolv.conf
+# manager like resolvconf-gentoo to manage this file for you. All packages
+# that baselayout supports use resolvconf-gentoo if installed.
+
+#-----------------------------------------------------------------------------
+# Cable in/out detection
+# Sometimes the cable is in, others it's out. Obviously you don't want to
+# restart net.eth0 every time when you plug it in either.
+#
+# netplug is a package that detects this and requires no extra configuration
+# on your part.
+# emerge sys-apps/netplug
+# or
+# emerge sys-apps/ifplugd
+# and you're done :)
+
+# By default we don't wait for netplug/ifplugd to configure the interface.
+# If you would like it to wait so that other services now that network is up
+# then you can specify a timeout here.
+plug_timeout="10"
+# A value of 0 means wait forever.
+
+# If you don't want to use netplug on a specific interface but you have it
+# installed, you can disable it for that interface via the modules statement
+modules_eth0=( "!netplug" )
+# You can do the same for ifplugd
+#
+# You can disable them both with the generic plug
+modules_eth0=( "!plug" )
+
+# To use specific ifplugd options, fex specifying wireless mode
+ifplugd_eth0="--api-mode=wlan"
+# man ifplugd for more options
+
+##############################################################################
+# ADVANCED CONFIGURATION
+#
+# Four functions can be defined which will be called surrounding the
+# start/stop operations. The functions are called with the interface
+# name first so that one function can control multiple adapters. An extra two
+# functions can be defined when an interface fails to start or stop.
+#
+# The return values for the preup and predown functions should be 0
+# (success) to indicate that configuration or deconfiguration of the
+# interface can continue. If preup returns a non-zero value, then
+# interface configuration will be aborted. If predown returns a
+# non-zero value, then the interface will not be allowed to continue
+# deconfiguration.
+#
+# The return values for the postup, postdown, failup and faildown functions are
+# ignored since there's nothing to do if they indicate failure.
+#
+# ${IFACE} is set to the interface being brought up/down
+# ${IFVAR} is ${IFACE} converted to variable name bash allows
+
+#preup() {
+# # Test for link on the interface prior to bringing it up. This
+# # only works on some network adapters and requires the mii-diag
+# # package to be installed.
+# if mii-tool "${IFACE}" 2> /dev/null | grep -q 'no link'; then
+# ewarn "No link on ${IFACE}, aborting configuration"
+# return 1
+# fi
+#
+# # Test for link on the interface prior to bringing it up. This
+# # only works on some network adapters and requires the ethtool
+# # package to be installed.
+# if ethtool "${IFACE}" | grep -q 'Link detected: no'; then
+# ewarn "No link on ${IFACE}, aborting configuration"
+# return 1
+# fi
+#
+#
+# # Remember to return 0 on success
+# return 0
+#}
+
+#predown() {
+# # The default in the script is to test for NFS root and disallow
+# # downing interfaces in that case. Note that if you specify a
+# # predown() function you will override that logic. Here it is, in
+# # case you still want it...
+# if is_net_fs /; then
+# eerror "root filesystem is network mounted -- can't stop ${IFACE}"
+# return 1
+# fi
+#
+# # Remember to return 0 on success
+# return 0
+#}
+
+#postup() {
+# # This function could be used, for example, to register with a
+# # dynamic DNS service. Another possibility would be to
+# # send/receive mail once the interface is brought up.
+
+# # Here is an example that allows the use of iproute rules
+# # which have been configured using the rules_eth0 variable.
+# #rules_eth0=(
+# # "from 24.80.102.112/32 to 192.168.1.0/24 table localnet priority 100"
+# # "from 216.113.223.51/32 to 192.168.1.0/24 table localnet priority 100"
+# #)
+# local x="rules_${IFVAR}[@]"
+# local -a rules=( "${!x}" )
+# if [[ -n ${rules} ]] ; then
+# einfo "Adding IP policy routing rules"
+# eindent
+# # Ensure that the kernel supports policy routing
+# if ! ip rule list | grep -q "^" ; then
+# eerror "You need to enable IP Policy Routing (CONFIG_IP_MULTIPLE_TABLES)"
+# eerror "in your kernel to use ip rules"
+# else
+# for x in "${rules[@]}" ; do
+# ebegin "${x}"
+# ip rule add ${x} dev "${IFACE}"
+# eend $?
+# done
+# fi
+# eoutdent
+# # Flush the cache
+# ip route flush cache dev "${IFACE}"
+# fi
+
+#}
+
+#postdown() {
+# # Enable Wake-On-LAN for every interface except for lo
+# # Probably a good idea to set RC_DOWN_INTERFACE="no" in /etc/conf.d/rc
+# # as well ;)
+# [[ ${IFACE} != "lo" ]] && ethtool -s "${IFACE}" wol g
+
+# Automatically erase any ip rules created in the example postup above
+# if interface_exists "${IFACE}" ; then
+# # Remove any rules for this interface
+# local rule
+# ip rule list | grep " iif ${IFACE}[ ]*" | {
+# while read rule ; do
+# rule="${rule#*:}"
+# ip rule del ${rule}
+# done
+# }
+# # Flush the route cache
+# ip route flush cache dev "${IFACE}"
+# fi
+
+# # Return 0 always
+# return 0
+#}
+
+#failup() {
+# # This function is mostly here for completeness... I haven't
+# # thought of anything nifty to do with it yet ;-)
+#}
+
+#faildown() {
+# # This function is mostly here for completeness... I haven't
+# # thought of anything nifty to do with it yet ;-)
+#}
+
+##############################################################################
+# FORCING MODULES
+# The Big Fat Warning :- If you use module forcing do not complain to us or
+# file bugs about it not working!
+#
+# Loading modules is a slow affair - we have to check each one for the following
+# 1) Code sanity
+# 2) Has the required package been emerged?
+# 3) Has it modified anything?
+# 4) Have all the dependant modules been loaded?
+
+# Then we have to strip out the conflicting modules based on user preference
+# and default configuration and sort them into the correct order.
+# Finally we check the end result for dependencies.
+
+# This, of course, takes valuable CPU time so we provide module forcing as a
+# means to speed things up. We still do *some* checking but not much.
+
+# It is essential that you force modules in the correct order and supply all
+# the modules you need. You must always supply an interface module - we
+# supply ifconfig or iproute2.
+
+# The Big Fat Warning :- If you use module forcing do not complain to us or
+# file bugs about it not working!
+
+# Now that we've warned you twice, here's how to do it
+modules_force=( "ifconfig" )
+modules_force=( "iproute2" "dhcpcd" )
+
+# We can also apply this to a specific interface
+modules_force_eth1=( "iproute2" )
+
+# The below will not work
+modules_force=( "dhcpcd" )
+# No interface (ifconfig/iproute2)
+modules_force=( "ifconfig" "essidnet" "iwconfig" )
+# Although it will not crash, essidnet will not work as it has to come after
+# iwconfig
+modules_force=( "iproute2" "ifconfig" )
+# The interface will be setup twice which will cause problems
diff --git a/src/settings/plugins/ifnet/tests/nm-system-settings.conf b/src/settings/plugins/ifnet/tests/nm-system-settings.conf
new file mode 100644
index 000000000..39bc87b8b
--- /dev/null
+++ b/src/settings/plugins/ifnet/tests/nm-system-settings.conf
@@ -0,0 +1,5 @@
+[main]
+plugins=ifnet,keyfile
+
+[ifnet]
+managed=false
diff --git a/src/settings/plugins/ifnet/tests/test_all.c b/src/settings/plugins/ifnet/tests/test_all.c
new file mode 100644
index 000000000..d114bbba8
--- /dev/null
+++ b/src/settings/plugins/ifnet/tests/test_all.c
@@ -0,0 +1,399 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service (ifnet)
+ *
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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 (C) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <glib.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <nm-utils.h>
+
+#include "net_parser.h"
+#include "nm-test-helpers.h"
+#include "net_utils.h"
+#include "wpa_parser.h"
+#include "connection_parser.h"
+
+static void
+test_getdata ()
+{
+ ASSERT (ifnet_get_data ("eth1", "config")
+ && strcmp (ifnet_get_data ("eth1", "config"), "dhcp") == 0,
+ "get data", "config_eth1 is not correct");
+ ASSERT (ifnet_get_data ("ppp0", "username")
+ && strcmp (ifnet_get_data ("ppp0", "username"), "user") == 0,
+ "get data", "config_ppp0 username is not correctly read");
+ ASSERT (ifnet_get_data ("ppp0", "password")
+ && strcmp (ifnet_get_data ("ppp0", "password"),
+ "password") == 0, "get data",
+ "config_ppp0 password is not correctly read");
+}
+
+static void
+test_read_hostname ()
+{
+ gchar *hostname = read_hostname ("hostname");
+
+ ASSERT (hostname != NULL, "get hostname", "hostname is NULL");
+ ASSERT (strcmp ("gentoo", hostname) == 0,
+ "get hostname",
+ "hostname is not correctly read, read:%s, expected: gentoo",
+ hostname);
+ g_free (hostname);
+}
+
+static void
+test_write_hostname ()
+{
+ gchar *hostname = read_hostname ("hostname");
+ gchar *tmp;
+
+ write_hostname ("gentoo-nm", "hostname");
+ tmp = read_hostname ("hostname");
+ ASSERT (strcmp (tmp, "gentoo-nm") == 0,
+ "write hostname", "write hostname error");
+ write_hostname (hostname, "hostname");
+ g_free (tmp);
+ g_free (hostname);
+}
+
+static void
+test_is_static ()
+{
+ ASSERT (is_static_ip4 ("eth1") == FALSE, "is static",
+ "a dhcp interface is recognized as static");
+ ASSERT (is_static_ip4 ("eth0") == TRUE, "is static",
+ "a static interface is recognized as dhcp");
+ ASSERT (!is_static_ip6 ("eth0") == TRUE, "is static",
+ "a static interface is recognized as dhcp");
+}
+
+static void
+test_has_default_route ()
+{
+ ASSERT (has_default_ip4_route ("eth0"),
+ "has default route", "eth0 should have a default ipv4 route");
+ ASSERT (has_default_ip6_route ("eth4"),
+ "has default route", "eth4 should have a default ipv6 route");
+ ASSERT (!has_default_ip4_route ("eth5")
+ && !has_default_ip6_route ("eth5"),
+ "has default route", "eth5 shouldn't have a default route");
+}
+
+static void
+test_has_ip6_address ()
+{
+ ASSERT (has_ip6_address ("eth2"), "has ip6 address",
+ "eth2 should have a ipv6 address");
+ ASSERT (!has_ip6_address ("eth0"), "has ip6 address",
+ "eth0 shouldn't have a ipv6 address")
+
+}
+
+static void
+test_is_ip4_address ()
+{
+ gchar *address1 = "192.168.4.232/24";
+ gchar *address2 = "192.168.100.{1..254}/24";
+ gchar *address3 = "192.168.4.2555/24";
+
+ ASSERT (is_ip4_address (address1), "is ip4 address",
+ "%s should be a valid address", address1);
+ ASSERT (is_ip4_address (address2), "is ip4 address",
+ "%s should be a valid address", address2);
+ ASSERT (!is_ip4_address (address3), "is ip4 address",
+ "%s should be an invalid address", address3);
+}
+
+static void
+test_is_ip6_address ()
+{
+ gchar *address1 = "4321:0:1:2:3:4:567:89ac/24";
+
+ ASSERT (is_ip6_address (address1), "is ip6 address",
+ "%s should be a valid address", address1);
+}
+
+static void
+check_ip_block (ip_block * iblock, gchar * ip, gchar * netmask, gchar * gateway)
+{
+ char *str;
+ struct in_addr tmp_ip4_addr;
+
+ str = malloc (INET_ADDRSTRLEN);
+ tmp_ip4_addr.s_addr = iblock->ip;
+ inet_ntop (AF_INET, &tmp_ip4_addr, str, INET_ADDRSTRLEN);
+ ASSERT (strcmp (ip, str) == 0, "check ip",
+ "ip expected:%s, find:%s", ip, str);
+ tmp_ip4_addr.s_addr = iblock->netmask;
+ inet_ntop (AF_INET, &tmp_ip4_addr, str, INET_ADDRSTRLEN);
+ ASSERT (strcmp (netmask, str) == 0, "check netmask",
+ "netmask expected:%s, find:%s", netmask, str);
+ tmp_ip4_addr.s_addr = iblock->gateway;
+ inet_ntop (AF_INET, &tmp_ip4_addr, str, INET_ADDRSTRLEN);
+ ASSERT (strcmp (gateway, str) == 0, "check gateway",
+ "gateway expected:%s, find:%s", gateway, str);
+ free (str);
+}
+
+static void
+test_convert_ipv4_config_block ()
+{
+ ip_block *iblock = convert_ip4_config_block ("eth0");
+ ip_block *tmp = iblock;
+
+ ASSERT (iblock != NULL, "convert ipv4 block",
+ "block eth0 should not be NULL");
+ check_ip_block (iblock, "202.117.16.121", "255.255.255.0",
+ "202.117.16.1");
+ iblock = iblock->next;
+ destroy_ip_block (tmp);
+ ASSERT (iblock != NULL, "convert ipv4 block",
+ "block eth0 should have a second IP address");
+ check_ip_block (iblock, "192.168.4.121", "255.255.255.0",
+ "202.117.16.1");
+ destroy_ip_block (iblock);
+ iblock = convert_ip4_config_block ("eth2");
+ ASSERT (iblock != NULL
+ && iblock->next == NULL,
+ "convert error IPv4 address", "should only get one address");
+ check_ip_block (iblock, "192.168.4.121", "255.255.255.0", "0.0.0.0");
+ destroy_ip_block (iblock);
+ iblock = convert_ip4_config_block ("eth3");
+ ASSERT (iblock == NULL, "convert config_block",
+ "convert error configuration");
+ destroy_ip_block (iblock);
+ iblock = convert_ip4_config_block ("eth6");
+ ASSERT (iblock != NULL, "convert config_block",
+ "convert error configuration");
+ destroy_ip_block (iblock);
+}
+
+static void
+test_convert_ipv4_routes_block ()
+{
+ ip_block *iblock = convert_ip4_routes_block ("eth0");
+ ip_block *tmp = iblock;
+
+ ASSERT (iblock != NULL, "convert ip4 routes", "should get one route");
+ check_ip_block (iblock, "192.168.4.0", "255.255.255.0", "192.168.4.1");
+ iblock = iblock->next;
+ destroy_ip_block (tmp);
+ ASSERT (iblock == NULL, "convert ip4 routes",
+ "should only get one route");
+}
+
+static void
+test_wpa_parser ()
+{
+ const char *value;
+
+ ASSERT (exist_ssid ("example"), "get wsec",
+ "ssid myxjtu2 is not found");
+ ASSERT (exist_ssid ("static-wep-test"), "exist_ssid",
+ "ssid static-wep-test is not found");
+ value = wpa_get_value ("static-wep-test", "key_mgmt");
+ ASSERT (value
+ && strcmp (value, "NONE") == 0, "get wpa data",
+ "key_mgmt of static-wep-test should be NONE, find %s", value);
+ value = wpa_get_value ("static-wep-test", "wep_key0");
+ ASSERT (value
+ && strcmp (value, "\"abcde\"") == 0,
+ "get wpa data",
+ "wep_key0 of static-wep-test should be abcde, find %s", value);
+ ASSERT (exist_ssid ("leap-example"), "get wsec",
+ "ssid leap-example is not found");
+}
+
+static void
+test_strip_string ()
+{
+ gchar *str = "( \"default via 202.117.16.1\" )";
+ gchar *result = g_strdup (str);
+ gchar *result_b = result;
+
+ result = strip_string (result, '(');
+ result = strip_string (result, ')');
+ result = strip_string (result, '"');
+ ASSERT (strcmp (result, "default via 202.117.16.1") ==
+ 0, "strip_string",
+ "string isn't stripped, result is: %s", result);
+ g_free (result_b);
+}
+
+static void
+test_is_unmanaged ()
+{
+ ASSERT (is_managed ("eth0"), "test_is_unmanaged",
+ "eth0 should be managed");
+ ASSERT (!is_managed ("eth4"), "test_is_unmanaged",
+ "eth4 should be unmanaged");
+}
+
+static void
+test_new_connection ()
+{
+ GError **error = NULL;
+ NMConnection *connection;
+
+ connection = ifnet_update_connection_from_config_block ("eth2", error);
+ ASSERT (connection != NULL, "new connection",
+ "new connection failed: %s",
+ error == NULL ? "None" : (*error)->message);
+ g_object_unref (connection);
+ connection =
+ ifnet_update_connection_from_config_block ("qiaomuf", error);
+ ASSERT (connection != NULL, "new connection",
+ "new connection failed: %s", error
+ && (*error) ? (*error)->message : "NONE");
+ g_object_unref (connection);
+ connection =
+ ifnet_update_connection_from_config_block ("myxjtu2", error);
+ ASSERT (connection != NULL, "new connection",
+ "new connection failed: %s", error
+ && (*error) ? (*error)->message : "NONE");
+ g_object_unref (connection);
+}
+
+#define NET_GEN_NAME "net.generate"
+#define SUP_GEN_NAME "wpa_supplicant.conf.generate"
+
+static void
+test_update_connection ()
+{
+ GError **error = NULL;
+ NMConnection *connection;
+ gboolean success;
+
+ connection = ifnet_update_connection_from_config_block ("eth0", error);
+ ASSERT (connection != NULL, "get connection",
+ "get connection failed: %s",
+ error == NULL ? "None" : (*error)->message);
+
+ success = ifnet_update_parsers_by_connection (connection, "eth0",
+ NET_GEN_NAME,
+ SUP_GEN_NAME,
+ NULL,
+ error);
+ ASSERT (success, "update connection", "update connection failed %s", "eth0");
+ g_object_unref (connection);
+
+ connection = ifnet_update_connection_from_config_block ("0xab3ace", error);
+ ASSERT (connection != NULL, "get connection", "get connection failed: %s",
+ error == NULL ? "None" : (*error)->message);
+
+ success = ifnet_update_parsers_by_connection (connection, "0xab3ace",
+ NET_GEN_NAME,
+ SUP_GEN_NAME,
+ NULL,
+ error);
+ ASSERT (success, "update connection", "update connection failed %s", "0xab3ace");
+ g_object_unref (connection);
+
+ unlink (NET_GEN_NAME);
+ unlink (SUP_GEN_NAME);
+}
+
+static void
+test_add_connection ()
+{
+ NMConnection *connection;
+
+ connection = ifnet_update_connection_from_config_block ("eth0", NULL);
+ ASSERT (ifnet_add_new_connection (connection, NET_GEN_NAME, SUP_GEN_NAME, NULL),
+ "add connection", "add connection failed: %s", "eth0");
+ g_object_unref (connection);
+ connection = ifnet_update_connection_from_config_block ("myxjtu2", NULL);
+ ASSERT (ifnet_add_new_connection (connection, NET_GEN_NAME, SUP_GEN_NAME, NULL),
+ "add connection", "add connection failed: %s", "myxjtu2");
+ g_object_unref (connection);
+
+ unlink (NET_GEN_NAME);
+ unlink (SUP_GEN_NAME);
+}
+
+static void
+test_delete_connection ()
+{
+ GError *error = NULL;
+ NMConnection *connection;
+
+ connection = ifnet_update_connection_from_config_block ("eth7", &error);
+ ASSERT (connection != NULL, "get connection",
+ "get connection failed: %s",
+ error ? error->message : "None");
+ ASSERT (ifnet_delete_connection_in_parsers ("eth7", NET_GEN_NAME, SUP_GEN_NAME),
+ "delete connection", "delete connection failed: %s", "eth7");
+ g_object_unref (connection);
+ connection = ifnet_update_connection_from_config_block ("qiaomuf", &error);
+ ASSERT (connection != NULL, "get connection",
+ "get connection failed: %s",
+ error ? error->message : "None");
+ ASSERT (ifnet_delete_connection_in_parsers ("qiaomuf", NET_GEN_NAME, SUP_GEN_NAME),
+ "delete connection", "delete connection failed: %s", "qiaomuf");
+ g_object_unref (connection);
+
+ unlink (NET_GEN_NAME);
+ unlink (SUP_GEN_NAME);
+}
+
+static void
+run_all (gboolean run)
+{
+ if (run) {
+ test_strip_string ();
+ test_is_static ();
+ test_has_ip6_address ();
+ test_has_default_route ();
+ test_getdata ();
+ test_read_hostname ();
+ test_write_hostname ();
+ test_is_ip4_address ();
+ test_is_ip6_address ();
+ test_convert_ipv4_config_block ();
+ test_convert_ipv4_routes_block ();
+ test_is_unmanaged ();
+ test_wpa_parser ();
+ test_convert_ipv4_routes_block ();
+ test_new_connection ();
+ test_update_connection ();
+ test_add_connection ();
+ test_delete_connection ();
+ }
+}
+
+int
+main (void)
+{
+// g_mem_set_vtable(glib_mem_profiler_table);
+// g_atexit(g_mem_profile);
+ g_type_init ();
+ ifnet_destroy ();
+ wpa_parser_destroy ();
+ ifnet_init ("net");
+ wpa_parser_init ("wpa_supplicant.conf");
+ printf ("Initialization complete\n");
+ run_all (TRUE);
+ ifnet_destroy ();
+ wpa_parser_destroy ();
+ return 0;
+}
diff --git a/src/settings/plugins/ifnet/tests/wpa_supplicant.conf b/src/settings/plugins/ifnet/tests/wpa_supplicant.conf
new file mode 100644
index 000000000..a2595d42c
--- /dev/null
+++ b/src/settings/plugins/ifnet/tests/wpa_supplicant.conf
@@ -0,0 +1,864 @@
+##### Example wpa_supplicant configuration file ###############################
+#
+# This file describes configuration file format and lists all available option.
+# Please also take a look at simpler configuration examples in 'examples'
+# subdirectory.
+#
+# Empty lines and lines starting with # are ignored
+
+# NOTE! This file may contain password information and should probably be made
+# readable only by root user on multiuser systems.
+
+# Note: All file paths in this configuration file should use full (absolute,
+# not relative to working directory) path in order to allow working directory
+# to be changed. This can happen if wpa_supplicant is run in the background.
+
+# Whether to allow wpa_supplicant to update (overwrite) configuration
+#
+# This option can be used to allow wpa_supplicant to overwrite configuration
+# file whenever configuration is changed (e.g., new network block is added with
+# wpa_cli or wpa_gui, or a password is changed). This is required for
+# wpa_cli/wpa_gui to be able to store the configuration changes permanently.
+# Please note that overwriting configuration file will remove the comments from
+# it.
+#update_config=1
+
+# global configuration (shared by all network blocks)
+#
+# Parameters for the control interface. If this is specified, wpa_supplicant
+# will open a control interface that is available for external programs to
+# manage wpa_supplicant. The meaning of this string depends on which control
+# interface mechanism is used. For all cases, the existance of this parameter
+# in configuration is used to determine whether the control interface is
+# enabled.
+#
+# For UNIX domain sockets (default on Linux and BSD): This is a directory that
+# will be created for UNIX domain sockets for listening to requests from
+# external programs (CLI/GUI, etc.) for status information and configuration.
+# The socket file will be named based on the interface name, so multiple
+# wpa_supplicant processes can be run at the same time if more than one
+# interface is used.
+# /var/run/wpa_supplicant is the recommended directory for sockets and by
+# default, wpa_cli will use it when trying to connect with wpa_supplicant.
+#
+# Access control for the control interface can be configured by setting the
+# directory to allow only members of a group to use sockets. This way, it is
+# possible to run wpa_supplicant as root (since it needs to change network
+# configuration and open raw sockets) and still allow GUI/CLI components to be
+# run as non-root users. However, since the control interface can be used to
+# change the network configuration, this access needs to be protected in many
+# cases. By default, wpa_supplicant is configured to use gid 0 (root). If you
+# want to allow non-root users to use the control interface, add a new group
+# and change this value to match with that group. Add users that should have
+# control interface access to this group. If this variable is commented out or
+# not included in the configuration file, group will not be changed from the
+# value it got by default when the directory or socket was created.
+#
+# When configuring both the directory and group, use following format:
+# DIR=/var/run/wpa_supplicant GROUP=wheel
+# DIR=/var/run/wpa_supplicant GROUP=0
+# (group can be either group name or gid)
+#
+# For UDP connections (default on Windows): The value will be ignored. This
+# variable is just used to select that the control interface is to be created.
+# The value can be set to, e.g., udp (ctrl_interface=udp)
+#
+# For Windows Named Pipe: This value can be used to set the security descriptor
+# for controlling access to the control interface. Security descriptor can be
+# set using Security Descriptor String Format (see http://msdn.microsoft.com/
+# library/default.asp?url=/library/en-us/secauthz/security/
+# security_descriptor_string_format.asp). The descriptor string needs to be
+# prefixed with SDDL=. For example, ctrl_interface=SDDL=D: would set an empty
+# DACL (which will reject all connections). See README-Windows.txt for more
+# information about SDDL string format.
+#
+ctrl_interface=/var/run/wpa_supplicant
+
+# IEEE 802.1X/EAPOL version
+# wpa_supplicant is implemented based on IEEE Std 802.1X-2004 which defines
+# EAPOL version 2. However, there are many APs that do not handle the new
+# version number correctly (they seem to drop the frames completely). In order
+# to make wpa_supplicant interoperate with these APs, the version number is set
+# to 1 by default. This configuration value can be used to set it to the new
+# version (2).
+eapol_version=1
+
+# AP scanning/selection
+# By default, wpa_supplicant requests driver to perform AP scanning and then
+# uses the scan results to select a suitable AP. Another alternative is to
+# allow the driver to take care of AP scanning and selection and use
+# wpa_supplicant just to process EAPOL frames based on IEEE 802.11 association
+# information from the driver.
+# 1: wpa_supplicant initiates scanning and AP selection
+# 0: driver takes care of scanning, AP selection, and IEEE 802.11 association
+# parameters (e.g., WPA IE generation); this mode can also be used with
+# non-WPA drivers when using IEEE 802.1X mode; do not try to associate with
+# APs (i.e., external program needs to control association). This mode must
+# also be used when using wired Ethernet drivers.
+# 2: like 0, but associate with APs using security policy and SSID (but not
+# BSSID); this can be used, e.g., with ndiswrapper and NDIS drivers to
+# enable operation with hidden SSIDs and optimized roaming; in this mode,
+# the network blocks in the configuration file are tried one by one until
+# the driver reports successful association; each network block should have
+# explicit security policy (i.e., only one option in the lists) for
+# key_mgmt, pairwise, group, proto variables
+ap_scan=1
+
+# EAP fast re-authentication
+# By default, fast re-authentication is enabled for all EAP methods that
+# support it. This variable can be used to disable fast re-authentication.
+# Normally, there is no need to disable this.
+fast_reauth=1
+
+# OpenSSL Engine support
+# These options can be used to load OpenSSL engines.
+# The two engines that are supported currently are shown below:
+# They are both from the opensc project (http://www.opensc.org/)
+# By default no engines are loaded.
+# make the opensc engine available
+#opensc_engine_path=/usr/lib64/engine_opensc.so
+# make the pkcs11 engine available
+#pkcs11_engine_path=/usr/lib64/engine_pkcs11.so
+# configure the path to the pkcs11 module required by the pkcs11 engine
+#pkcs11_module_path=/usr/lib64/opensc-pkcs11.so
+
+# Dynamic EAP methods
+# If EAP methods were built dynamically as shared object files, they need to be
+# loaded here before being used in the network blocks. By default, EAP methods
+# are included statically in the build, so these lines are not needed
+#load_dynamic_eap=/usr/lib/wpa_supplicant/eap_tls.so
+#load_dynamic_eap=/usr/lib/wpa_supplicant/eap_md5.so
+
+# Driver interface parameters
+# This field can be used to configure arbitrary driver interace parameters. The
+# format is specific to the selected driver interface. This field is not used
+# in most cases.
+#driver_param="field=value"
+
+# Country code
+# The ISO/IEC alpha2 country code for the country in which this device is
+# currently operating.
+#country=US
+
+# Maximum lifetime for PMKSA in seconds; default 43200
+#dot11RSNAConfigPMKLifetime=43200
+# Threshold for reauthentication (percentage of PMK lifetime); default 70
+#dot11RSNAConfigPMKReauthThreshold=70
+# Timeout for security association negotiation in seconds; default 60
+#dot11RSNAConfigSATimeout=60
+
+# Wi-Fi Protected Setup (WPS) parameters
+
+# Universally Unique IDentifier (UUID; see RFC 4122) of the device
+# If not configured, UUID will be generated based on the local MAC address.
+#uuid=12345678-9abc-def0-1234-56789abcdef0
+
+# Device Name
+# User-friendly description of device; up to 32 octets encoded in UTF-8
+#device_name=Wireless Client
+
+# Manufacturer
+# The manufacturer of the device (up to 64 ASCII characters)
+#manufacturer=Company
+
+# Model Name
+# Model of the device (up to 32 ASCII characters)
+#model_name=cmodel
+
+# Model Number
+# Additional device description (up to 32 ASCII characters)
+#model_number=123
+
+# Serial Number
+# Serial number of the device (up to 32 characters)
+#serial_number=12345
+
+# Primary Device Type
+# Used format: <categ>-<OUI>-<subcateg>
+# categ = Category as an integer value
+# OUI = OUI and type octet as a 4-octet hex-encoded value; 0050F204 for
+# default WPS OUI
+# subcateg = OUI-specific Sub Category as an integer value
+# Examples:
+# 1-0050F204-1 (Computer / PC)
+# 1-0050F204-2 (Computer / Server)
+# 5-0050F204-1 (Storage / NAS)
+# 6-0050F204-1 (Network Infrastructure / AP)
+#device_type=1-0050F204-1
+
+# OS Version
+# 4-octet operating system version number (hex string)
+#os_version=01020300
+
+# Credential processing
+# 0 = process received credentials internally (default)
+# 1 = do not process received credentials; just pass them over ctrl_iface to
+# external program(s)
+# 2 = process received credentials internally and pass them over ctrl_iface
+# to external program(s)
+#wps_cred_processing=0
+
+# network block
+#
+# Each network (usually AP's sharing the same SSID) is configured as a separate
+# block in this configuration file. The network blocks are in preference order
+# (the first match is used).
+#
+# network block fields:
+#
+# disabled:
+# 0 = this network can be used (default)
+# 1 = this network block is disabled (can be enabled through ctrl_iface,
+# e.g., with wpa_cli or wpa_gui)
+#
+# id_str: Network identifier string for external scripts. This value is passed
+# to external action script through wpa_cli as WPA_ID_STR environment
+# variable to make it easier to do network specific configuration.
+#
+# ssid: SSID (mandatory); either as an ASCII string with double quotation or
+# as hex string; network name
+#
+# scan_ssid:
+# 0 = do not scan this SSID with specific Probe Request frames (default)
+# 1 = scan with SSID-specific Probe Request frames (this can be used to
+# find APs that do not accept broadcast SSID or use multiple SSIDs;
+# this will add latency to scanning, so enable this only when needed)
+#
+# bssid: BSSID (optional); if set, this network block is used only when
+# associating with the AP using the configured BSSID
+#
+# priority: priority group (integer)
+# By default, all networks will get same priority group (0). If some of the
+# networks are more desirable, this field can be used to change the order in
+# which wpa_supplicant goes through the networks when selecting a BSS. The
+# priority groups will be iterated in decreasing priority (i.e., the larger the
+# priority value, the sooner the network is matched against the scan results).
+# Within each priority group, networks will be selected based on security
+# policy, signal strength, etc.
+# Please note that AP scanning with scan_ssid=1 and ap_scan=2 mode are not
+# using this priority to select the order for scanning. Instead, they try the
+# networks in the order that used in the configuration file.
+#
+# mode: IEEE 802.11 operation mode
+# 0 = infrastructure (Managed) mode, i.e., associate with an AP (default)
+# 1 = IBSS (ad-hoc, peer-to-peer)
+# Note: IBSS can only be used with key_mgmt NONE (plaintext and static WEP)
+# and key_mgmt=WPA-NONE (fixed group key TKIP/CCMP). In addition, ap_scan has
+# to be set to 2 for IBSS. WPA-None requires following network block options:
+# proto=WPA, key_mgmt=WPA-NONE, pairwise=NONE, group=TKIP (or CCMP, but not
+# both), and psk must also be set.
+#
+# frequency: Channel frequency in megahertz (MHz) for IBSS, e.g.,
+# 2412 = IEEE 802.11b/g channel 1. This value is used to configure the initial
+# channel for IBSS (adhoc) networks. It is ignored in the infrastructure mode.
+# In addition, this value is only used by the station that creates the IBSS. If
+# an IBSS network with the configured SSID is already present, the frequency of
+# the network will be used instead of this configured value.
+#
+# proto: list of accepted protocols
+# WPA = WPA/IEEE 802.11i/D3.0
+# RSN = WPA2/IEEE 802.11i (also WPA2 can be used as an alias for RSN)
+# If not set, this defaults to: WPA RSN
+#
+# key_mgmt: list of accepted authenticated key management protocols
+# WPA-PSK = WPA pre-shared key (this requires 'psk' field)
+# WPA-EAP = WPA using EAP authentication
+# IEEE8021X = IEEE 802.1X using EAP authentication and (optionally) dynamically
+# generated WEP keys
+# NONE = WPA is not used; plaintext or static WEP could be used
+# WPA-PSK-SHA256 = Like WPA-PSK but using stronger SHA256-based algorithms
+# WPA-EAP-SHA256 = Like WPA-EAP but using stronger SHA256-based algorithms
+# If not set, this defaults to: WPA-PSK WPA-EAP
+#
+# auth_alg: list of allowed IEEE 802.11 authentication algorithms
+# OPEN = Open System authentication (required for WPA/WPA2)
+# SHARED = Shared Key authentication (requires static WEP keys)
+# LEAP = LEAP/Network EAP (only used with LEAP)
+# If not set, automatic selection is used (Open System with LEAP enabled if
+# LEAP is allowed as one of the EAP methods).
+#
+# pairwise: list of accepted pairwise (unicast) ciphers for WPA
+# CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0]
+# TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]
+# NONE = Use only Group Keys (deprecated, should not be included if APs support
+# pairwise keys)
+# If not set, this defaults to: CCMP TKIP
+#
+# group: list of accepted group (broadcast/multicast) ciphers for WPA
+# CCMP = AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0]
+# TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0]
+# WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key
+# WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key [IEEE 802.11]
+# If not set, this defaults to: CCMP TKIP WEP104 WEP40
+#
+# psk: WPA preshared key; 256-bit pre-shared key
+# The key used in WPA-PSK mode can be entered either as 64 hex-digits, i.e.,
+# 32 bytes or as an ASCII passphrase (in which case, the real PSK will be
+# generated using the passphrase and SSID). ASCII passphrase must be between
+# 8 and 63 characters (inclusive).
+# This field is not needed, if WPA-EAP is used.
+# Note: Separate tool, wpa_passphrase, can be used to generate 256-bit keys
+# from ASCII passphrase. This process uses lot of CPU and wpa_supplicant
+# startup and reconfiguration time can be optimized by generating the PSK only
+# only when the passphrase or SSID has actually changed.
+#
+# eapol_flags: IEEE 802.1X/EAPOL options (bit field)
+# Dynamic WEP key required for non-WPA mode
+# bit0 (1): require dynamically generated unicast WEP key
+# bit1 (2): require dynamically generated broadcast WEP key
+# (3 = require both keys; default)
+# Note: When using wired authentication, eapol_flags must be set to 0 for the
+# authentication to be completed successfully.
+#
+# mixed_cell: This option can be used to configure whether so called mixed
+# cells, i.e., networks that use both plaintext and encryption in the same
+# SSID, are allowed when selecting a BSS form scan results.
+# 0 = disabled (default)
+# 1 = enabled
+#
+# proactive_key_caching:
+# Enable/disable opportunistic PMKSA caching for WPA2.
+# 0 = disabled (default)
+# 1 = enabled
+#
+# wep_key0..3: Static WEP key (ASCII in double quotation, e.g. "abcde" or
+# hex without quotation, e.g., 0102030405)
+# wep_tx_keyidx: Default WEP key index (TX) (0..3)
+#
+# peerkey: Whether PeerKey negotiation for direct links (IEEE 802.11e DLS) is
+# allowed. This is only used with RSN/WPA2.
+# 0 = disabled (default)
+# 1 = enabled
+#peerkey=1
+#
+# wpa_ptk_rekey: Maximum lifetime for PTK in seconds. This can be used to
+# enforce rekeying of PTK to mitigate some attacks against TKIP deficiencies.
+#
+# Following fields are only used with internal EAP implementation.
+# eap: space-separated list of accepted EAP methods
+# MD5 = EAP-MD5 (unsecure and does not generate keying material ->
+# cannot be used with WPA; to be used as a Phase 2 method
+# with EAP-PEAP or EAP-TTLS)
+# MSCHAPV2 = EAP-MSCHAPv2 (cannot be used separately with WPA; to be used
+# as a Phase 2 method with EAP-PEAP or EAP-TTLS)
+# OTP = EAP-OTP (cannot be used separately with WPA; to be used
+# as a Phase 2 method with EAP-PEAP or EAP-TTLS)
+# GTC = EAP-GTC (cannot be used separately with WPA; to be used
+# as a Phase 2 method with EAP-PEAP or EAP-TTLS)
+# TLS = EAP-TLS (client and server certificate)
+# PEAP = EAP-PEAP (with tunnelled EAP authentication)
+# TTLS = EAP-TTLS (with tunnelled EAP or PAP/CHAP/MSCHAP/MSCHAPV2
+# authentication)
+# If not set, all compiled in methods are allowed.
+#
+# identity: Identity string for EAP
+# This field is also used to configure user NAI for
+# EAP-PSK/PAX/SAKE/GPSK.
+# anonymous_identity: Anonymous identity string for EAP (to be used as the
+# unencrypted identity with EAP types that support different tunnelled
+# identity, e.g., EAP-TTLS)
+# password: Password string for EAP. This field can include either the
+# plaintext password (using ASCII or hex string) or a NtPasswordHash
+# (16-byte MD4 hash of password) in hash:<32 hex digits> format.
+# NtPasswordHash can only be used when the password is for MSCHAPv2 or
+# MSCHAP (EAP-MSCHAPv2, EAP-TTLS/MSCHAPv2, EAP-TTLS/MSCHAP, LEAP).
+# EAP-PSK (128-bit PSK), EAP-PAX (128-bit PSK), and EAP-SAKE (256-bit
+# PSK) is also configured using this field. For EAP-GPSK, this is a
+# variable length PSK.
+# ca_cert: File path to CA certificate file (PEM/DER). This file can have one
+# or more trusted CA certificates. If ca_cert and ca_path are not
+# included, server certificate will not be verified. This is insecure and
+# a trusted CA certificate should always be configured when using
+# EAP-TLS/TTLS/PEAP. Full path should be used since working directory may
+# change when wpa_supplicant is run in the background.
+# On Windows, trusted CA certificates can be loaded from the system
+# certificate store by setting this to cert_store://<name>, e.g.,
+# ca_cert="cert_store://CA" or ca_cert="cert_store://ROOT".
+# Note that when running wpa_supplicant as an application, the user
+# certificate store (My user account) is used, whereas computer store
+# (Computer account) is used when running wpasvc as a service.
+# ca_path: Directory path for CA certificate files (PEM). This path may
+# contain multiple CA certificates in OpenSSL format. Common use for this
+# is to point to system trusted CA list which is often installed into
+# directory like /etc/ssl/certs. If configured, these certificates are
+# added to the list of trusted CAs. ca_cert may also be included in that
+# case, but it is not required.
+# client_cert: File path to client certificate file (PEM/DER)
+# Full path should be used since working directory may change when
+# wpa_supplicant is run in the background.
+# Alternatively, a named configuration blob can be used by setting this
+# to blob://<blob name>.
+# private_key: File path to client private key file (PEM/DER/PFX)
+# When PKCS#12/PFX file (.p12/.pfx) is used, client_cert should be
+# commented out. Both the private key and certificate will be read from
+# the PKCS#12 file in this case. Full path should be used since working
+# directory may change when wpa_supplicant is run in the background.
+# Windows certificate store can be used by leaving client_cert out and
+# configuring private_key in one of the following formats:
+# cert://substring_to_match
+# hash://certificate_thumbprint_in_hex
+# for example: private_key="hash://63093aa9c47f56ae88334c7b65a4"
+# Note that when running wpa_supplicant as an application, the user
+# certificate store (My user account) is used, whereas computer store
+# (Computer account) is used when running wpasvc as a service.
+# Alternatively, a named configuration blob can be used by setting this
+# to blob://<blob name>.
+# private_key_passwd: Password for private key file (if left out, this will be
+# asked through control interface)
+# dh_file: File path to DH/DSA parameters file (in PEM format)
+# This is an optional configuration file for setting parameters for an
+# ephemeral DH key exchange. In most cases, the default RSA
+# authentication does not use this configuration. However, it is possible
+# setup RSA to use ephemeral DH key exchange. In addition, ciphers with
+# DSA keys always use ephemeral DH keys. This can be used to achieve
+# forward secrecy. If the file is in DSA parameters format, it will be
+# automatically converted into DH params.
+# subject_match: Substring to be matched against the subject of the
+# authentication server certificate. If this string is set, the server
+# sertificate is only accepted if it contains this string in the subject.
+# The subject string is in following format:
+# /C=US/ST=CA/L=San Francisco/CN=Test AS/emailAddress=as@example.com
+# altsubject_match: Semicolon separated string of entries to be matched against
+# the alternative subject name of the authentication server certificate.
+# If this string is set, the server sertificate is only accepted if it
+# contains one of the entries in an alternative subject name extension.
+# altSubjectName string is in following format: TYPE:VALUE
+# Example: EMAIL:server@example.com
+# Example: DNS:server.example.com;DNS:server2.example.com
+# Following types are supported: EMAIL, DNS, URI
+# phase1: Phase1 (outer authentication, i.e., TLS tunnel) parameters
+# (string with field-value pairs, e.g., "peapver=0" or
+# "peapver=1 peaplabel=1")
+# 'peapver' can be used to force which PEAP version (0 or 1) is used.
+# 'peaplabel=1' can be used to force new label, "client PEAP encryption",
+# to be used during key derivation when PEAPv1 or newer. Most existing
+# PEAPv1 implementation seem to be using the old label, "client EAP
+# encryption", and wpa_supplicant is now using that as the default value.
+# Some servers, e.g., Radiator, may require peaplabel=1 configuration to
+# interoperate with PEAPv1; see eap_testing.txt for more details.
+# 'peap_outer_success=0' can be used to terminate PEAP authentication on
+# tunneled EAP-Success. This is required with some RADIUS servers that
+# implement draft-josefsson-pppext-eap-tls-eap-05.txt (e.g.,
+# Lucent NavisRadius v4.4.0 with PEAP in "IETF Draft 5" mode)
+# include_tls_length=1 can be used to force wpa_supplicant to include
+# TLS Message Length field in all TLS messages even if they are not
+# fragmented.
+# sim_min_num_chal=3 can be used to configure EAP-SIM to require three
+# challenges (by default, it accepts 2 or 3)
+# result_ind=1 can be used to enable EAP-SIM and EAP-AKA to use
+# protected result indication.
+# 'crypto_binding' option can be used to control PEAPv0 cryptobinding
+# behavior:
+# * 0 = do not use cryptobinding (default)
+# * 1 = use cryptobinding if server supports it
+# * 2 = require cryptobinding
+# EAP-WSC (WPS) uses following options: pin=<Device Password> or
+# pbc=1.
+# phase2: Phase2 (inner authentication with TLS tunnel) parameters
+# (string with field-value pairs, e.g., "auth=MSCHAPV2" for EAP-PEAP or
+# "autheap=MSCHAPV2 autheap=MD5" for EAP-TTLS)
+# Following certificate/private key fields are used in inner Phase2
+# authentication when using EAP-TTLS or EAP-PEAP.
+# ca_cert2: File path to CA certificate file. This file can have one or more
+# trusted CA certificates. If ca_cert2 and ca_path2 are not included,
+# server certificate will not be verified. This is insecure and a trusted
+# CA certificate should always be configured.
+# ca_path2: Directory path for CA certificate files (PEM)
+# client_cert2: File path to client certificate file
+# private_key2: File path to client private key file
+# private_key2_passwd: Password for private key file
+# dh_file2: File path to DH/DSA parameters file (in PEM format)
+# subject_match2: Substring to be matched against the subject of the
+# authentication server certificate.
+# altsubject_match2: Substring to be matched against the alternative subject
+# name of the authentication server certificate.
+#
+# fragment_size: Maximum EAP fragment size in bytes (default 1398).
+# This value limits the fragment size for EAP methods that support
+# fragmentation (e.g., EAP-TLS and EAP-PEAP). This value should be set
+# small enough to make the EAP messages fit in MTU of the network
+# interface used for EAPOL. The default value is suitable for most
+# cases.
+#
+# EAP-FAST variables:
+# pac_file: File path for the PAC entries. wpa_supplicant will need to be able
+# to create this file and write updates to it when PAC is being
+# provisioned or refreshed. Full path to the file should be used since
+# working directory may change when wpa_supplicant is run in the
+# background. Alternatively, a named configuration blob can be used by
+# setting this to blob://<blob name>
+# phase1: fast_provisioning option can be used to enable in-line provisioning
+# of EAP-FAST credentials (PAC):
+# 0 = disabled,
+# 1 = allow unauthenticated provisioning,
+# 2 = allow authenticated provisioning,
+# 3 = allow both unauthenticated and authenticated provisioning
+# fast_max_pac_list_len=<num> option can be used to set the maximum
+# number of PAC entries to store in a PAC list (default: 10)
+# fast_pac_format=binary option can be used to select binary format for
+# storing PAC entries in order to save some space (the default
+# text format uses about 2.5 times the size of minimal binary
+# format)
+#
+# wpa_supplicant supports number of "EAP workarounds" to work around
+# interoperability issues with incorrectly behaving authentication servers.
+# These are enabled by default because some of the issues are present in large
+# number of authentication servers. Strict EAP conformance mode can be
+# configured by disabling workarounds with eap_workaround=0.
+
+# Example blocks:
+
+# Simple case: WPA-PSK, PSK as an ASCII passphrase, allow all valid ciphers
+network={
+ ssid="simple"
+ psk="very secret passphrase"
+ priority=5
+}
+
+# Same as previous, but request SSID-specific scanning (for APs that reject
+# broadcast SSID)
+network={
+ ssid="second ssid"
+ scan_ssid=1
+ psk="very secret passphrase"
+ priority=2
+}
+
+# Only WPA-PSK is used. Any valid cipher combination is accepted.
+network={
+ ssid="example"
+ proto=WPA
+ key_mgmt=WPA-PSK
+ pairwise=CCMP TKIP
+ group=CCMP TKIP WEP104 WEP40
+ psk=06b4be19da289f475aa46a33cb793029d4ab3db7a23ee92382eb0106c72ac7bb
+ priority=2
+}
+
+# WPA-Personal(PSK) with TKIP and enforcement for frequent PTK rekeying
+network={
+ ssid="example"
+ proto=WPA
+ key_mgmt=WPA-PSK
+ pairwise=TKIP
+ group=TKIP
+ psk="not so secure passphrase"
+ wpa_ptk_rekey=600
+}
+
+# Only WPA-EAP is used. Both CCMP and TKIP is accepted. An AP that used WEP104
+# or WEP40 as the group cipher will not be accepted.
+network={
+ ssid="example"
+ proto=RSN
+ key_mgmt=WPA-EAP
+ pairwise=CCMP TKIP
+ group=CCMP TKIP
+ eap=TLS
+ identity="user@example.com"
+ ca_cert="/etc/cert/ca.pem"
+ client_cert="/etc/cert/user.pem"
+ private_key="/etc/cert/user.prv"
+ private_key_passwd="password"
+ priority=1
+}
+
+# EAP-PEAP/MSCHAPv2 configuration for RADIUS servers that use the new peaplabel
+# (e.g., Radiator)
+network={
+ ssid="example"
+ key_mgmt=WPA-EAP
+ eap=PEAP
+ identity="user@example.com"
+ password="foobar"
+ ca_cert="/etc/cert/ca.pem"
+ phase1="peaplabel=1"
+ phase2="auth=MSCHAPV2"
+ priority=10
+}
+
+# EAP-TTLS/EAP-MD5-Challenge configuration with anonymous identity for the
+# unencrypted use. Real identity is sent only within an encrypted TLS tunnel.
+network={
+ ssid="example"
+ key_mgmt=WPA-EAP
+ eap=TTLS
+ identity="user@example.com"
+ anonymous_identity="anonymous@example.com"
+ password="foobar"
+ ca_cert="/etc/cert/ca.pem"
+ priority=2
+}
+
+# EAP-TTLS/MSCHAPv2 configuration with anonymous identity for the unencrypted
+# use. Real identity is sent only within an encrypted TLS tunnel.
+network={
+ ssid="example"
+ key_mgmt=WPA-EAP
+ eap=TTLS
+ identity="user@example.com"
+ anonymous_identity="anonymous@example.com"
+ password="foobar"
+ ca_cert="/etc/cert/ca.pem"
+ phase2="auth=MSCHAPV2"
+}
+
+# WPA-EAP, EAP-TTLS with different CA certificate used for outer and inner
+# authentication.
+network={
+ ssid="example"
+ key_mgmt=WPA-EAP
+ eap=TTLS
+ # Phase1 / outer authentication
+ anonymous_identity="anonymous@example.com"
+ ca_cert="/etc/cert/ca.pem"
+ # Phase 2 / inner authentication
+ phase2="autheap=TLS"
+ ca_cert2="/etc/cert/ca2.pem"
+ client_cert2="/etc/cer/user.pem"
+ private_key2="/etc/cer/user.prv"
+ private_key2_passwd="password"
+ priority=2
+}
+
+# Both WPA-PSK and WPA-EAP is accepted. Only CCMP is accepted as pairwise and
+# group cipher.
+network={
+ ssid="example"
+ bssid=00:11:22:33:44:55
+ proto=WPA RSN
+ key_mgmt=WPA-PSK WPA-EAP
+ pairwise=CCMP
+ group=CCMP
+ psk=06b4be19da289f475aa46a33cb793029d4ab3db7a23ee92382eb0106c72ac7bb
+}
+
+# Special characters in SSID, so use hex string. Default to WPA-PSK, WPA-EAP
+# and all valid ciphers.
+network={
+ ssid=00010203
+ psk=000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+}
+
+
+# EAP-SIM with a GSM SIM or USIM
+network={
+ ssid="eap-sim-test"
+ key_mgmt=WPA-EAP
+ eap=SIM
+ pin="1234"
+ pcsc=""
+}
+
+
+# EAP-PSK
+network={
+ ssid="eap-psk-test"
+ key_mgmt=WPA-EAP
+ eap=PSK
+ anonymous_identity="eap_psk_user"
+ password=06b4be19da289f475aa46a33cb793029
+ identity="eap_psk_user@example.com"
+}
+
+
+# IEEE 802.1X/EAPOL with dynamically generated WEP keys (i.e., no WPA) using
+# EAP-TLS for authentication and key generation; require both unicast and
+# broadcast WEP keys.
+network={
+ ssid="1xtest"
+ key_mgmt=IEEE8021X
+ eap=TLS
+ identity="user@example.com"
+ ca_cert="/etc/cert/ca.pem"
+ client_cert="/etc/cert/user.pem"
+ private_key="/etc/cert/user.prv"
+ private_key_passwd="password"
+ eapol_flags=3
+}
+
+
+# LEAP with dynamic WEP keys
+network={
+ ssid="leap-example"
+ key_mgmt=IEEE8021X
+ eap=LEAP
+ identity="user"
+ password="foobar"
+}
+
+# EAP-IKEv2 using shared secrets for both server and peer authentication
+network={
+ ssid="ikev2-example"
+ key_mgmt=WPA-EAP
+ eap=IKEV2
+ identity="user"
+ password="foobar"
+}
+
+# EAP-FAST with WPA (WPA or WPA2)
+network={
+ ssid="eap-fast-test"
+ key_mgmt=WPA-EAP
+ eap=FAST
+ anonymous_identity="FAST-000102030405"
+ identity="username"
+ password="password"
+ phase1="fast_provisioning=1"
+ pac_file="/etc/wpa_supplicant.eap-fast-pac"
+}
+
+network={
+ ssid="eap-fast-test"
+ key_mgmt=WPA-EAP
+ eap=FAST
+ anonymous_identity="FAST-000102030405"
+ identity="username"
+ password="password"
+ phase1="fast_provisioning=1"
+ pac_file="blob://eap-fast-pac"
+}
+
+# Plaintext connection (no WPA, no IEEE 802.1X)
+network={
+ ssid="plaintext-test"
+ key_mgmt=NONE
+}
+
+
+# Shared WEP key connection (no WPA, no IEEE 802.1X)
+network={
+ ssid="static-wep-test"
+ key_mgmt=NONE
+ wep_key0="abcde"
+ wep_key1=0102030405
+ wep_key2="1234567890123"
+ wep_tx_keyidx=0
+ priority=5
+}
+
+
+# Shared WEP key connection (no WPA, no IEEE 802.1X) using Shared Key
+# IEEE 802.11 authentication
+network={
+ ssid="static-wep-test2"
+ key_mgmt=NONE
+ wep_key0="abcde"
+ wep_key1=0102030405
+ wep_key2="1234567890123"
+ wep_tx_keyidx=0
+ priority=5
+ auth_alg=SHARED
+}
+
+
+# IBSS/ad-hoc network with WPA-None/TKIP.
+network={
+ ssid="test adhoc"
+ mode=1
+ frequency=2412
+ proto=WPA
+ key_mgmt=WPA-NONE
+ pairwise=NONE
+ group=TKIP
+ psk="secret passphrase"
+}
+
+
+# Catch all example that allows more or less all configuration modes
+network={
+ ssid="example"
+ scan_ssid=1
+ key_mgmt=WPA-EAP WPA-PSK IEEE8021X NONE
+ pairwise=CCMP TKIP
+ group=CCMP TKIP WEP104 WEP40
+ psk="very secret passphrase"
+ eap=TTLS PEAP TLS
+ identity="user@example.com"
+ password="foobar"
+ ca_cert="/etc/cert/ca.pem"
+ client_cert="/etc/cert/user.pem"
+ private_key="/etc/cert/user.prv"
+ private_key_passwd="password"
+ phase1="peaplabel=0"
+}
+
+# Example of EAP-TLS with smartcard (openssl engine)
+network={
+ ssid="example"
+ key_mgmt=WPA-EAP
+ eap=TLS
+ proto=RSN
+ pairwise=CCMP TKIP
+ group=CCMP TKIP
+ identity="user@example.com"
+ ca_cert="/etc/cert/ca.pem"
+ client_cert="/etc/cert/user.pem"
+
+ engine=1
+
+ # The engine configured here must be available. Look at
+ # OpenSSL engine support in the global section.
+ # The key available through the engine must be the private key
+ # matching the client certificate configured above.
+
+ # use the opensc engine
+ #engine_id="opensc"
+ #key_id="45"
+
+ # use the pkcs11 engine
+ engine_id="pkcs11"
+ key_id="id_45"
+
+ # Optional PIN configuration; this can be left out and PIN will be
+ # asked through the control interface
+ pin="1234"
+}
+
+# Example configuration showing how to use an inlined blob as a CA certificate
+# data instead of using external file
+network={
+ ssid="example"
+ key_mgmt=WPA-EAP
+ eap=TTLS
+ identity="user@example.com"
+ anonymous_identity="anonymous@example.com"
+ password="foobar"
+ ca_cert="blob://exampleblob"
+ priority=20
+}
+
+blob-base64-exampleblob={
+SGVsbG8gV29ybGQhCg==
+}
+
+
+# Wildcard match for SSID (plaintext APs only). This example select any
+# open AP regardless of its SSID.
+network={
+ key_mgmt=NONE
+}
+network={
+ ssid="myxjtu2"
+ scan_ssid=1
+ key_mgmt=WPA-PSK
+ psk="xjtudlc3731"
+ disabled=0
+ key_mgmt=NONE
+ wep_key0="12345"
+ wep_key1=1234567890
+ wep_key2="zxcvb"
+ wep_tx_keyidx=1
+ auth_alg=OPEN
+ mode=1
+}
+network={
+ ssid=ab3ace
+ key_mgmt=WPA-EAP
+ eap=TTLS
+ identity="user@example.com"
+ anonymous_identity="anonymous@example.com"
+ password="foobar"
+ ca_cert="blob://exampleblob"
+ priority=20
+}
diff --git a/src/settings/plugins/ifnet/wpa_parser.c b/src/settings/plugins/ifnet/wpa_parser.c
new file mode 100644
index 000000000..da2bc3bb9
--- /dev/null
+++ b/src/settings/plugins/ifnet/wpa_parser.c
@@ -0,0 +1,566 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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 (C) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <nm-system-config-interface.h>
+#include "wpa_parser.h"
+#include "net_parser.h"
+#include "net_utils.h"
+
+/* Security information */
+static GHashTable *wsec_table = NULL;
+
+/* Global information used for writing */
+static GHashTable *wsec_global_table = NULL;
+
+static gboolean wpa_parser_data_changed = FALSE;
+
+static long
+wpa_get_long (GHashTable *table, const char *key)
+{
+ return atol (g_hash_table_lookup (table, key));
+}
+
+static void
+destroy_security (GHashTable * network)
+{
+ gpointer key, value;
+ GHashTableIter iter;
+
+ g_return_if_fail (network);
+ g_hash_table_iter_init (&iter, network);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ g_free (key);
+ g_free (value);
+ }
+
+ g_hash_table_destroy (network);
+}
+
+static GHashTable *
+add_security (GHashTable *security)
+{
+ GHashTable *oldsecurity;
+ const char *ssid, *value;
+ char *ssid_key;
+ gboolean is_hex_ssid;
+
+ /* Every security information should have a ssid */
+ ssid = g_hash_table_lookup (security, "ssid");
+ if (!ssid) {
+ destroy_security (security);
+ return NULL;
+ }
+
+ /* Hex format begins with " */
+ is_hex_ssid = (ssid[0] != '"');
+ if ((value = g_hash_table_lookup (security, "disabled")) != NULL) {
+ if (strcmp (value, "1") == 0)
+ return NULL;
+ }
+
+ /* Default priority is 1 */
+ if (g_hash_table_lookup (security, "priority") == NULL)
+ g_hash_table_insert (security, g_strdup ("priority"),
+ g_strdup ("1"));
+
+ oldsecurity = g_hash_table_lookup (wsec_table, ssid);
+ /* Security with lower priority will be ignored */
+ if (oldsecurity != NULL) {
+ if (wpa_get_long (oldsecurity, "priority") >=
+ wpa_get_long (security, "priority")) {
+ destroy_security (security);
+ return NULL;
+ } else {
+ g_hash_table_remove (wsec_table, ssid);
+ destroy_security (oldsecurity);
+ }
+ }
+
+ /* format ssid */
+ ssid_key =
+ is_hex_ssid ? g_strdup_printf ("0x%s",
+ ssid) :
+ strip_string (g_strdup (ssid), '"');
+ g_hash_table_insert (wsec_table, ssid_key, security);
+ return security;
+}
+
+static void
+add_key_value (GHashTable * network, gchar * line)
+{
+ gchar **key_value;
+
+ if (g_str_has_prefix (line, "network={"))
+ line += 9;
+ strip_string (line, '{');
+ strip_string (line, '}');
+ if (line[0] == '\0')
+ return;
+ key_value = g_strsplit (line, "=", 2);
+ if (g_strv_length (key_value) != 2) {
+ g_strfreev (key_value);
+ return;
+ }
+ g_strstrip (key_value[0]);
+ g_strstrip (key_value[1]);
+
+ /* Reserve quotes for psk, wep_key, ssid
+ * Quotes will determine whether they are hex format */
+ if (strcmp (key_value[0], "psk") != 0
+ && !g_str_has_prefix (key_value[0], "wep_key")
+ && strcmp (key_value[0], "ssid") != 0)
+ strip_string (key_value[1], '"');
+ g_hash_table_insert (network, g_strdup (key_value[0]),
+ g_strdup (key_value[1]));
+ g_strfreev (key_value);
+}
+
+static void
+add_one_wep_key (GHashTable * table, int key_num, gchar * one_wep_key)
+{
+ if (one_wep_key[0] == 's') {
+ //asc key
+ g_hash_table_insert (table,
+ g_strdup_printf ("wep_key%d", key_num - 1),
+ g_strdup_printf ("\"%s\"",
+ one_wep_key + 2));
+ } else {
+ gchar buf[30];
+ int i = 0, j = 0;
+
+ //hex key
+ while (one_wep_key[i] != '\0') {
+ if (one_wep_key[i] != '-')
+ buf[j++] = one_wep_key[i];
+ i++;
+ }
+ buf[j] = '\0';
+ g_hash_table_insert (table,
+ g_strdup_printf ("wep_key%d", key_num - 1),
+ g_strdup (buf));
+
+ }
+}
+
+/* Reading wep security information from /etc/conf.d/net.
+ * This should not be used in futre, use wpa_supplicant instead. */
+static void
+add_keys_from_net ()
+{
+ GList *names = ifnet_get_connection_names ();
+ GList *iter = names;
+ gchar *wep_keys = "(\\[([1-4])\\]\\s+(s:\\w{5}|s:\\w{13}|"
+ "([\\da-fA-F]{4}\\-){2}[\\da-fA-F]{2}|"
+ "([\\da-fA-F]{4}\\-){6}[\\da-fA-F]{2})\\s+)";
+ gchar *key_method =
+ "\\s+key\\s+\\[([1-4])\\]\\s+enc\\s+(open|restricted)";
+ GRegex *regex_keys = g_regex_new (wep_keys, 0, 0, NULL);
+ GRegex *regex_method = g_regex_new (key_method, 0, 0, NULL);
+ GMatchInfo *keys_info;
+ GMatchInfo *method_info;
+
+ while (iter) {
+ gchar *conn_name = iter->data;
+ GHashTable *table;
+ const char *key_str;
+
+ if ((key_str = ifnet_get_data (conn_name, "key")) == NULL) {
+ iter = g_list_next (iter);
+ continue;
+ }
+
+ wpa_add_security (conn_name);
+ table = _get_hash_table (conn_name);
+ /* Give lowest priority */
+ wpa_set_data (conn_name, "priority", "0");
+ g_regex_match (regex_keys, key_str, 0, &keys_info);
+ /* add wep keys */
+ while (g_match_info_matches (keys_info)) {
+ gchar *key_num = g_match_info_fetch (keys_info, 2);
+ gchar *one_wep_key = g_match_info_fetch (keys_info, 3);
+
+ add_one_wep_key (table, atoi (key_num), one_wep_key);
+ g_free (key_num);
+ g_free (one_wep_key);
+ g_match_info_next (keys_info, NULL);
+ }
+ g_match_info_free (keys_info);
+
+ g_regex_match (regex_method, key_str, 0, &method_info);
+ /* set default key index and auth alg */
+ if (g_match_info_matches (method_info)) {
+ gchar *default_idx =
+ g_match_info_fetch (method_info, 1);
+ gchar *method = g_match_info_fetch (method_info, 2);
+
+ default_idx[0]--;
+ g_hash_table_insert (table, g_strdup ("wep_tx_keyidx"),
+ default_idx);
+ g_hash_table_insert (table, g_strdup ("auth_alg"),
+ g_ascii_strup (method, -1));
+ }
+ g_match_info_free (method_info);
+ add_security (table);
+ iter = g_list_next (iter);
+ }
+ g_list_free (names);
+ g_regex_unref (regex_keys);
+ g_regex_unref (regex_method);
+}
+
+static void
+add_global_data (gchar * line)
+{
+ gchar **key_value;
+
+ g_strstrip (line);
+ key_value = g_strsplit (line, "=", 2);
+ if (g_strv_length (key_value) != 2) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME, "Can't handle this line: %s\n",
+ line);
+ g_strfreev (key_value);
+ return;
+ }
+ g_hash_table_insert (wsec_global_table,
+ g_strdup (g_strstrip (key_value[0])),
+ g_strdup (g_strstrip (key_value[1])));
+ g_strfreev (key_value);
+}
+
+void
+wpa_parser_init (const char *wpa_supplicant_conf)
+{
+ GIOChannel *channel = NULL;
+ gchar *line;
+ gboolean complete = FALSE;
+
+ wpa_parser_data_changed = FALSE;
+ wsec_table = g_hash_table_new (g_str_hash, g_str_equal);
+ wsec_global_table = g_hash_table_new (g_str_hash, g_str_equal);
+
+ if (g_file_test (wpa_supplicant_conf, G_FILE_TEST_IS_REGULAR))
+ channel =
+ g_io_channel_new_file (wpa_supplicant_conf, "r", NULL);
+ if (channel == NULL) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "Can't open %s for wireless security",
+ wpa_supplicant_conf);
+ return;
+ }
+
+ while (g_io_channel_read_line (channel, &line, NULL, NULL, NULL)
+ != G_IO_STATUS_EOF) {
+ g_strstrip (line);
+ if (line[0] != '#' && line[0] != '\0') {
+ if (strstr (line, "network={") == NULL) {
+ add_global_data (line);
+ g_free (line);
+ continue;
+ } else {
+ GHashTable *network =
+ g_hash_table_new (g_str_hash, g_str_equal);
+ gchar *tmp;
+
+ do {
+ if (line[0] == '#' || line[0] == '\0') {
+ g_free (line);
+ continue;
+ }
+ /* ignore inline comments */
+ if ((tmp = strchr (line, '#')) != NULL)
+ *tmp = '\0';
+ if (strstr (line, "}") != NULL)
+ complete = TRUE;
+ add_key_value (network, line);
+ g_free (line);
+ } while (complete == FALSE
+ &&
+ g_io_channel_read_line
+ (channel, &line, NULL,
+ NULL, NULL) != G_IO_STATUS_EOF);
+ add_security (network);
+ //EOF in inner loop
+ if (complete == FALSE) {
+ g_free (line);
+ break;
+ }
+ complete = FALSE;
+ }
+ } else
+ g_free (line);
+ }
+
+ g_io_channel_shutdown (channel, FALSE, NULL);
+ g_io_channel_unref (channel);
+
+ add_keys_from_net ();
+}
+
+const char *
+wpa_get_value (const char *ssid, const char *key)
+{
+ GHashTable *target = g_hash_table_lookup (wsec_table, ssid);
+
+ if (target)
+ return g_hash_table_lookup (target, key);
+ return NULL;
+}
+
+gboolean
+exist_ssid (const char *ssid)
+{
+ return g_hash_table_lookup (wsec_table, ssid) != NULL;
+}
+
+GHashTable *
+_get_hash_table (const char *ssid)
+{
+ return g_hash_table_lookup (wsec_table, ssid);
+}
+
+static gchar *quoted_keys[] =
+ { "identity", "cert", "private", "phase", "password", NULL };
+
+/* tell whether the key needs quotes when writing is performed */
+static gboolean
+need_quote (gchar * key)
+{
+ int i = 0;
+
+ while (quoted_keys[i] != NULL) {
+ if (strstr (key, quoted_keys[i]))
+ return TRUE;
+ i++;
+ }
+ return FALSE;
+}
+
+gboolean
+wpa_flush_to_file (const char *config_file)
+{
+ GIOChannel *channel;
+ GError **error = NULL;
+ gpointer key, value, ssid, security;
+ GHashTableIter iter, iter_security;
+ gchar *out_line;
+ gsize bytes_written;
+ gboolean result = FALSE;
+
+ if (!wpa_parser_data_changed)
+ return TRUE;
+ if (!wsec_table || !wsec_global_table)
+ return FALSE;
+
+ channel = g_io_channel_new_file (config_file, "w", NULL);
+ if (!channel) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME,
+ "Can't open file %s for writing", config_file);
+ return FALSE;
+ }
+ g_hash_table_iter_init (&iter, wsec_global_table);
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Writing to %s", config_file);
+ g_io_channel_write_chars (channel,
+ "#Generated by NetworkManager\n"
+ "###### Global Configuration ######\n",
+ -1, &bytes_written, error);
+
+ /* Writing global information */
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ out_line =
+ g_strdup_printf ("%s=%s\n", (gchar *) key, (gchar *) value);
+ g_io_channel_write_chars (channel, out_line, -1, &bytes_written,
+ error);
+ if (bytes_written == 0 || (error && *error))
+ break;
+ g_free (out_line);
+ }
+ if (error && *error) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME, "Found error: %s",
+ (*error)->message);
+ goto done;
+ }
+ g_io_channel_write_chars (channel,
+ "\n###### Security Configuration ######\n",
+ -1, &bytes_written, error);
+
+ g_hash_table_iter_init (&iter, wsec_table);
+ /* Writing security */
+ while (g_hash_table_iter_next (&iter, &ssid, &security)) {
+ g_hash_table_iter_init (&iter_security,
+ (GHashTable *) security);
+ g_io_channel_write_chars (channel, "network={\n", -1,
+ &bytes_written, error);
+ while (g_hash_table_iter_next (&iter_security, &key, &value)) {
+ out_line =
+ g_strdup_printf (need_quote ((gchar *) key) ?
+ "\t%s=\"%s\"\n" : "\t%s=%s\n",
+ (gchar *) key, (gchar *) value);
+ g_io_channel_write_chars (channel, out_line, -1,
+ &bytes_written, error);
+ if (bytes_written == 0 || (error && *error))
+ break;
+ g_free (out_line);
+ }
+ g_io_channel_write_chars (channel,
+ "}\n\n", -1, &bytes_written, error);
+
+ }
+ if (error && *error) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME, "Found error: %s",
+ (*error)->message);
+ goto done;
+ }
+ g_io_channel_flush (channel, error);
+
+ if (error && *error) {
+ PLUGIN_WARN (IFNET_PLUGIN_NAME, "Found error: %s",
+ (*error)->message);
+ goto done;
+ }
+ wpa_parser_data_changed = FALSE;
+ result = TRUE;
+done:
+ g_io_channel_shutdown (channel, FALSE, NULL);
+ g_io_channel_unref (channel);
+ return result;
+}
+
+/* If value is NULL, this method will delete old key value pair */
+void
+wpa_set_data (const char *ssid, const char *key, const char *value)
+{
+ gpointer old_key = NULL, old_value = NULL;
+ GHashTable *security = g_hash_table_lookup (wsec_table, ssid);
+ gchar * stripped = NULL;
+
+ g_return_if_fail (security != NULL);
+
+ if (value){
+ stripped = g_strdup(value);
+ if (strcmp (key, "ssid") != 0 && strcmp (key, "psk") != 0
+ && !g_str_has_prefix (key, "wep_key"))
+ strip_string (stripped, '"');
+ }
+
+ /* Remove old key value pairs */
+ if (g_hash_table_lookup_extended
+ (security, key, &old_key, &old_value)) {
+ if (stripped && !strcmp(old_value, stripped)){
+ g_free (stripped);
+ return;
+ }
+ g_hash_table_remove (security, old_key);
+ g_free (old_key);
+ g_free (old_value);
+ } else if (!value)
+ return;
+
+ /* Add new key value */
+ if (stripped)
+ g_hash_table_insert (security, g_strdup (key), stripped);
+ wpa_parser_data_changed = TRUE;
+}
+
+gboolean
+wpa_has_security (const char *ssid)
+{
+ return g_hash_table_lookup (wsec_table, ssid) != NULL;
+}
+
+gboolean
+wpa_add_security (const char *ssid)
+{
+ if (wpa_has_security (ssid))
+ return TRUE;
+ else {
+ GHashTable *security =
+ g_hash_table_new (g_str_hash, g_str_equal);
+ gchar *ssid_i;
+
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Adding security for %s",
+ ssid);
+ if (g_str_has_prefix (ssid, "0x")) {
+ /* hex ssid */
+ ssid_i = g_strdup (ssid + 2);
+ } else {
+ /* ascii ssid requires quotes */
+ ssid_i = g_strdup_printf ("\"%s\"", ssid);
+ }
+ g_hash_table_insert (security, strdup ("ssid"), ssid_i);
+ g_hash_table_insert (security, strdup ("priority"),
+ strdup ("1"));
+ g_hash_table_insert (wsec_table, g_strdup (ssid), security);
+ wpa_parser_data_changed = TRUE;
+ return TRUE;
+ }
+}
+
+gboolean
+wpa_delete_security (const char *ssid)
+{
+ gpointer old_key, old_value;
+
+ g_return_val_if_fail (wsec_table != NULL && ssid != NULL, FALSE);
+ PLUGIN_PRINT (IFNET_PLUGIN_NAME, "Deleting security for %s", ssid);
+ if (!g_hash_table_lookup_extended
+ (wsec_table, ssid, &old_key, &old_value))
+ return FALSE;
+ g_hash_table_remove (wsec_table, old_key);
+ g_free (old_key);
+ destroy_security ((GHashTable *) old_value);
+ wpa_parser_data_changed = TRUE;
+ return TRUE;
+
+}
+
+void
+wpa_parser_destroy (void)
+{
+ GHashTableIter iter;
+ gpointer key;
+ gpointer value;
+
+ /* Destroy security */
+ if (wsec_table) {
+ g_hash_table_iter_init (&iter, wsec_table);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ destroy_security ((GHashTable *) value);
+ g_free (key);
+ }
+
+ g_hash_table_destroy (wsec_table);
+ wsec_table = NULL;
+ }
+
+ /* Destroy global data */
+ if (wsec_global_table) {
+ g_hash_table_iter_init (&iter, wsec_global_table);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ g_free (key);
+ g_free (value);
+ }
+
+ g_hash_table_destroy (wsec_global_table);
+ wsec_global_table = NULL;
+ }
+}
diff --git a/src/settings/plugins/ifnet/wpa_parser.h b/src/settings/plugins/ifnet/wpa_parser.h
new file mode 100644
index 000000000..7fd77a056
--- /dev/null
+++ b/src/settings/plugins/ifnet/wpa_parser.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/*
+ * Mu Qiao <qiaomuf@gmail.com>
+ *
+ * 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 (C) 1999-2010 Gentoo Foundation, Inc.
+ */
+
+#ifndef _WPA_PARSER_H
+#define _WPA_PARSER_H
+#define WPA_SUPPLICANT_CONF "/etc/wpa_supplicant/wpa_supplicant.conf"
+#include <glib.h>
+void wpa_parser_init (const char *wpa_supplicant_conf);
+void wpa_parser_destroy (void);
+
+/* reader functions */
+const char *wpa_get_value (const char *ssid, const char *key);
+gboolean exist_ssid (const char *ssid);
+GHashTable *_get_hash_table (const char *ssid);
+gboolean wpa_has_security (const char *ssid);
+
+/* writer functions */
+gboolean wpa_flush_to_file (const char *config_file);
+void wpa_set_data (const char *ssid, const char *key, const char *value);
+gboolean wpa_add_security (const char *ssid);
+gboolean wpa_delete_security (const char *ssid);
+#endif