diff options
| author | Michael Biebl <biebl@debian.org> | 2016-01-20 16:26:51 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2016-01-20 16:26:51 +0100 |
| commit | 494f296a3baab08522617b24b1f126d8f9a17502 (patch) | |
| tree | c8ef32fb0dd1c4ff35a0b38e787abb58692de0cd /src/devices | |
| parent | 54f6333410ffd570e62717d9e77c5c987175e397 (diff) | |
Imported Upstream version 1.1.90 upstream/1.1.90
Diffstat (limited to 'src/devices')
120 files changed, 10634 insertions, 10148 deletions
diff --git a/src/devices/Makefile.am b/src/devices/Makefile.am new file mode 100644 index 00000000..3c6155b9 --- /dev/null +++ b/src/devices/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = tests diff --git a/src/devices/wimax/Makefile.in b/src/devices/Makefile.in index b1b57a79..4415d31b 100644 --- a/src/devices/wimax/Makefile.in +++ b/src/devices/Makefile.in @@ -13,7 +13,6 @@ # PARTICULAR PURPOSE. @SET_MAKE@ - VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ @@ -88,7 +87,7 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -subdir = src/devices/wimax +subdir = src/devices ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_warnings.m4 \ @@ -110,50 +109,6 @@ 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__uninstall_files_from_dir = { \ - test -z "$$files" \ - || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ - || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ - $(am__cd) "$$dir" && rm -f $$files; }; \ - } -am__installdirs = "$(DESTDIR)$(pkglibdir)" -LTLIBRARIES = $(pkglib_LTLIBRARIES) -am__DEPENDENCIES_1 = -libnm_device_plugin_wimax_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) -am_libnm_device_plugin_wimax_la_OBJECTS = nm-wimax-factory.lo \ - nm-device-wimax.lo nm-wimax-nsp.lo nm-wimax-util.lo iwmxsdk.lo -libnm_device_plugin_wimax_la_OBJECTS = \ - $(am_libnm_device_plugin_wimax_la_OBJECTS) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = -libnm_device_plugin_wimax_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ - $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ - $(AM_CFLAGS) $(CFLAGS) $(libnm_device_plugin_wimax_la_LDFLAGS) \ - $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false @@ -166,35 +121,29 @@ AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = -DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp -am__depfiles_maybe = depfiles -am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ - $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ - $(AM_CFLAGS) $(CFLAGS) -AM_V_CC = $(am__v_CC_@AM_V@) -am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) -am__v_CC_0 = @echo " CC " $@; -am__v_CC_1 = -CCLD = $(CC) -LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(AM_LDFLAGS) $(LDFLAGS) -o $@ -AM_V_CCLD = $(am__v_CCLD_@AM_V@) -am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) -am__v_CCLD_0 = @echo " CCLD " $@; -am__v_CCLD_1 = -SOURCES = $(libnm_device_plugin_wimax_la_SOURCES) -DIST_SOURCES = $(libnm_device_plugin_wimax_la_SOURCES) +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ + ctags-recursive dvi-recursive html-recursive info-recursive \ + install-data-recursive install-dvi-recursive \ + install-exec-recursive install-html-recursive \ + install-info-recursive install-pdf-recursive \ + install-ps-recursive install-recursive installcheck-recursive \ + installdirs-recursive pdf-recursive ps-recursive \ + tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac +RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ + distclean-recursive maintainer-clean-recursive +am__recursive_targets = \ + $(RECURSIVE_TARGETS) \ + $(RECURSIVE_CLEAN_TARGETS) \ + $(am__extra_recursive_targets) +AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ + distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is @@ -214,9 +163,34 @@ am__define_uniq_tagged_files = \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags -am__DIST_COMMON = $(srcdir)/Makefile.in \ - $(top_srcdir)/build-aux/depcomp +DIST_SUBDIRS = $(SUBDIRS) +am__DIST_COMMON = $(srcdir)/Makefile.in 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@ @@ -232,7 +206,6 @@ BLUEZ5_LIBS = @BLUEZ5_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ -CKDB_PATH = @CKDB_PATH@ CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ @@ -244,8 +217,6 @@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DBUS_CFLAGS = @DBUS_CFLAGS@ -DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@ -DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@ DBUS_LIBS = @DBUS_LIBS@ DBUS_SYS_DIR = @DBUS_SYS_DIR@ DEFS = @DEFS@ @@ -255,6 +226,7 @@ DHCPCD_PATH = @DHCPCD_PATH@ DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ DLLTOOL = @DLLTOOL@ DNSMASQ_PATH = @DNSMASQ_PATH@ +DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ @@ -309,16 +281,13 @@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ IPTABLES_PATH = @IPTABLES_PATH@ -IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ -IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ +LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@ +LIBAUDIT_LIBS = @LIBAUDIT_LIBS@ LIBDL = @LIBDL@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ @@ -355,6 +324,8 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ +NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ NM_MICRO_VERSION = @NM_MICRO_VERSION@ NM_MINOR_VERSION = @NM_MINOR_VERSION@ @@ -383,7 +354,6 @@ POLKIT_LIBS = @POLKIT_LIBS@ POSUB = @POSUB@ PPPD_PATH = @PPPD_PATH@ PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ -PPPOE_PATH = @PPPOE_PATH@ QT_CFLAGS = @QT_CFLAGS@ QT_LIBS = @QT_LIBS@ RANLIB = @RANLIB@ @@ -398,6 +368,8 @@ SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ +SYSTEMD_JOURNAL_CFLAGS = @SYSTEMD_JOURNAL_CFLAGS@ +SYSTEMD_JOURNAL_LIBS = @SYSTEMD_JOURNAL_LIBS@ SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ @@ -458,6 +430,7 @@ mkdir_p = @mkdir_p@ nmbinary = @nmbinary@ nmconfdir = @nmconfdir@ nmdatadir = @nmdatadir@ +nmlibdir = @nmlibdir@ nmrundir = @nmrundir@ nmstatedir = @nmstatedir@ oldincludedir = @oldincludedir@ @@ -465,6 +438,7 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -480,55 +454,10 @@ with_dhcpcd = @with_dhcpcd@ with_netconfig = @with_netconfig@ with_resolvconf = @with_resolvconf@ with_valgrind = @with_valgrind@ -AM_CPPFLAGS = \ - -I${top_srcdir}/src \ - -I${top_builddir}/src \ - -I${top_srcdir}/src/devices \ - -I${top_srcdir}/src/platform \ - -I${top_srcdir}/include \ - -I${top_builddir}/include \ - -I${top_builddir}/libnm-core \ - -I${top_srcdir}/libnm-core \ - -DG_LOG_DOMAIN=\""NetworkManager-wimax"\" \ - -DNETWORKMANAGER_COMPILATION \ - -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ - $(DBUS_CFLAGS) \ - $(IWMX_SDK_CFLAGS) - -pkglib_LTLIBRARIES = libnm-device-plugin-wimax.la -SYMBOL_VIS_FILE = $(srcdir)/exports.ver -libnm_device_plugin_wimax_la_SOURCES = \ - nm-wimax-factory.c \ - nm-device-wimax.c \ - nm-device-wimax.h \ - nm-wimax-nsp.c \ - nm-wimax-nsp.h \ - nm-wimax-types.h \ - nm-wimax-util.c \ - nm-wimax-util.h \ - iwmxsdk.c \ - iwmxsdk.h - -libnm_device_plugin_wimax_la_LDFLAGS = \ - -module -avoid-version \ - -Wl,--version-script=$(SYMBOL_VIS_FILE) - -libnm_device_plugin_wimax_la_LIBADD = \ - $(DBUS_LIBS) \ - $(IWMX_SDK_LIBS) \ - $(GUDEV_LIBS) - -BUILT_SOURCES = \ - nm-wimax-nsp-glue.h \ - nm-device-wimax-glue.h - -CLEANFILES = $(BUILT_SOURCES) -EXTRA_DIST = $(SYMBOL_VIS_FILE) -all: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) all-am +SUBDIRS = tests +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 \ @@ -538,9 +467,9 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi exit 1;; \ esac; \ done; \ - echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/devices/wimax/Makefile'; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/devices/Makefile'; \ $(am__cd) $(top_srcdir) && \ - $(AUTOMAKE) --gnu src/devices/wimax/Makefile + $(AUTOMAKE) --gnu src/devices/Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ @@ -559,91 +488,67 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): -install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES) - @$(NORMAL_INSTALL) - @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 " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \ - $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \ - 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)'; \ - locs=`for p in $$list; do echo $$p; done | \ - sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ - sort -u`; \ - test -z "$$locs" || { \ - echo rm -f $${locs}; \ - rm -f $${locs}; \ - } - -libnm-device-plugin-wimax.la: $(libnm_device_plugin_wimax_la_OBJECTS) $(libnm_device_plugin_wimax_la_DEPENDENCIES) $(EXTRA_libnm_device_plugin_wimax_la_DEPENDENCIES) - $(AM_V_CCLD)$(libnm_device_plugin_wimax_la_LINK) -rpath $(pkglibdir) $(libnm_device_plugin_wimax_la_OBJECTS) $(libnm_device_plugin_wimax_la_LIBADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iwmxsdk.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-wimax.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-wimax-factory.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-wimax-nsp.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-wimax-util.Plo@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< - mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs +# This directory's subdirectories are mostly independent; you can cd +# into them and run 'make' without going through this Makefile. +# To change the values of 'make' variables: instead of editing Makefiles, +# (1) if the variable is set in 'config.status', edit 'config.status' +# (which will cause the Makefiles to be regenerated when you run 'make'); +# (2) otherwise, pass the desired values on the 'make' command line. +$(am__recursive_targets): + @fail=; \ + if $(am__make_keepgoing); then \ + failcom='fail=yes'; \ + else \ + failcom='exit 1'; \ + fi; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique -tags: tags-am +tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ @@ -656,7 +561,7 @@ tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $$unique; \ fi; \ fi -ctags: ctags-am +ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) @@ -669,7 +574,7 @@ GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" -cscopelist: cscopelist-am +cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ @@ -718,26 +623,45 @@ distdir: $(DISTFILES) || exit 1; \ fi; \ done -@ENABLE_TESTS_FALSE@check-local: -check-am: all-am - $(MAKE) $(AM_MAKEFLAGS) check-local -check: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) check-am -all-am: Makefile $(LTLIBRARIES) -installdirs: - for dir in "$(DESTDIR)$(pkglibdir)"; do \ - test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + $(am__make_dryrun) \ + || test -d "$(distdir)/$$subdir" \ + || $(MKDIR_P) "$(distdir)/$$subdir" \ + || exit 1; \ + dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ + $(am__relativize); \ + new_distdir=$$reldir; \ + dir1=$$subdir; dir2="$(top_distdir)"; \ + $(am__relativize); \ + new_top_distdir=$$reldir; \ + echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ + echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ + ($(am__cd) $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$new_top_distdir" \ + distdir="$$new_distdir" \ + am__remove_distdir=: \ + am__skip_length_check=: \ + am__skip_mode_fix=: \ + distdir) \ + || exit 1; \ + fi; \ done -install: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) install-am -install-exec: install-exec-am -install-data: install-data-am -uninstall: uninstall-am +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +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-am +installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ @@ -751,7 +675,6 @@ install-strip: mostlyclean-generic: clean-generic: - -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) @@ -760,106 +683,89 @@ distclean-generic: maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." - -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) -clean: clean-am +clean: clean-recursive -clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ - mostlyclean-am +clean-am: clean-generic clean-libtool mostlyclean-am -distclean: distclean-am - -rm -rf ./$(DEPDIR) +distclean: distclean-recursive -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags +distclean-am: clean-am distclean-generic distclean-tags -dvi: dvi-am +dvi: dvi-recursive dvi-am: -html: html-am +html: html-recursive html-am: -info: info-am +info: info-recursive info-am: install-data-am: -install-dvi: install-dvi-am +install-dvi: install-dvi-recursive install-dvi-am: -install-exec-am: install-pkglibLTLIBRARIES +install-exec-am: -install-html: install-html-am +install-html: install-html-recursive install-html-am: -install-info: install-info-am +install-info: install-info-recursive install-info-am: install-man: -install-pdf: install-pdf-am +install-pdf: install-pdf-recursive install-pdf-am: -install-ps: install-ps-am +install-ps: install-ps-recursive install-ps-am: installcheck-am: -maintainer-clean: maintainer-clean-am - -rm -rf ./$(DEPDIR) +maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic -mostlyclean: mostlyclean-am +mostlyclean: mostlyclean-recursive -mostlyclean-am: mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool +mostlyclean-am: mostlyclean-generic mostlyclean-libtool -pdf: pdf-am +pdf: pdf-recursive pdf-am: -ps: ps-am +ps: ps-recursive ps-am: -uninstall-am: uninstall-pkglibLTLIBRARIES - -.MAKE: all check check-am install install-am install-strip - -.PHONY: CTAGS GTAGS TAGS all all-am check check-am check-local clean \ - clean-generic clean-libtool clean-pkglibLTLIBRARIES \ - cscopelist-am ctags ctags-am distclean distclean-compile \ - distclean-generic distclean-libtool distclean-tags distdir dvi \ - dvi-am html html-am info info-am install install-am \ - install-data install-data-am install-dvi install-dvi-am \ - install-exec install-exec-am install-html install-html-am \ - install-info install-info-am install-man install-pdf \ - install-pdf-am install-pkglibLTLIBRARIES install-ps \ - install-ps-am install-strip installcheck installcheck-am \ - installdirs maintainer-clean maintainer-clean-generic \ - mostlyclean mostlyclean-compile mostlyclean-generic \ - mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ - uninstall-am uninstall-pkglibLTLIBRARIES +uninstall-am: -.PRECIOUS: Makefile +.MAKE: $(am__recursive_targets) install-am install-strip +.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ + check-am clean clean-generic clean-libtool cscopelist-am ctags \ + ctags-am distclean 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 \ + installdirs-am maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ + ps ps-am tags tags-am uninstall uninstall-am -nm-wimax-nsp-glue.h: $(top_srcdir)/introspection/nm-wimax-nsp.xml - dbus-binding-tool --prefix=nm_wimax_nsp --mode=glib-server --output=$@ $< - -nm-device-wimax-glue.h: $(top_srcdir)/introspection/nm-device-wimax.xml - dbus-binding-tool --prefix=nm_device_wimax --mode=glib-server --output=$@ $< +.PRECIOUS: Makefile -@ENABLE_TESTS_TRUE@check-local: -@ENABLE_TESTS_TRUE@ $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-wimax.so $(SYMBOL_VIS_FILE) # 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. diff --git a/src/devices/adsl/Makefile.am b/src/devices/adsl/Makefile.am index d7457c88..e7034fa8 100644 --- a/src/devices/adsl/Makefile.am +++ b/src/devices/adsl/Makefile.am @@ -7,26 +7,16 @@ AM_CPPFLAGS = \ -I${top_builddir}/src \ -I${top_srcdir}/src/devices \ -I${top_srcdir}/src/platform \ - -I${top_srcdir}/include \ - -I$(top_builddir)/include \ + -I${top_builddir}/introspection \ + -I${top_srcdir}/shared \ + -I$(top_builddir)/shared \ -I${top_builddir}/libnm-core \ -I${top_srcdir}/libnm-core \ -DG_LOG_DOMAIN=\""NetworkManager-adsl"\" \ - -DNETWORKMANAGER_COMPILATION \ + -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ - $(DBUS_CFLAGS) \ $(GUDEV_CFLAGS) -GLIB_GENERATED = nm-adsl-enum-types.h nm-adsl-enum-types.c -GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM -GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM -nm_adsl_enum_types_sources = $(srcdir)/nm-device-adsl.h - -nm-device-adsl-glue.h: $(top_srcdir)/introspection/nm-device-adsl.xml - dbus-binding-tool --prefix=nm_device_adsl --mode=glib-server --output=$@ $< - -BUILT_SOURCES = $(GLIB_GENERATED) nm-device-adsl-glue.h - pkglib_LTLIBRARIES = libnm-device-plugin-adsl.la SYMBOL_VIS_FILE=$(srcdir)/exports.ver @@ -35,19 +25,16 @@ libnm_device_plugin_adsl_la_SOURCES = \ nm-atm-manager.c \ nm-atm-manager.h \ nm-device-adsl.c \ - nm-device-adsl.h \ - \ - $(BUILT_SOURCES) + nm-device-adsl.h libnm_device_plugin_adsl_la_LDFLAGS = \ -module -avoid-version \ -Wl,--version-script=$(SYMBOL_VIS_FILE) libnm_device_plugin_adsl_la_LIBADD = \ - $(DBUS_LIBS) \ + $(top_builddir)/introspection/libnmdbus.la \ $(GUDEV_LIBS) -CLEANFILES = $(BUILT_SOURCES) EXTRA_DIST = $(SYMBOL_VIS_FILE) if ENABLE_TESTS diff --git a/src/devices/adsl/Makefile.in b/src/devices/adsl/Makefile.in index b6e944f8..e969a627 100644 --- a/src/devices/adsl/Makefile.in +++ b/src/devices/adsl/Makefile.in @@ -140,12 +140,11 @@ am__uninstall_files_from_dir = { \ am__installdirs = "$(DESTDIR)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) am__DEPENDENCIES_1 = -libnm_device_plugin_adsl_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ +libnm_device_plugin_adsl_la_DEPENDENCIES = \ + $(top_builddir)/introspection/libnmdbus.la \ $(am__DEPENDENCIES_1) -am__objects_1 = nm-adsl-enum-types.lo -am__objects_2 = $(am__objects_1) am_libnm_device_plugin_adsl_la_OBJECTS = nm-atm-manager.lo \ - nm-device-adsl.lo $(am__objects_2) + nm-device-adsl.lo libnm_device_plugin_adsl_la_OBJECTS = \ $(am_libnm_device_plugin_adsl_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) @@ -234,7 +233,6 @@ BLUEZ5_LIBS = @BLUEZ5_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ -CKDB_PATH = @CKDB_PATH@ CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ @@ -246,8 +244,6 @@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DBUS_CFLAGS = @DBUS_CFLAGS@ -DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@ -DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@ DBUS_LIBS = @DBUS_LIBS@ DBUS_SYS_DIR = @DBUS_SYS_DIR@ DEFS = @DEFS@ @@ -257,6 +253,7 @@ DHCPCD_PATH = @DHCPCD_PATH@ DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ DLLTOOL = @DLLTOOL@ DNSMASQ_PATH = @DNSMASQ_PATH@ +DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ @@ -311,16 +308,13 @@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ IPTABLES_PATH = @IPTABLES_PATH@ -IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ -IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ +LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@ +LIBAUDIT_LIBS = @LIBAUDIT_LIBS@ LIBDL = @LIBDL@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ @@ -357,6 +351,8 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ +NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ NM_MICRO_VERSION = @NM_MICRO_VERSION@ NM_MINOR_VERSION = @NM_MINOR_VERSION@ @@ -385,7 +381,6 @@ POLKIT_LIBS = @POLKIT_LIBS@ POSUB = @POSUB@ PPPD_PATH = @PPPD_PATH@ PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ -PPPOE_PATH = @PPPOE_PATH@ QT_CFLAGS = @QT_CFLAGS@ QT_LIBS = @QT_LIBS@ RANLIB = @RANLIB@ @@ -400,6 +395,8 @@ SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ +SYSTEMD_JOURNAL_CFLAGS = @SYSTEMD_JOURNAL_CFLAGS@ +SYSTEMD_JOURNAL_LIBS = @SYSTEMD_JOURNAL_LIBS@ SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ @@ -460,6 +457,7 @@ mkdir_p = @mkdir_p@ nmbinary = @nmbinary@ nmconfdir = @nmconfdir@ nmdatadir = @nmdatadir@ +nmlibdir = @nmlibdir@ nmrundir = @nmrundir@ nmstatedir = @nmstatedir@ oldincludedir = @oldincludedir@ @@ -467,6 +465,7 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -487,43 +486,34 @@ AM_CPPFLAGS = \ -I${top_builddir}/src \ -I${top_srcdir}/src/devices \ -I${top_srcdir}/src/platform \ - -I${top_srcdir}/include \ - -I$(top_builddir)/include \ + -I${top_builddir}/introspection \ + -I${top_srcdir}/shared \ + -I$(top_builddir)/shared \ -I${top_builddir}/libnm-core \ -I${top_srcdir}/libnm-core \ -DG_LOG_DOMAIN=\""NetworkManager-adsl"\" \ - -DNETWORKMANAGER_COMPILATION \ + -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ - $(DBUS_CFLAGS) \ $(GUDEV_CFLAGS) -GLIB_GENERATED = nm-adsl-enum-types.h nm-adsl-enum-types.c -GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM -GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM -nm_adsl_enum_types_sources = $(srcdir)/nm-device-adsl.h -BUILT_SOURCES = $(GLIB_GENERATED) nm-device-adsl-glue.h pkglib_LTLIBRARIES = libnm-device-plugin-adsl.la SYMBOL_VIS_FILE = $(srcdir)/exports.ver libnm_device_plugin_adsl_la_SOURCES = \ nm-atm-manager.c \ nm-atm-manager.h \ nm-device-adsl.c \ - nm-device-adsl.h \ - \ - $(BUILT_SOURCES) + nm-device-adsl.h libnm_device_plugin_adsl_la_LDFLAGS = \ -module -avoid-version \ -Wl,--version-script=$(SYMBOL_VIS_FILE) libnm_device_plugin_adsl_la_LIBADD = \ - $(DBUS_LIBS) \ + $(top_builddir)/introspection/libnmdbus.la \ $(GUDEV_LIBS) -CLEANFILES = $(BUILT_SOURCES) EXTRA_DIST = $(SYMBOL_VIS_FILE) -all: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) all-am +all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj @@ -601,7 +591,6 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-adsl-enum-types.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-atm-manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-adsl.Plo@am__quote@ @@ -717,15 +706,13 @@ distdir: $(DISTFILES) @ENABLE_TESTS_FALSE@check-local: check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local -check: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) check-am +check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done -install: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) install-am +install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am @@ -747,7 +734,6 @@ install-strip: mostlyclean-generic: clean-generic: - -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) @@ -756,7 +742,6 @@ distclean-generic: maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." - -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ @@ -828,7 +813,7 @@ ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES -.MAKE: all check check-am install install-am install-strip +.MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am check-local clean \ clean-generic clean-libtool clean-pkglibLTLIBRARIES \ @@ -851,9 +836,6 @@ include $(GLIB_MAKEFILE) @GNOME_CODE_COVERAGE_RULES@ -nm-device-adsl-glue.h: $(top_srcdir)/introspection/nm-device-adsl.xml - dbus-binding-tool --prefix=nm_device_adsl --mode=glib-server --output=$@ $< - @ENABLE_TESTS_TRUE@check-local: @ENABLE_TESTS_TRUE@ $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-adsl.so $(SYMBOL_VIS_FILE) diff --git a/src/devices/adsl/nm-adsl-enum-types.c b/src/devices/adsl/nm-adsl-enum-types.c deleted file mode 100644 index 08565331..00000000 --- a/src/devices/adsl/nm-adsl-enum-types.c +++ /dev/null @@ -1,12 +0,0 @@ - - - -/* Generated by glib-mkenums. Do not edit */ - -#include "nm-adsl-enum-types.h" - -#include "nm-device-adsl.h" - - - - diff --git a/src/devices/adsl/nm-adsl-enum-types.h b/src/devices/adsl/nm-adsl-enum-types.h deleted file mode 100644 index 88e1fe84..00000000 --- a/src/devices/adsl/nm-adsl-enum-types.h +++ /dev/null @@ -1,17 +0,0 @@ - - - -/* Generated by glib-mkenums. Do not edit */ - -#ifndef __NM_ADSL_ENUM_TYPES_H__ -#define __NM_ADSL_ENUM_TYPES_H__ - -#include <glib-object.h> - -G_BEGIN_DECLS -G_END_DECLS - -#endif /* __NM_ADSL_ENUM_TYPES_H__ */ - - - diff --git a/src/devices/adsl/nm-atm-manager.c b/src/devices/adsl/nm-atm-manager.c index aeb5af6c..d3f1423f 100644 --- a/src/devices/adsl/nm-atm-manager.c +++ b/src/devices/adsl/nm-atm-manager.c @@ -24,14 +24,12 @@ #include <gudev/gudev.h> #include <gmodule.h> +#include "nm-default.h" #include "nm-atm-manager.h" #include "nm-setting-adsl.h" #include "nm-device-adsl.h" #include "nm-device-factory.h" -#include "nm-logging.h" -#include "nm-glib-compat.h" #include "nm-platform.h" -#include "gsystem-local-alloc.h" typedef struct { GUdevClient *client; @@ -42,7 +40,7 @@ typedef struct { static GType nm_atm_manager_get_type (void); -static void device_factory_interface_init (NMDeviceFactory *factory_iface); +static void device_factory_interface_init (NMDeviceFactoryInterface *factory_iface); G_DEFINE_TYPE_EXTENDED (NMAtmManager, nm_atm_manager, G_TYPE_OBJECT, 0, G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_FACTORY, device_factory_interface_init)) @@ -239,7 +237,7 @@ nm_atm_manager_init (NMAtmManager *self) } static void -device_factory_interface_init (NMDeviceFactory *factory_iface) +device_factory_interface_init (NMDeviceFactoryInterface *factory_iface) { factory_iface->get_supported_types = get_supported_types; factory_iface->start = start; diff --git a/src/devices/adsl/nm-atm-manager.h b/src/devices/adsl/nm-atm-manager.h index e4ec3e6a..fe0bc14c 100644 --- a/src/devices/adsl/nm-atm-manager.h +++ b/src/devices/adsl/nm-atm-manager.h @@ -22,8 +22,7 @@ #ifndef __NETWORKMANAGER_ATM_MANAGER_H__ #define __NETWORKMANAGER_ATM_MANAGER_H__ -#include <glib.h> -#include <glib-object.h> +#include "nm-default.h" G_BEGIN_DECLS diff --git a/src/devices/adsl/nm-device-adsl-glue.h b/src/devices/adsl/nm-device-adsl-glue.h deleted file mode 100644 index 3a1b9108..00000000 --- a/src/devices/adsl/nm-device-adsl-glue.h +++ /dev/null @@ -1,73 +0,0 @@ -/* Generated by dbus-binding-tool; do not edit! */ - - -#ifndef __dbus_glib_marshal_nm_device_adsl_MARSHAL_H__ -#define __dbus_glib_marshal_nm_device_adsl_MARSHAL_H__ - -#include <glib-object.h> - -G_BEGIN_DECLS - -#ifdef G_ENABLE_DEBUG -#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) -#define g_marshal_value_peek_char(v) g_value_get_schar (v) -#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) -#define g_marshal_value_peek_int(v) g_value_get_int (v) -#define g_marshal_value_peek_uint(v) g_value_get_uint (v) -#define g_marshal_value_peek_long(v) g_value_get_long (v) -#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) -#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) -#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) -#define g_marshal_value_peek_enum(v) g_value_get_enum (v) -#define g_marshal_value_peek_flags(v) g_value_get_flags (v) -#define g_marshal_value_peek_float(v) g_value_get_float (v) -#define g_marshal_value_peek_double(v) g_value_get_double (v) -#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) -#define g_marshal_value_peek_param(v) g_value_get_param (v) -#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) -#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) -#define g_marshal_value_peek_object(v) g_value_get_object (v) -#define g_marshal_value_peek_variant(v) g_value_get_variant (v) -#else /* !G_ENABLE_DEBUG */ -/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. - * Do not access GValues directly in your code. Instead, use the - * g_value_get_*() functions - */ -#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int -#define g_marshal_value_peek_char(v) (v)->data[0].v_int -#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint -#define g_marshal_value_peek_int(v) (v)->data[0].v_int -#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint -#define g_marshal_value_peek_long(v) (v)->data[0].v_long -#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong -#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 -#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 -#define g_marshal_value_peek_enum(v) (v)->data[0].v_long -#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong -#define g_marshal_value_peek_float(v) (v)->data[0].v_float -#define g_marshal_value_peek_double(v) (v)->data[0].v_double -#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer -#endif /* !G_ENABLE_DEBUG */ - - -G_END_DECLS - -#endif /* __dbus_glib_marshal_nm_device_adsl_MARSHAL_H__ */ - -#include <dbus/dbus-glib.h> -static const DBusGMethodInfo dbus_glib_nm_device_adsl_methods[] = { -}; - -const DBusGObjectInfo dbus_glib_nm_device_adsl_object_info = { 1, - dbus_glib_nm_device_adsl_methods, - 0, -"\0", -"org.freedesktop.NetworkManager.Device.Adsl\0PropertiesChanged\0\0", -"org.freedesktop.NetworkManager.Device.Adsl\0Carrier\0carrier\0read\0\0" -}; - diff --git a/src/devices/adsl/nm-device-adsl.c b/src/devices/adsl/nm-device-adsl.c index bcef39a2..dd9a1203 100644 --- a/src/devices/adsl/nm-device-adsl.c +++ b/src/devices/adsl/nm-device-adsl.c @@ -29,24 +29,20 @@ #include <sys/types.h> #include <unistd.h> -#include <glib.h> -#include <glib/gi18n.h> #include <stdlib.h> #include <string.h> +#include "nm-default.h" #include "nm-device-adsl.h" #include "nm-device-private.h" -#include "NetworkManagerUtils.h" -#include "nm-logging.h" #include "nm-enum-types.h" -#include "nm-dbus-manager.h" #include "nm-platform.h" #include "ppp-manager/nm-ppp-manager.h" #include "nm-setting-adsl.h" #include "nm-utils.h" -#include "nm-device-adsl-glue.h" +#include "nmdbus-device-adsl.h" #include "nm-device-logging.h" _LOG_DECLARE_SELF (NMDeviceAdsl); @@ -238,7 +234,6 @@ link_changed_cb (NMPlatform *platform, int ifindex, NMPlatformLink *info, NMPlatformSignalChangeType change_type, - NMPlatformReason reason, NMDeviceAdsl *self) { if (change_type == NM_PLATFORM_SIGNAL_REMOVED) { @@ -264,7 +259,7 @@ pppoe_vcc_config (NMDeviceAdsl *self) NMDevice *device = NM_DEVICE (self); NMSettingAdsl *s_adsl; - s_adsl = nm_connection_get_setting_adsl (nm_device_get_connection (device)); + s_adsl = nm_connection_get_setting_adsl (nm_device_get_applied_connection (device)); g_assert (s_adsl); /* Set up the VCC */ @@ -272,7 +267,7 @@ pppoe_vcc_config (NMDeviceAdsl *self) return FALSE; /* Watch for the 'nas' interface going away */ - g_signal_connect (nm_platform_get (), NM_PLATFORM_SIGNAL_LINK_CHANGED, + g_signal_connect (NM_PLATFORM_GET, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (link_changed_cb), self); @@ -397,7 +392,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_reason) g_assert (out_reason); - s_adsl = nm_connection_get_setting_adsl (nm_device_get_connection (device)); + s_adsl = nm_connection_get_setting_adsl (nm_device_get_applied_connection (device)); g_assert (s_adsl); protocol = nm_setting_adsl_get_protocol (s_adsl); @@ -464,7 +459,7 @@ act_stage3_ip4_config_start (NMDevice *device, req = nm_device_get_act_request (device); g_assert (req); - connection = nm_act_request_get_connection (req); + connection = nm_act_request_get_applied_connection (req); g_assert (req); s_adsl = nm_connection_get_setting_adsl (connection); @@ -483,7 +478,7 @@ act_stage3_ip4_config_start (NMDevice *device, priv->ppp_manager = nm_ppp_manager_new (ppp_iface); if (nm_ppp_manager_start (priv->ppp_manager, req, nm_setting_adsl_get_username (s_adsl), 30, &err)) { - g_signal_connect (priv->ppp_manager, "state-changed", + g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_STATE_CHANGED, G_CALLBACK (ppp_state_changed), self); g_signal_connect (priv->ppp_manager, "ip4-config", @@ -494,8 +489,7 @@ act_stage3_ip4_config_start (NMDevice *device, _LOGW (LOGD_ADSL, "PPP failed to start: %s", err->message); g_error_free (err); - g_object_unref (priv->ppp_manager); - priv->ppp_manager = NULL; + nm_exported_object_clear_and_unexport (&priv->ppp_manager); *reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED; } @@ -511,10 +505,10 @@ adsl_cleanup (NMDeviceAdsl *self) if (priv->ppp_manager) { g_signal_handlers_disconnect_by_func (priv->ppp_manager, G_CALLBACK (ppp_state_changed), self); g_signal_handlers_disconnect_by_func (priv->ppp_manager, G_CALLBACK (ppp_ip4_config), self); - g_clear_object (&priv->ppp_manager); + nm_exported_object_clear_and_unexport (&priv->ppp_manager); } - g_signal_handlers_disconnect_by_func (nm_platform_get (), G_CALLBACK (link_changed_cb), self); + g_signal_handlers_disconnect_by_func (NM_PLATFORM_GET, G_CALLBACK (link_changed_cb), self); if (priv->brfd >= 0) { close (priv->brfd); @@ -666,7 +660,7 @@ nm_device_adsl_class_init (NMDeviceAdslClass *klass) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); - nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), - G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_adsl_object_info); + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_ADSL_SKELETON, + NULL); } diff --git a/src/devices/adsl/nm-device-adsl.h b/src/devices/adsl/nm-device-adsl.h index bf41ed79..efcdaf69 100644 --- a/src/devices/adsl/nm-device-adsl.h +++ b/src/devices/adsl/nm-device-adsl.h @@ -22,9 +22,8 @@ #ifndef __NETWORKMANAGER_DEVICE_ADSL_H__ #define __NETWORKMANAGER_DEVICE_ADSL_H__ -#include <glib-object.h> - // Parent class +#include "nm-default.h" #include "nm-device.h" G_BEGIN_DECLS diff --git a/src/devices/bluetooth/Makefile.am b/src/devices/bluetooth/Makefile.am index e6e378f0..2054ea0f 100644 --- a/src/devices/bluetooth/Makefile.am +++ b/src/devices/bluetooth/Makefile.am @@ -9,25 +9,22 @@ AM_CPPFLAGS = \ -I${top_srcdir}/src/settings \ -I${top_srcdir}/src/platform \ -I${top_srcdir}/src/devices/wwan \ - -I${top_srcdir}/include \ - -I$(top_builddir)/include \ + -I${top_builddir}/introspection \ + -I${top_srcdir}/shared \ + -I$(top_builddir)/shared \ -I${top_builddir}/libnm-core \ -I${top_srcdir}/libnm-core \ -DG_LOG_DOMAIN=\""NetworkManager-bluetooth"\" \ - -DNETWORKMANAGER_COMPILATION \ + -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ - $(GLIB_CFLAGS) \ - $(DBUS_CFLAGS) + $(GLIB_CFLAGS) GLIB_GENERATED = nm-bt-enum-types.h nm-bt-enum-types.c GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM nm_bt_enum_types_sources = $(srcdir)/nm-bt-error.h -nm-device-bt-glue.h: $(top_srcdir)/introspection/nm-device-bt.xml - dbus-binding-tool --prefix=nm_device_bt --mode=glib-server --output=$@ $< - -BUILT_SOURCES = $(GLIB_GENERATED) nm-device-bt-glue.h +BUILT_SOURCES = $(GLIB_GENERATED) pkglib_LTLIBRARIES = libnm-device-plugin-bluetooth.la @@ -58,8 +55,9 @@ libnm_device_plugin_bluetooth_la_LDFLAGS = \ -Wl,--version-script=$(SYMBOL_VIS_FILE) libnm_device_plugin_bluetooth_la_LIBADD = \ + $(top_builddir)/introspection/libnmdbus.la \ $(top_builddir)/src/devices/wwan/libnm-wwan.la \ - $(DBUS_LIBS) \ + $(GLIB_LIBS) \ $(GUDEV_LIBS) if WITH_BLUEZ5_DUN diff --git a/src/devices/bluetooth/Makefile.in b/src/devices/bluetooth/Makefile.in index bdc3b5cb..f93f7242 100644 --- a/src/devices/bluetooth/Makefile.in +++ b/src/devices/bluetooth/Makefile.in @@ -148,6 +148,7 @@ LTLIBRARIES = $(pkglib_LTLIBRARIES) am__DEPENDENCIES_1 = @WITH_BLUEZ5_DUN_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) libnm_device_plugin_bluetooth_la_DEPENDENCIES = \ + $(top_builddir)/introspection/libnmdbus.la \ $(top_builddir)/src/devices/wwan/libnm-wwan.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_2) @@ -157,8 +158,7 @@ am__libnm_device_plugin_bluetooth_la_SOURCES_DIST = \ nm-bluez4-adapter.h nm-bluez4-manager.c nm-bluez4-manager.h \ nm-bluez5-manager.c nm-bluez5-manager.h nm-bt-error.h \ nm-bt-error.c nm-device-bt.c nm-device-bt.h nm-bt-enum-types.h \ - nm-bt-enum-types.c nm-device-bt-glue.h nm-bluez5-dun.c \ - nm-bluez5-dun.h + nm-bt-enum-types.c nm-bluez5-dun.c nm-bluez5-dun.h am__objects_1 = nm-bt-enum-types.lo am__objects_2 = $(am__objects_1) @WITH_BLUEZ5_DUN_TRUE@am__objects_3 = nm-bluez5-dun.lo @@ -254,7 +254,6 @@ BLUEZ5_LIBS = @BLUEZ5_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ -CKDB_PATH = @CKDB_PATH@ CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ @@ -266,8 +265,6 @@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DBUS_CFLAGS = @DBUS_CFLAGS@ -DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@ -DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@ DBUS_LIBS = @DBUS_LIBS@ DBUS_SYS_DIR = @DBUS_SYS_DIR@ DEFS = @DEFS@ @@ -277,6 +274,7 @@ DHCPCD_PATH = @DHCPCD_PATH@ DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ DLLTOOL = @DLLTOOL@ DNSMASQ_PATH = @DNSMASQ_PATH@ +DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ @@ -331,16 +329,13 @@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ IPTABLES_PATH = @IPTABLES_PATH@ -IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ -IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ +LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@ +LIBAUDIT_LIBS = @LIBAUDIT_LIBS@ LIBDL = @LIBDL@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ @@ -377,6 +372,8 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ +NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ NM_MICRO_VERSION = @NM_MICRO_VERSION@ NM_MINOR_VERSION = @NM_MINOR_VERSION@ @@ -405,7 +402,6 @@ POLKIT_LIBS = @POLKIT_LIBS@ POSUB = @POSUB@ PPPD_PATH = @PPPD_PATH@ PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ -PPPOE_PATH = @PPPOE_PATH@ QT_CFLAGS = @QT_CFLAGS@ QT_LIBS = @QT_LIBS@ RANLIB = @RANLIB@ @@ -420,6 +416,8 @@ SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ +SYSTEMD_JOURNAL_CFLAGS = @SYSTEMD_JOURNAL_CFLAGS@ +SYSTEMD_JOURNAL_LIBS = @SYSTEMD_JOURNAL_LIBS@ SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ @@ -480,6 +478,7 @@ mkdir_p = @mkdir_p@ nmbinary = @nmbinary@ nmconfdir = @nmconfdir@ nmdatadir = @nmdatadir@ +nmlibdir = @nmlibdir@ nmrundir = @nmrundir@ nmstatedir = @nmstatedir@ oldincludedir = @oldincludedir@ @@ -487,6 +486,7 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -505,17 +505,18 @@ with_valgrind = @with_valgrind@ AM_CPPFLAGS = -I${top_srcdir}/src -I${top_builddir}/src \ -I${top_srcdir}/src/devices -I${top_srcdir}/src/settings \ -I${top_srcdir}/src/platform -I${top_srcdir}/src/devices/wwan \ - -I${top_srcdir}/include -I$(top_builddir)/include \ - -I${top_builddir}/libnm-core -I${top_srcdir}/libnm-core \ + -I${top_builddir}/introspection -I${top_srcdir}/shared \ + -I$(top_builddir)/shared -I${top_builddir}/libnm-core \ + -I${top_srcdir}/libnm-core \ -DG_LOG_DOMAIN=\""NetworkManager-bluetooth"\" \ - -DNETWORKMANAGER_COMPILATION \ + -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE $(GLIB_CFLAGS) \ - $(DBUS_CFLAGS) $(am__append_1) + $(am__append_1) GLIB_GENERATED = nm-bt-enum-types.h nm-bt-enum-types.c GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM nm_bt_enum_types_sources = $(srcdir)/nm-bt-error.h -BUILT_SOURCES = $(GLIB_GENERATED) nm-device-bt-glue.h +BUILT_SOURCES = $(GLIB_GENERATED) pkglib_LTLIBRARIES = libnm-device-plugin-bluetooth.la SYMBOL_VIS_FILE = $(srcdir)/exports.ver libnm_device_plugin_bluetooth_la_SOURCES = nm-bluez-manager.c \ @@ -529,7 +530,8 @@ libnm_device_plugin_bluetooth_la_LDFLAGS = \ -Wl,--version-script=$(SYMBOL_VIS_FILE) libnm_device_plugin_bluetooth_la_LIBADD = \ - $(top_builddir)/src/devices/wwan/libnm-wwan.la $(DBUS_LIBS) \ + $(top_builddir)/introspection/libnmdbus.la \ + $(top_builddir)/src/devices/wwan/libnm-wwan.la $(GLIB_LIBS) \ $(GUDEV_LIBS) $(am__append_3) CLEANFILES = $(BUILT_SOURCES) EXTRA_DIST = $(SYMBOL_VIS_FILE) @@ -868,9 +870,6 @@ include $(GLIB_MAKEFILE) @GNOME_CODE_COVERAGE_RULES@ -nm-device-bt-glue.h: $(top_srcdir)/introspection/nm-device-bt.xml - dbus-binding-tool --prefix=nm_device_bt --mode=glib-server --output=$@ $< - @ENABLE_TESTS_TRUE@check-local: @ENABLE_TESTS_TRUE@ $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-bluetooth.so $(SYMBOL_VIS_FILE) diff --git a/src/devices/bluetooth/nm-bluez-common.h b/src/devices/bluetooth/nm-bluez-common.h index f0cab43b..4262fa76 100644 --- a/src/devices/bluetooth/nm-bluez-common.h +++ b/src/devices/bluetooth/nm-bluez-common.h @@ -21,7 +21,7 @@ #ifndef __NETWORKMANAGER_BLUEZ_COMMON_H__ #define __NETWORKMANAGER_BLUEZ_COMMON_H__ -#include <config.h> +#include "config.h" #define BLUETOOTH_CONNECT_DUN "dun" #define BLUETOOTH_CONNECT_NAP "nap" diff --git a/src/devices/bluetooth/nm-bluez-device.c b/src/devices/bluetooth/nm-bluez-device.c index 89ad8270..b7032143 100644 --- a/src/devices/bluetooth/nm-bluez-device.c +++ b/src/devices/bluetooth/nm-bluez-device.c @@ -21,17 +21,14 @@ #include "config.h" -#include <glib.h> -#include <glib/gi18n.h> -#include <gio/gio.h> #include <string.h> +#include "nm-default.h" #include "nm-core-internal.h" #include "nm-bt-error.h" #include "nm-bluez-common.h" #include "nm-bluez-device.h" -#include "nm-logging.h" #include "nm-settings-connection.h" #include "NetworkManagerUtils.h" @@ -869,21 +866,14 @@ properties_changed (GDBusProxy *proxy, static void bluez4_property_changed (GDBusProxy *proxy, - const char *sender, - const char *signal_name, - GVariant *parameters, - gpointer user_data) + const char *property, + GVariant *v, + gpointer user_data) { NMBluezDevice *self = NM_BLUEZ_DEVICE (user_data); - if (g_strcmp0 (signal_name, "PropertyChanged") == 0) { - const char *property = NULL; - GVariant *v = NULL; - - g_variant_get (parameters, "(&sv)", &property, &v); - _take_one_variant_property (self, property, v); - check_emit_usable (self); - } + _take_one_variant_property (self, property, v); + check_emit_usable (self); } static void @@ -893,27 +883,22 @@ get_properties_cb_4 (GObject *source_object, GAsyncResult *res, gpointer user_da NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); GError *err = NULL; GVariant *v_properties, *v_dict; - GVariantType *v_type; - v_properties = g_dbus_proxy_call_finish (priv->proxy, res, &err); + v_properties = _nm_dbus_proxy_call_finish (priv->proxy, res, + G_VARIANT_TYPE ("(a{sv})"), + &err); if (!v_properties) { + g_dbus_error_strip_remote_error (err); nm_log_warn (LOGD_BT, "bluez[%s] error getting device properties: %s", - priv->path, err && err->message ? err->message : "(unknown)"); + priv->path, err->message); g_error_free (err); g_signal_emit (self, signals[INITIALIZED], 0, FALSE); goto END; } - v_type = g_variant_type_new ("(a{sv})"); - if (g_variant_is_of_type (v_properties, v_type)) { - v_dict = g_variant_get_child_value (v_properties, 0); - _set_properties (self, v_dict); - g_variant_unref (v_dict); - } else { - nm_log_warn (LOGD_BT, "bluez[%s] GetProperties returns unexpected result of type %s", priv->path, g_variant_get_type_string (v_properties)); - } - g_variant_type_free (v_type); - + v_dict = g_variant_get_child_value (v_properties, 0); + _set_properties (self, v_dict); + g_variant_unref (v_dict); g_variant_unref (v_properties); /* Check if any connections match this device */ @@ -922,7 +907,6 @@ get_properties_cb_4 (GObject *source_object, GAsyncResult *res, gpointer user_da priv->initialized = TRUE; g_signal_emit (self, signals[INITIALIZED], 0, TRUE); - check_emit_usable (self); END: @@ -990,8 +974,8 @@ on_proxy_acquired (GObject *object, GAsyncResult *res, NMBluezDevice *self) G_CALLBACK (properties_changed), self); if (priv->bluez_version == 4) { /* Watch for custom Bluez4 PropertyChanged signals */ - g_signal_connect (priv->proxy, "g-signal", - G_CALLBACK (bluez4_property_changed), self); + _nm_dbus_signal_connect (priv->proxy, "PropertyChanged", G_VARIANT_TYPE ("(sv)"), + G_CALLBACK (bluez4_property_changed), self); } query_properties (self); diff --git a/src/devices/bluetooth/nm-bluez-device.h b/src/devices/bluetooth/nm-bluez-device.h index 92d99fa7..0e54fcb0 100644 --- a/src/devices/bluetooth/nm-bluez-device.h +++ b/src/devices/bluetooth/nm-bluez-device.h @@ -21,11 +21,9 @@ #ifndef __NETWORKMANAGER_BLUEZ_DEVICE_H__ #define __NETWORKMANAGER_BLUEZ_DEVICE_H__ -#include <glib.h> -#include <glib-object.h> -#include <gio/gio.h> -#include <config.h> +#include "config.h" +#include "nm-default.h" #include "nm-connection.h" #include "nm-connection-provider.h" diff --git a/src/devices/bluetooth/nm-bluez-manager.c b/src/devices/bluetooth/nm-bluez-manager.c index df4eb46d..6903356c 100644 --- a/src/devices/bluetooth/nm-bluez-manager.c +++ b/src/devices/bluetooth/nm-bluez-manager.c @@ -24,9 +24,8 @@ #include <string.h> #include <stdlib.h> #include <gmodule.h> -#include <gio/gio.h> -#include "nm-logging.h" +#include "nm-default.h" #include "nm-bluez-manager.h" #include "nm-device-factory.h" #include "nm-setting-bluetooth.h" @@ -36,9 +35,9 @@ #include "nm-bluez-common.h" #include "nm-connection-provider.h" #include "nm-device-bt.h" - -#include "nm-dbus-manager.h" +#include "nm-core-internal.h" #include "nm-platform.h" +#include "nm-dbus-compat.h" typedef struct { int bluez_version; @@ -57,7 +56,7 @@ typedef struct { static GType nm_bluez_manager_get_type (void); -static void device_factory_interface_init (NMDeviceFactory *factory_iface); +static void device_factory_interface_init (NMDeviceFactoryInterface *factory_iface); G_DEFINE_TYPE_EXTENDED (NMBluezManager, nm_bluez_manager, G_TYPE_OBJECT, 0, G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_FACTORY, device_factory_interface_init)) @@ -278,10 +277,13 @@ check_bluez_and_try_setup_do_introspect (GObject *source_object, g_clear_object (&priv->async_cancellable); - result = g_dbus_proxy_call_finish (priv->introspect_proxy, res, &error); - + result = _nm_dbus_proxy_call_finish (priv->introspect_proxy, res, + G_VARIANT_TYPE ("(s)"), &error); if (!result) { - char *reason2 = g_strdup_printf ("introspect failed with %s", error->message); + char *reason2; + + g_dbus_error_strip_remote_error (error); + reason2 = g_strdup_printf ("introspect failed with %s", error->message); check_bluez_and_try_setup_final_step (self, 0, reason2); g_error_free (error); g_free (reason2); @@ -407,7 +409,11 @@ nm_bluez_manager_init (NMBluezManager *self) } static NMDevice * -new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error) +create_device (NMDeviceFactory *factory, + const char *iface, + const NMPlatformLink *plink, + NMConnection *connection, + gboolean *out_ignore) { g_warn_if_fail (plink->type == NM_LINK_TYPE_BNEP); *out_ignore = TRUE; @@ -415,10 +421,10 @@ new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, } static void -device_factory_interface_init (NMDeviceFactory *factory_iface) +device_factory_interface_init (NMDeviceFactoryInterface *factory_iface) { factory_iface->get_supported_types = get_supported_types; - factory_iface->new_link = new_link; + factory_iface->create_device = create_device; factory_iface->start = start; } diff --git a/src/devices/bluetooth/nm-bluez-manager.h b/src/devices/bluetooth/nm-bluez-manager.h index 8320b298..1f5597d8 100644 --- a/src/devices/bluetooth/nm-bluez-manager.h +++ b/src/devices/bluetooth/nm-bluez-manager.h @@ -22,8 +22,7 @@ #ifndef __NETWORKMANAGER_BLUEZ_MANAGER_H__ #define __NETWORKMANAGER_BLUEZ_MANAGER_H__ -#include <glib.h> -#include <glib-object.h> +#include "nm-default.h" G_BEGIN_DECLS diff --git a/src/devices/bluetooth/nm-bluez4-adapter.c b/src/devices/bluetooth/nm-bluez4-adapter.c index 9d1cfe1f..04ae833a 100644 --- a/src/devices/bluetooth/nm-bluez4-adapter.c +++ b/src/devices/bluetooth/nm-bluez4-adapter.c @@ -20,17 +20,14 @@ #include "config.h" -#include <glib.h> #include <string.h> +#include "nm-default.h" #include "nm-dbus-interface.h" -#include "nm-dbus-manager.h" #include "nm-bluez4-adapter.h" #include "nm-bluez-device.h" #include "nm-bluez-common.h" -#include "nm-dbus-glib-types.h" -#include "nm-logging.h" - +#include "nm-core-internal.h" G_DEFINE_TYPE (NMBluez4Adapter, nm_bluez4_adapter, G_TYPE_OBJECT) @@ -38,7 +35,7 @@ G_DEFINE_TYPE (NMBluez4Adapter, nm_bluez4_adapter, G_TYPE_OBJECT) typedef struct { char *path; - DBusGProxy *proxy; + GDBusProxy *proxy; gboolean initialized; char *address; @@ -158,7 +155,7 @@ device_do_remove (NMBluez4Adapter *self, NMBluezDevice *device) } static void -device_created (DBusGProxy *proxy, const char *path, gpointer user_data) +device_created (GDBusProxy *proxy, const char *path, gpointer user_data) { NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data); NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); @@ -173,7 +170,7 @@ device_created (DBusGProxy *proxy, const char *path, gpointer user_data) } static void -device_removed (DBusGProxy *proxy, const char *path, gpointer user_data) +device_removed (GDBusProxy *proxy, const char *path, gpointer user_data) { NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data); NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); @@ -186,37 +183,36 @@ device_removed (DBusGProxy *proxy, const char *path, gpointer user_data) device_do_remove (self, device); } - static void -get_properties_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +get_properties_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) { NMBluez4Adapter *self = NM_BLUEZ4_ADAPTER (user_data); NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); - GHashTable *properties = NULL; GError *err = NULL; - GValue *value; - GPtrArray *devices; + GVariant *ret, *properties; + char **devices; int i; - if (!dbus_g_proxy_end_call (proxy, call, &err, - DBUS_TYPE_G_MAP_OF_VARIANT, &properties, - G_TYPE_INVALID)) { - nm_log_warn (LOGD_BT, "bluez error getting adapter properties: %s", - err && err->message ? err->message : "(unknown)"); + ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, + G_VARIANT_TYPE ("(a{sv})"), &err); + if (!ret) { + g_dbus_error_strip_remote_error (err); + nm_log_warn (LOGD_BT, "bluez error getting adapter properties: %s", err->message); g_error_free (err); goto done; } - value = g_hash_table_lookup (properties, "Address"); - priv->address = value ? g_value_dup_string (value) : NULL; - - value = g_hash_table_lookup (properties, "Devices"); - devices = value ? g_value_get_boxed (value) : NULL; + properties = g_variant_get_child_value (ret, 0); - for (i = 0; devices && i < devices->len; i++) - device_created (priv->proxy, g_ptr_array_index (devices, i), self); + g_variant_lookup (properties, "Address", "s", &priv->address); + if (g_variant_lookup (properties, "Devices", "^ao", &devices)) { + for (i = 0; devices[i]; i++) + device_created (priv->proxy, devices[i], self); + g_strfreev (devices); + } - g_hash_table_unref (properties); + g_variant_unref (properties); + g_variant_unref (ret); priv->initialized = TRUE; @@ -228,16 +224,12 @@ static void query_properties (NMBluez4Adapter *self) { NMBluez4AdapterPrivate *priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); - DBusGProxyCall *call; - - call = dbus_g_proxy_begin_call (priv->proxy, "GetProperties", - get_properties_cb, - self, - NULL, G_TYPE_INVALID); - if (!call) { - nm_log_warn (LOGD_BT, "failed to request Bluetooth adapter properties for %s.", - priv->path); - } + + g_dbus_proxy_call (priv->proxy, "GetProperties", + NULL, + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, + get_properties_cb, self); } /***********************************************************/ @@ -247,34 +239,25 @@ nm_bluez4_adapter_new (const char *path, NMConnectionProvider *provider) { NMBluez4Adapter *self; NMBluez4AdapterPrivate *priv; - DBusGConnection *connection; self = (NMBluez4Adapter *) g_object_new (NM_TYPE_BLUEZ4_ADAPTER, NM_BLUEZ4_ADAPTER_PATH, path, NULL); - if (!self) - return NULL; - priv = NM_BLUEZ4_ADAPTER_GET_PRIVATE (self); priv->provider = provider; - connection = nm_dbus_manager_get_connection (nm_dbus_manager_get ()); - - priv->proxy = dbus_g_proxy_new_for_name (connection, - BLUEZ_SERVICE, - priv->path, - BLUEZ4_ADAPTER_INTERFACE); - - dbus_g_proxy_add_signal (priv->proxy, "DeviceCreated", - DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->proxy, "DeviceCreated", - G_CALLBACK (device_created), self, NULL); - - dbus_g_proxy_add_signal (priv->proxy, "DeviceRemoved", - DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->proxy, "DeviceRemoved", - G_CALLBACK (device_removed), self, NULL); + priv->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, + NULL, + BLUEZ_SERVICE, + priv->path, + BLUEZ4_ADAPTER_INTERFACE, + NULL, NULL); + _nm_dbus_signal_connect (priv->proxy, "DeviceCreated", G_VARIANT_TYPE ("(o)"), + G_CALLBACK (device_created), self); + _nm_dbus_signal_connect (priv->proxy, "DeviceRemoved", G_VARIANT_TYPE ("(o)"), + G_CALLBACK (device_removed), self); query_properties (self); return self; diff --git a/src/devices/bluetooth/nm-bluez4-adapter.h b/src/devices/bluetooth/nm-bluez4-adapter.h index a6256412..a8a2bfb4 100644 --- a/src/devices/bluetooth/nm-bluez4-adapter.h +++ b/src/devices/bluetooth/nm-bluez4-adapter.h @@ -21,9 +21,8 @@ #ifndef __NETWORKMANAGER_BLUEZ4_ADAPTER_H__ #define __NETWORKMANAGER_BLUEZ4_ADAPTER_H__ -#include <glib.h> -#include <glib-object.h> +#include "nm-default.h" #include "nm-bluez-device.h" #include "nm-connection-provider.h" diff --git a/src/devices/bluetooth/nm-bluez4-manager.c b/src/devices/bluetooth/nm-bluez4-manager.c index 23b13d32..c5ba120c 100644 --- a/src/devices/bluetooth/nm-bluez4-manager.c +++ b/src/devices/bluetooth/nm-bluez4-manager.c @@ -24,24 +24,20 @@ #include <signal.h> #include <string.h> #include <stdlib.h> -#include <dbus/dbus-glib.h> -#include "nm-logging.h" -#include "nm-dbus-glib-types.h" +#include "nm-default.h" #include "nm-bluez-manager.h" #include "nm-bluez4-manager.h" #include "nm-bluez4-adapter.h" -#include "nm-dbus-manager.h" #include "nm-bluez-common.h" - +#include "nm-core-internal.h" typedef struct { - NMDBusManager *dbus_mgr; gulong name_owner_changed_id; NMConnectionProvider *provider; - DBusGProxy *proxy; + GDBusProxy *proxy; NMBluez4Adapter *adapter; } NMBluez4ManagerPrivate; @@ -120,7 +116,7 @@ adapter_initialized (NMBluez4Adapter *adapter, gboolean success, gpointer user_d } static void -adapter_removed (DBusGProxy *proxy, const char *path, NMBluez4Manager *self) +adapter_removed (GDBusProxy *proxy, const char *path, NMBluez4Manager *self) { NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); @@ -140,7 +136,7 @@ adapter_removed (DBusGProxy *proxy, const char *path, NMBluez4Manager *self) } static void -default_adapter_changed (DBusGProxy *proxy, const char *path, NMBluez4Manager *self) +default_adapter_changed (GDBusProxy *proxy, const char *path, NMBluez4Manager *self) { NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); const char *cur_path = NULL; @@ -166,130 +162,65 @@ default_adapter_changed (DBusGProxy *proxy, const char *path, NMBluez4Manager *s } static void -default_adapter_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +default_adapter_cb (GObject *proxy, GAsyncResult *result, gpointer user_data) { NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data); NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - const char *default_adapter = NULL; + GVariant *ret; GError *err = NULL; - if (!dbus_g_proxy_end_call (proxy, call, &err, - DBUS_TYPE_G_OBJECT_PATH, &default_adapter, - G_TYPE_INVALID)) { + ret = _nm_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), result, + G_VARIANT_TYPE ("(o)"), &err); + if (ret) { + const char *default_adapter; + + g_variant_get (ret, "(&o)", &default_adapter); + default_adapter_changed (priv->proxy, default_adapter, self); + g_variant_unref (ret); + } else { /* Ignore "No such adapter" errors; just means bluetooth isn't active */ - if ( !dbus_g_error_has_name (err, "org.bluez.Error.NoSuchAdapter") - && !dbus_g_error_has_name (err, "org.freedesktop.systemd1.LoadFailed") - && !g_error_matches (err, DBUS_GERROR, DBUS_GERROR_SERVICE_UNKNOWN)) { + if ( !_nm_dbus_error_has_name (err, "org.bluez.Error.NoSuchAdapter") + && !_nm_dbus_error_has_name (err, "org.freedesktop.systemd1.LoadFailed") + && !g_error_matches (err, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) { + g_dbus_error_strip_remote_error (err); nm_log_warn (LOGD_BT, "bluez error getting default adapter: %s", - err && err->message ? err->message : "(unknown)"); + err->message); } g_error_free (err); - return; } - - default_adapter_changed (priv->proxy, default_adapter, self); } static void query_default_adapter (NMBluez4Manager *self) { NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - DBusGProxyCall *call; - - call = dbus_g_proxy_begin_call (priv->proxy, "DefaultAdapter", - default_adapter_cb, - self, - NULL, G_TYPE_INVALID); - if (!call) - nm_log_warn (LOGD_BT, "failed to request default Bluetooth adapter."); -} - -static void -bluez_connect (NMBluez4Manager *self) -{ - NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - DBusGConnection *connection; - - g_return_if_fail (priv->proxy == NULL); - connection = nm_dbus_manager_get_connection (priv->dbus_mgr); - if (!connection) - return; - - priv->proxy = dbus_g_proxy_new_for_name (connection, - BLUEZ_SERVICE, - BLUEZ_MANAGER_PATH, - BLUEZ4_MANAGER_INTERFACE); - - dbus_g_proxy_add_signal (priv->proxy, "AdapterRemoved", - DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->proxy, "AdapterRemoved", - G_CALLBACK (adapter_removed), self, NULL); - - dbus_g_proxy_add_signal (priv->proxy, "DefaultAdapterChanged", - DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->proxy, "DefaultAdapterChanged", - G_CALLBACK (default_adapter_changed), self, NULL); - - query_default_adapter (self); + g_dbus_proxy_call (priv->proxy, "DefaultAdapter", + NULL, + G_DBUS_CALL_FLAGS_NONE, -1, + NULL, + default_adapter_cb, self); } static void -name_owner_changed_cb (NMDBusManager *dbus_mgr, - const char *name, - const char *old_owner, - const char *new_owner, +name_owner_changed_cb (GObject *object, + GParamSpec *pspec, gpointer user_data) { NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data); NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - gboolean old_owner_good = (old_owner && strlen (old_owner)); - gboolean new_owner_good = (new_owner && strlen (new_owner)); + char *owner; - /* Can't handle the signal if its not from the Bluez */ - if (strcmp (BLUEZ_SERVICE, name)) - return; - - if (!old_owner_good && new_owner_good) + owner = g_dbus_proxy_get_name_owner (priv->proxy); + if (owner) { query_default_adapter (self); - else if (old_owner_good && !new_owner_good) { + g_free (owner); + } else { /* Throwing away the adapter removes all devices too */ - if (priv->adapter) { - g_object_unref (priv->adapter); - priv->adapter = NULL; - } + g_clear_object (&priv->adapter); } } -static void -bluez_cleanup (NMBluez4Manager *self, gboolean do_signal) -{ - NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - - if (priv->proxy) { - g_object_unref (priv->proxy); - priv->proxy = NULL; - } - - if (priv->adapter) { - g_object_unref (priv->adapter); - priv->adapter = NULL; - } -} - -static void -dbus_connection_changed_cb (NMDBusManager *dbus_mgr, - DBusGConnection *connection, - gpointer user_data) -{ - NMBluez4Manager *self = NM_BLUEZ4_MANAGER (user_data); - - if (!connection) - bluez_cleanup (self, TRUE); - else - bluez_connect (self); -} - /****************************************************************/ NMBluez4Manager * @@ -307,20 +238,21 @@ nm_bluez4_manager_init (NMBluez4Manager *self) { NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - priv->dbus_mgr = nm_dbus_manager_get (); - g_assert (priv->dbus_mgr); + priv->proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, + NULL, + BLUEZ_SERVICE, + BLUEZ_MANAGER_PATH, + BLUEZ4_MANAGER_INTERFACE, + NULL, NULL); + _nm_dbus_signal_connect (priv->proxy, "AdapterRemoved", G_VARIANT_TYPE ("(o)"), + G_CALLBACK (adapter_removed), self); + _nm_dbus_signal_connect (priv->proxy, "DefaultAdapterChanged", G_VARIANT_TYPE ("(o)"), + G_CALLBACK (default_adapter_changed), self); + g_signal_connect (priv->proxy, "notify::g-name-owner", + G_CALLBACK (name_owner_changed_cb), self); - g_signal_connect (priv->dbus_mgr, - NM_DBUS_MANAGER_NAME_OWNER_CHANGED, - G_CALLBACK (name_owner_changed_cb), - self); - - g_signal_connect (priv->dbus_mgr, - NM_DBUS_MANAGER_DBUS_CONNECTION_CHANGED, - G_CALLBACK (dbus_connection_changed_cb), - self); - - bluez_connect (self); + query_default_adapter (self); } static void @@ -329,13 +261,8 @@ dispose (GObject *object) NMBluez4Manager *self = NM_BLUEZ4_MANAGER (object); NMBluez4ManagerPrivate *priv = NM_BLUEZ4_MANAGER_GET_PRIVATE (self); - bluez_cleanup (self, FALSE); - - if (priv->dbus_mgr) { - g_signal_handlers_disconnect_by_func (priv->dbus_mgr, name_owner_changed_cb, self); - g_signal_handlers_disconnect_by_func (priv->dbus_mgr, dbus_connection_changed_cb, self); - priv->dbus_mgr = NULL; - } + g_clear_object (&priv->proxy); + g_clear_object (&priv->adapter); G_OBJECT_CLASS (nm_bluez4_manager_parent_class)->dispose (object); } diff --git a/src/devices/bluetooth/nm-bluez4-manager.h b/src/devices/bluetooth/nm-bluez4-manager.h index 13cfef93..f6bf7658 100644 --- a/src/devices/bluetooth/nm-bluez4-manager.h +++ b/src/devices/bluetooth/nm-bluez4-manager.h @@ -22,11 +22,8 @@ #ifndef __NETWORKMANAGER_BLUEZ4_MANAGER_H__ #define __NETWORKMANAGER_BLUEZ4_MANAGER_H__ -#include <glib.h> -#include <glib-object.h> - -#include <config.h> -#include "nm-connection-provider.h" +#include "nm-default.h" +#include "nm-connection-provider.h" G_BEGIN_DECLS diff --git a/src/devices/bluetooth/nm-bluez5-dun.c b/src/devices/bluetooth/nm-bluez5-dun.c index a97eaa77..875a662f 100644 --- a/src/devices/bluetooth/nm-bluez5-dun.c +++ b/src/devices/bluetooth/nm-bluez5-dun.c @@ -32,7 +32,7 @@ #include "nm-bluez5-dun.h" #include "nm-bt-error.h" -#include "nm-logging.h" +#include "nm-default.h" #include "NetworkManagerUtils.h" struct _NMBluez5DunContext { @@ -137,10 +137,7 @@ sdp_search_cleanup (NMBluez5DunContext *context) context->sdp_session = NULL; } - if (context->sdp_watch_id) { - g_source_remove (context->sdp_watch_id); - context->sdp_watch_id = 0; - } + nm_clear_g_source (&context->sdp_watch_id); } static void diff --git a/src/devices/bluetooth/nm-bluez5-dun.h b/src/devices/bluetooth/nm-bluez5-dun.h index 7e259725..c59cbb80 100644 --- a/src/devices/bluetooth/nm-bluez5-dun.h +++ b/src/devices/bluetooth/nm-bluez5-dun.h @@ -21,8 +21,7 @@ #ifndef _NM_BLUEZ5_UTILS_H_ #define _NM_BLUEZ5_UTILS_H_ -#include <glib.h> -#include <gio/gio.h> +#include "nm-default.h" typedef struct _NMBluez5DunContext NMBluez5DunContext; diff --git a/src/devices/bluetooth/nm-bluez5-manager.c b/src/devices/bluetooth/nm-bluez5-manager.c index b8568523..c9f5828d 100644 --- a/src/devices/bluetooth/nm-bluez5-manager.c +++ b/src/devices/bluetooth/nm-bluez5-manager.c @@ -25,20 +25,16 @@ #include <signal.h> #include <string.h> #include <stdlib.h> -#include <gio/gio.h> -#include "nm-logging.h" +#include "nm-default.h" #include "nm-bluez-manager.h" #include "nm-bluez5-manager.h" #include "nm-bluez-device.h" #include "nm-bluez-common.h" -#include "nm-dbus-manager.h" +#include "nm-core-internal.h" typedef struct { - NMDBusManager *dbus_mgr; - gulong name_owner_changed_id; - NMConnectionProvider *provider; GDBusProxy *proxy; @@ -170,39 +166,23 @@ device_removed (GDBusProxy *proxy, const gchar *path, NMBluez5Manager *self) } static void -object_manager_g_signal (GDBusProxy *proxy, - gchar *sender_name, - gchar *signal_name, - GVariant *parameters, - NMBluez5Manager *self) +object_manager_interfaces_added (GDBusProxy *proxy, + const char *path, + GVariant *dict, + NMBluez5Manager *self) { - GVariant *variant; - const gchar *path; - - if (!strcmp (signal_name, "InterfacesRemoved")) { - const gchar **ifaces; - gsize i, length; - - g_variant_get (parameters, "(&o*)", &path, &variant); - - ifaces = g_variant_get_strv (variant, &length); - - for (i = 0; i < length; i++) { - if (!strcmp (ifaces[i], BLUEZ5_DEVICE_INTERFACE)) { - device_removed (proxy, path, self); - break; - } - } - - g_free (ifaces); - - } else if (!strcmp (signal_name, "InterfacesAdded")) { - g_variant_get (parameters, "(&o*)", &path, &variant); + if (g_variant_lookup (dict, BLUEZ5_DEVICE_INTERFACE, "a{sv}", NULL)) + device_added (proxy, path, self); +} - if (g_variant_lookup_value (variant, BLUEZ5_DEVICE_INTERFACE, - G_VARIANT_TYPE_DICTIONARY)) - device_added (proxy, path, self); - } +static void +object_manager_interfaces_removed (GDBusProxy *proxy, + const char *path, + const char **ifaces, + NMBluez5Manager *self) +{ + if (_nm_utils_string_in_list (BLUEZ5_DEVICE_INTERFACE, ifaces)) + device_removed (proxy, path, self); } static void @@ -215,14 +195,15 @@ get_managed_objects_cb (GDBusProxy *proxy, GError *error = NULL; const char *path; - variant = g_dbus_proxy_call_finish (proxy, res, &error); - + variant = _nm_dbus_proxy_call_finish (proxy, res, + G_VARIANT_TYPE ("(a{oa{sa{sv}}})"), + &error); if (!variant) { if (g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) nm_log_warn (LOGD_BT, "Couldn't get managed objects: not running Bluez5?"); else { - nm_log_warn (LOGD_BT, "Couldn't get managed objects: %s", - error && error->message ? error->message : "(unknown)"); + g_dbus_error_strip_remote_error (error); + nm_log_warn (LOGD_BT, "Couldn't get managed objects: %s", error->message); } g_clear_error (&error); return; @@ -238,6 +219,8 @@ get_managed_objects_cb (GDBusProxy *proxy, g_variant_unref (variant); } +static void name_owner_changed_cb (GObject *object, GParamSpec *pspec, gpointer user_data); + static void on_proxy_acquired (GObject *object, GAsyncResult *res, @@ -255,6 +238,9 @@ on_proxy_acquired (GObject *object, return; } + g_signal_connect (priv->proxy, "notify::g-name-owner", + G_CALLBACK (name_owner_changed_cb), self); + /* Get already managed devices. */ g_dbus_proxy_call (priv->proxy, "GetManagedObjects", NULL, @@ -264,8 +250,10 @@ on_proxy_acquired (GObject *object, (GAsyncReadyCallback) get_managed_objects_cb, self); - g_signal_connect (priv->proxy, "g-signal", - G_CALLBACK (object_manager_g_signal), self); + _nm_dbus_signal_connect (priv->proxy, "InterfacesAdded", G_VARIANT_TYPE ("(oa{sa{sv}})"), + G_CALLBACK (object_manager_interfaces_added), self); + _nm_dbus_signal_connect (priv->proxy, "InterfacesRemoved", G_VARIANT_TYPE ("(oas)"), + G_CALLBACK (object_manager_interfaces_removed), self); } static void @@ -287,24 +275,19 @@ bluez_connect (NMBluez5Manager *self) } static void -name_owner_changed_cb (NMDBusManager *dbus_mgr, - const char *name, - const char *old_owner, - const char *new_owner, +name_owner_changed_cb (GObject *object, + GParamSpec *pspec, gpointer user_data) { NMBluez5Manager *self = NM_BLUEZ5_MANAGER (user_data); NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); - gboolean old_owner_good = (old_owner && strlen (old_owner)); - gboolean new_owner_good = (new_owner && strlen (new_owner)); + char *owner; - /* Can't handle the signal if its not from the Bluez */ - if (strcmp (BLUEZ_SERVICE, name)) - return; - - if (old_owner_good && !new_owner_good) { - if (priv->devices) + if (priv->devices) { + owner = g_dbus_proxy_get_name_owner (priv->proxy); + if (!owner) remove_all_devices (self); + g_free (owner); } } @@ -314,8 +297,8 @@ bluez_cleanup (NMBluez5Manager *self, gboolean do_signal) NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); if (priv->proxy) { - g_object_unref (priv->proxy); - priv->proxy = NULL; + g_signal_handlers_disconnect_by_func (priv->proxy, G_CALLBACK (name_owner_changed_cb), self); + g_clear_object (&priv->proxy); } if (do_signal) @@ -324,19 +307,6 @@ bluez_cleanup (NMBluez5Manager *self, gboolean do_signal) g_hash_table_remove_all (priv->devices); } -static void -dbus_connection_changed_cb (NMDBusManager *dbus_mgr, - DBusGConnection *connection, - gpointer user_data) -{ - NMBluez5Manager *self = NM_BLUEZ5_MANAGER (user_data); - - if (!connection) - bluez_cleanup (self, TRUE); - else - bluez_connect (self); -} - /****************************************************************/ NMBluez5Manager * @@ -354,19 +324,6 @@ nm_bluez5_manager_init (NMBluez5Manager *self) { NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); - priv->dbus_mgr = nm_dbus_manager_get (); - g_assert (priv->dbus_mgr); - - g_signal_connect (priv->dbus_mgr, - NM_DBUS_MANAGER_NAME_OWNER_CHANGED, - G_CALLBACK (name_owner_changed_cb), - self); - - g_signal_connect (priv->dbus_mgr, - NM_DBUS_MANAGER_DBUS_CONNECTION_CHANGED, - G_CALLBACK (dbus_connection_changed_cb), - self); - bluez_connect (self); priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, @@ -377,16 +334,9 @@ static void dispose (GObject *object) { NMBluez5Manager *self = NM_BLUEZ5_MANAGER (object); - NMBluez5ManagerPrivate *priv = NM_BLUEZ5_MANAGER_GET_PRIVATE (self); bluez_cleanup (self, FALSE); - if (priv->dbus_mgr) { - g_signal_handlers_disconnect_by_func (priv->dbus_mgr, name_owner_changed_cb, self); - g_signal_handlers_disconnect_by_func (priv->dbus_mgr, dbus_connection_changed_cb, self); - priv->dbus_mgr = NULL; - } - G_OBJECT_CLASS (nm_bluez5_manager_parent_class)->dispose (object); } diff --git a/src/devices/bluetooth/nm-bluez5-manager.h b/src/devices/bluetooth/nm-bluez5-manager.h index 8152976d..ae5512f8 100644 --- a/src/devices/bluetooth/nm-bluez5-manager.h +++ b/src/devices/bluetooth/nm-bluez5-manager.h @@ -22,11 +22,8 @@ #ifndef __NETWORKMANAGER_BLUEZ5_MANAGER_H__ #define __NETWORKMANAGER_BLUEZ5_MANAGER_H__ -#include <glib.h> -#include <glib-object.h> - -#include <config.h> -#include "nm-connection-provider.h" +#include "nm-default.h" +#include "nm-connection-provider.h" G_BEGIN_DECLS diff --git a/src/devices/bluetooth/nm-bt-enum-types.c b/src/devices/bluetooth/nm-bt-enum-types.c index 16741c9f..207055e1 100644 --- a/src/devices/bluetooth/nm-bt-enum-types.c +++ b/src/devices/bluetooth/nm-bt-enum-types.c @@ -3,6 +3,8 @@ /* Generated by glib-mkenums. Do not edit */ +#include "config.h" + #include "nm-bt-enum-types.h" #include "nm-bt-error.h" diff --git a/src/devices/bluetooth/nm-bt-error.c b/src/devices/bluetooth/nm-bt-error.c index e3b8e7f5..9c35d8b6 100644 --- a/src/devices/bluetooth/nm-bt-error.c +++ b/src/devices/bluetooth/nm-bt-error.c @@ -20,7 +20,7 @@ #include "config.h" -#include <glib.h> +#include "nm-default.h" #include "nm-bt-error.h" GQuark diff --git a/src/devices/bluetooth/nm-device-bt-glue.h b/src/devices/bluetooth/nm-device-bt-glue.h deleted file mode 100644 index b6f851b2..00000000 --- a/src/devices/bluetooth/nm-device-bt-glue.h +++ /dev/null @@ -1,73 +0,0 @@ -/* Generated by dbus-binding-tool; do not edit! */ - - -#ifndef __dbus_glib_marshal_nm_device_bt_MARSHAL_H__ -#define __dbus_glib_marshal_nm_device_bt_MARSHAL_H__ - -#include <glib-object.h> - -G_BEGIN_DECLS - -#ifdef G_ENABLE_DEBUG -#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) -#define g_marshal_value_peek_char(v) g_value_get_schar (v) -#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) -#define g_marshal_value_peek_int(v) g_value_get_int (v) -#define g_marshal_value_peek_uint(v) g_value_get_uint (v) -#define g_marshal_value_peek_long(v) g_value_get_long (v) -#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) -#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) -#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) -#define g_marshal_value_peek_enum(v) g_value_get_enum (v) -#define g_marshal_value_peek_flags(v) g_value_get_flags (v) -#define g_marshal_value_peek_float(v) g_value_get_float (v) -#define g_marshal_value_peek_double(v) g_value_get_double (v) -#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) -#define g_marshal_value_peek_param(v) g_value_get_param (v) -#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) -#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) -#define g_marshal_value_peek_object(v) g_value_get_object (v) -#define g_marshal_value_peek_variant(v) g_value_get_variant (v) -#else /* !G_ENABLE_DEBUG */ -/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. - * Do not access GValues directly in your code. Instead, use the - * g_value_get_*() functions - */ -#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int -#define g_marshal_value_peek_char(v) (v)->data[0].v_int -#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint -#define g_marshal_value_peek_int(v) (v)->data[0].v_int -#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint -#define g_marshal_value_peek_long(v) (v)->data[0].v_long -#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong -#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 -#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 -#define g_marshal_value_peek_enum(v) (v)->data[0].v_long -#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong -#define g_marshal_value_peek_float(v) (v)->data[0].v_float -#define g_marshal_value_peek_double(v) (v)->data[0].v_double -#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer -#endif /* !G_ENABLE_DEBUG */ - - -G_END_DECLS - -#endif /* __dbus_glib_marshal_nm_device_bt_MARSHAL_H__ */ - -#include <dbus/dbus-glib.h> -static const DBusGMethodInfo dbus_glib_nm_device_bt_methods[] = { -}; - -const DBusGObjectInfo dbus_glib_nm_device_bt_object_info = { 1, - dbus_glib_nm_device_bt_methods, - 0, -"\0", -"org.freedesktop.NetworkManager.Device.Bluetooth\0PropertiesChanged\0\0", -"org.freedesktop.NetworkManager.Device.Bluetooth\0HwAddress\0hw_address\0read\0org.freedesktop.NetworkManager.Device.Bluetooth\0Name\0name\0read\0org.freedesktop.NetworkManager.Device.Bluetooth\0BtCapabilities\0bt_capabilities\0read\0\0" -}; - diff --git a/src/devices/bluetooth/nm-device-bt.c b/src/devices/bluetooth/nm-device-bt.c index 88033e2e..1e3f9cdc 100644 --- a/src/devices/bluetooth/nm-device-bt.c +++ b/src/devices/bluetooth/nm-device-bt.c @@ -23,16 +23,11 @@ #include <stdio.h> #include <string.h> -#include <glib/gi18n.h> -#include <gio/gio.h> - -#include "nm-glib-compat.h" +#include "nm-default.h" #include "nm-bluez-common.h" #include "nm-bluez-device.h" -#include "nm-dbus-manager.h" #include "nm-device-bt.h" #include "nm-device-private.h" -#include "nm-logging.h" #include "ppp-manager/nm-ppp-manager.h" #include "nm-setting-connection.h" #include "nm-setting-bluetooth.h" @@ -40,14 +35,17 @@ #include "nm-setting-gsm.h" #include "nm-setting-serial.h" #include "nm-setting-ppp.h" -#include "nm-device-bt-glue.h" #include "NetworkManagerUtils.h" #include "nm-bt-enum-types.h" #include "nm-utils.h" #include "nm-bt-error.h" #include "nm-bt-enum-types.h" -#define MM_DBUS_SERVICE "org.freedesktop.ModemManager1" +#include "nmdbus-device-bt.h" + +#define MM_DBUS_SERVICE "org.freedesktop.ModemManager1" +#define MM_DBUS_PATH "/org/freedesktop/ModemManager1" +#define MM_DBUS_INTERFACE "org.freedesktop.ModemManager1" #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceBt); @@ -59,8 +57,7 @@ G_DEFINE_TYPE (NMDeviceBt, nm_device_bt, NM_TYPE_DEVICE) static gboolean modem_stage1 (NMDeviceBt *self, NMModem *modem, NMDeviceStateReason *reason); typedef struct { - NMDBusManager *dbus_mgr; - guint mm_watch_id; + GDBusProxy *mm_proxy; gboolean mm_running; NMBluezDevice *bt_device; @@ -461,7 +458,7 @@ modem_prepare_result (NMModem *modem, * the device to be auto-activated anymore, which would risk locking * the SIM if the incorrect PIN continues to be used. */ - g_object_set (G_OBJECT (device), NM_DEVICE_AUTOCONNECT, FALSE, NULL); + nm_device_set_autoconnect (device, FALSE); _LOGI (LOGD_MB, "disabling autoconnect due to failed SIM PIN"); } @@ -635,10 +632,7 @@ component_added (NMDevice *device, GObject *component) g_free (base); /* Got the modem */ - if (priv->timeout_id) { - g_source_remove (priv->timeout_id); - priv->timeout_id = 0; - } + nm_clear_g_source (&priv->timeout_id); /* Can only accept the modem in stage2, but since the interface matched * what we were expecting, don't let anything else claim the modem either. @@ -706,10 +700,7 @@ check_connect_continue (NMDeviceBt *self) dun ? "DUN" : (pan ? "PAN" : "unknown")); /* Kill the connect timeout since we're connected now */ - if (priv->timeout_id) { - g_source_remove (priv->timeout_id); - priv->timeout_id = 0; - } + nm_clear_g_source (&priv->timeout_id); if (pan) { /* Bluez says we're connected now. Start IP config. */ @@ -824,7 +815,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (device); NMConnection *connection; - connection = nm_device_get_connection (device); + connection = nm_device_get_applied_connection (device); g_assert (connection); priv->bt_type = get_connection_bt_type (connection); if (priv->bt_type == NM_BT_CAPABILITY_NONE) { @@ -914,10 +905,7 @@ deactivate (NMDevice *device) if (priv->bt_type != NM_BT_CAPABILITY_NONE) nm_bluez_device_disconnect (priv->bt_device); - if (priv->timeout_id) { - g_source_remove (priv->timeout_id); - priv->timeout_id = 0; - } + nm_clear_g_source (&priv->timeout_id); priv->bt_type = NM_BT_CAPABILITY_NONE; @@ -967,25 +955,17 @@ set_mm_running (NMDeviceBt *self, gboolean running) } static void -mm_name_owner_changed (NMDBusManager *dbus_mgr, - const char *name, - const char *old_owner, - const char *new_owner, +mm_name_owner_changed (GObject *object, + GParamSpec *pspec, NMDeviceBt *self) { - gboolean old_owner_good; - gboolean new_owner_good; - - /* Can't handle the signal if its not from the modem service */ - if (strcmp (MM_DBUS_SERVICE, name) != 0) - return; - - old_owner_good = (old_owner && strlen (old_owner)); - new_owner_good = (new_owner && strlen (new_owner)); + char *owner; - if (!old_owner_good && new_owner_good) + owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (object)); + if (owner) { set_mm_running (self, TRUE); - else if (old_owner_good && !new_owner_good) + g_free (owner); + } else set_mm_running (self, FALSE); } @@ -1021,18 +1001,27 @@ static void nm_device_bt_init (NMDeviceBt *self) { NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (self); - gboolean mm_running; - - priv->dbus_mgr = nm_dbus_manager_get (); - - priv->mm_watch_id = g_signal_connect (priv->dbus_mgr, - NM_DBUS_MANAGER_NAME_OWNER_CHANGED, - G_CALLBACK (mm_name_owner_changed), - self); + GError *error = NULL; - /* Initial check to see if ModemManager is running */ - mm_running = nm_dbus_manager_name_has_owner (priv->dbus_mgr, MM_DBUS_SERVICE); - set_mm_running (self, mm_running); + priv->mm_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | + G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, + NULL, + MM_DBUS_SERVICE, + MM_DBUS_PATH, + MM_DBUS_INTERFACE, + NULL, &error); + if (priv->mm_proxy) { + g_signal_connect (priv->mm_proxy, "notify::g-name-owner", + G_CALLBACK (mm_name_owner_changed), + self); + mm_name_owner_changed (G_OBJECT (priv->mm_proxy), NULL, self); + } else { + _LOGW (LOGD_MB, "Could not create proxy for '%s': %s", + MM_DBUS_SERVICE, error->message); + g_clear_error (&error); + } } static void @@ -1106,18 +1095,14 @@ dispose (GObject *object) { NMDeviceBtPrivate *priv = NM_DEVICE_BT_GET_PRIVATE (object); - if (priv->timeout_id) { - g_source_remove (priv->timeout_id); - priv->timeout_id = 0; - } + nm_clear_g_source (&priv->timeout_id); g_signal_handlers_disconnect_matched (priv->bt_device, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, object); - if (priv->dbus_mgr && priv->mm_watch_id) { - g_signal_handler_disconnect (priv->dbus_mgr, priv->mm_watch_id); - priv->mm_watch_id = 0; + if (priv->mm_proxy) { + g_signal_handlers_disconnect_by_func (priv->mm_proxy, G_CALLBACK (mm_name_owner_changed), object); + g_clear_object (&priv->mm_proxy); } - priv->dbus_mgr = NULL; modem_cleanup (NM_DEVICE_BT (object)); g_clear_object (&priv->bt_device); @@ -1197,7 +1182,7 @@ nm_device_bt_class_init (NMDeviceBtClass *klass) G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); - nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), - G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_bt_object_info); + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_BLUETOOTH_SKELETON, + NULL); } diff --git a/src/devices/bluetooth/nm-device-bt.h b/src/devices/bluetooth/nm-device-bt.h index c1e95d91..c565745f 100644 --- a/src/devices/bluetooth/nm-device-bt.h +++ b/src/devices/bluetooth/nm-device-bt.h @@ -21,7 +21,7 @@ #ifndef __NETWORKMANAGER_DEVICE_BT_H__ #define __NETWORKMANAGER_DEVICE_BT_H__ -#include <nm-device.h> +#include "nm-device.h" #include "nm-bluez-device.h" #include "nm-modem.h" diff --git a/src/devices/nm-device-bond.c b/src/devices/nm-device-bond.c index afcba3b3..dfd1de6d 100644 --- a/src/devices/nm-device-bond.c +++ b/src/devices/nm-device-bond.c @@ -20,26 +20,20 @@ #include "config.h" -#include <glib.h> -#include <glib/gi18n.h> - #include <errno.h> #include <stdlib.h> -#include "gsystem-local-alloc.h" +#include "nm-default.h" #include "nm-device-bond.h" -#include "nm-logging.h" #include "NetworkManagerUtils.h" #include "nm-device-private.h" #include "nm-platform.h" -#include "nm-dbus-glib-types.h" -#include "nm-dbus-manager.h" #include "nm-enum-types.h" #include "nm-device-factory.h" #include "nm-core-internal.h" #include "nm-ip4-config.h" -#include "nm-device-bond-glue.h" +#include "nmdbus-device-bond.h" #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceBond); @@ -52,13 +46,6 @@ typedef struct { int dummy; } NMDeviceBondPrivate; -enum { - PROP_0, - PROP_SLAVES, - - LAST_PROP -}; - /******************************************************************/ static NMDeviceCapabilities @@ -143,7 +130,7 @@ set_bond_attr (NMDevice *device, const char *attr, const char *value) gboolean ret; int ifindex = nm_device_get_ifindex (device); - ret = nm_platform_master_set_option (NM_PLATFORM_GET, ifindex, attr, value); + ret = nm_platform_sysctl_master_set_option (NM_PLATFORM_GET, ifindex, attr, value); if (!ret) _LOGW (LOGD_HW, "failed to set bonding attribute '%s' to '%s'", attr, value); return ret; @@ -177,7 +164,7 @@ update_connection (NMDevice *device, NMConnection *connection) /* Read bond options from sysfs and update the Bond setting to match */ options = nm_setting_bond_get_valid_options (s_bond); while (options && *options) { - gs_free char *value = nm_platform_master_get_option (NM_PLATFORM_GET, ifindex, *options); + gs_free char *value = nm_platform_sysctl_master_get_option (NM_PLATFORM_GET, ifindex, *options); const char *defvalue = nm_setting_bond_get_option_default (s_bond, *options); if (value && !ignore_if_zero (*options, value) && (g_strcmp0 (value, defvalue) != 0)) { @@ -270,7 +257,7 @@ apply_bonding_config (NMDevice *device) * arp_interval doesn't require miimon to be 0 */ - connection = nm_device_get_connection (device); + connection = nm_device_get_applied_connection (device); g_assert (connection); s_bond = nm_connection_get_setting_bond (connection); g_assert (s_bond); @@ -333,7 +320,7 @@ apply_bonding_config (NMDevice *device) } /* Clear ARP targets */ - contents = nm_platform_master_get_option (NM_PLATFORM_GET, ifindex, "arp_ip_target"); + contents = nm_platform_sysctl_master_get_option (NM_PLATFORM_GET, ifindex, "arp_ip_target"); set_arp_targets (device, contents, " \n", "-"); g_free (contents); @@ -383,7 +370,7 @@ ip4_config_pre_commit (NMDevice *self, NMIP4Config *config) NMSettingWired *s_wired; guint32 mtu; - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); g_assert (connection); s_wired = nm_connection_get_setting_wired (connection); @@ -421,17 +408,16 @@ enslave_slave (NMDevice *device, } else _LOGI (LOGD_BOND, "bond slave %s was enslaved", slave_iface); - g_object_notify (G_OBJECT (device), NM_DEVICE_BOND_SLAVES); return TRUE; } -static gboolean +static void release_slave (NMDevice *device, NMDevice *slave, gboolean configure) { NMDeviceBond *self = NM_DEVICE_BOND (device); - gboolean success = TRUE, no_firmware = FALSE; + gboolean success, no_firmware = FALSE; if (configure) { success = nm_platform_link_release (NM_PLATFORM_GET, @@ -445,65 +431,48 @@ release_slave (NMDevice *device, _LOGW (LOGD_BOND, "failed to release bond slave %s", nm_device_get_ip_iface (slave)); } - } else { - _LOGI (LOGD_BOND, "bond slave %s was released", - nm_device_get_ip_iface (slave)); - } - - if (success) - g_object_notify (G_OBJECT (device), NM_DEVICE_BOND_SLAVES); - if (configure) { /* Kernel bonding code "closes" the slave when releasing it, (which clears * IFF_UP), so we must bring it back up here to ensure carrier changes and * other state is noticed by the now-released slave. */ if (!nm_device_bring_up (slave, TRUE, &no_firmware)) _LOGW (LOGD_BOND, "released bond slave could not be brought up."); + } else { + _LOGI (LOGD_BOND, "bond slave %s was released", + nm_device_get_ip_iface (slave)); } - - return success; } -/******************************************************************/ - -static void -nm_device_bond_init (NMDeviceBond * self) +static gboolean +create_and_realize (NMDevice *device, + NMConnection *connection, + NMDevice *parent, + const NMPlatformLink **out_plink, + GError **error) { -} + const char *iface = nm_device_get_iface (device); + NMPlatformError plerr; -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - GPtrArray *slaves; - GSList *list, *iter; - - switch (prop_id) { - break; - case PROP_SLAVES: - slaves = g_ptr_array_new (); - list = nm_device_master_get_slaves (NM_DEVICE (object)); - for (iter = list; iter; iter = iter->next) - g_ptr_array_add (slaves, g_strdup (nm_device_get_path (NM_DEVICE (iter->data)))); - g_slist_free (list); - g_value_take_boxed (value, slaves); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; + g_assert (iface); + + plerr = nm_platform_link_bond_add (NM_PLATFORM_GET, iface, out_plink); + if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, + "Failed to create bond interface '%s' for '%s': %s", + iface, + nm_connection_get_id (connection), + nm_platform_error_to_string (plerr)); + return FALSE; } + return TRUE; } +/******************************************************************/ + static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) +nm_device_bond_init (NMDeviceBond * self) { - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } } static void @@ -514,11 +483,7 @@ nm_device_bond_class_init (NMDeviceBondClass *klass) g_type_class_add_private (object_class, sizeof (NMDeviceBondPrivate)); - parent_class->connection_type = NM_SETTING_BOND_SETTING_NAME; - - /* virtual methods */ - object_class->get_property = get_property; - object_class->set_property = set_property; + NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_BOND_SETTING_NAME, NM_LINK_TYPE_BOND) parent_class->get_generic_capabilities = get_generic_capabilities; parent_class->is_available = is_available; @@ -529,22 +494,15 @@ nm_device_bond_class_init (NMDeviceBondClass *klass) parent_class->update_connection = update_connection; parent_class->master_update_slave_connection = master_update_slave_connection; + parent_class->create_and_realize = create_and_realize; parent_class->act_stage1_prepare = act_stage1_prepare; parent_class->ip4_config_pre_commit = ip4_config_pre_commit; parent_class->enslave_slave = enslave_slave; parent_class->release_slave = release_slave; - /* properties */ - g_object_class_install_property - (object_class, PROP_SLAVES, - g_param_spec_boxed (NM_DEVICE_BOND_SLAVES, "", "", - DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), - G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_bond_object_info); + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_BOND_SKELETON, + NULL); } /*************************************************************/ @@ -553,45 +511,18 @@ nm_device_bond_class_init (NMDeviceBondClass *klass) #define NM_BOND_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BOND_FACTORY, NMBondFactory)) static NMDevice * -new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error) -{ - return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BOND, - NM_DEVICE_PLATFORM_DEVICE, plink, - NM_DEVICE_DRIVER, "bonding", - NM_DEVICE_TYPE_DESC, "Bond", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BOND, - NM_DEVICE_IS_MASTER, TRUE, - NULL); -} - -static NMDevice * -create_virtual_device_for_connection (NMDeviceFactory *factory, - NMConnection *connection, - NMDevice *parent, - GError **error) +create_device (NMDeviceFactory *factory, + const char *iface, + const NMPlatformLink *plink, + NMConnection *connection, + gboolean *out_ignore) { - const char *iface = nm_connection_get_interface_name (connection); - NMPlatformError plerr; - const NMPlatformLink *plink; - - g_assert (iface); - - plerr = nm_platform_bond_add (NM_PLATFORM_GET, iface, NULL); - if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { - g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, - "Failed to create bond interface '%s' for '%s': %s", - iface, - nm_connection_get_id (connection), - nm_platform_error_to_string (plerr)); - return NULL; - } - plink = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, iface); - return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BOND, - NM_DEVICE_PLATFORM_DEVICE, plink, + NM_DEVICE_IFACE, iface, NM_DEVICE_DRIVER, "bonding", NM_DEVICE_TYPE_DESC, "Bond", NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BOND, + NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_BOND, NM_DEVICE_IS_MASTER, TRUE, NULL); } @@ -599,7 +530,6 @@ create_virtual_device_for_connection (NMDeviceFactory *factory, NM_DEVICE_FACTORY_DEFINE_INTERNAL (BOND, Bond, bond, NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_BOND) NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_BOND_SETTING_NAME), - factory_iface->new_link = new_link; - factory_iface->create_virtual_device_for_connection = create_virtual_device_for_connection; + factory_iface->create_device = create_device; ) diff --git a/src/devices/nm-device-bond.h b/src/devices/nm-device-bond.h index 17217a57..9e86719e 100644 --- a/src/devices/nm-device-bond.h +++ b/src/devices/nm-device-bond.h @@ -21,8 +21,6 @@ #ifndef __NETWORKMANAGER_DEVICE_BOND_H__ #define __NETWORKMANAGER_DEVICE_BOND_H__ -#include <glib-object.h> - #include "nm-device.h" G_BEGIN_DECLS @@ -34,8 +32,6 @@ G_BEGIN_DECLS #define NM_IS_DEVICE_BOND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_BOND)) #define NM_DEVICE_BOND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_BOND, NMDeviceBondClass)) -#define NM_DEVICE_BOND_SLAVES "slaves" - typedef NMDevice NMDeviceBond; typedef NMDeviceClass NMDeviceBondClass; diff --git a/src/devices/nm-device-bridge.c b/src/devices/nm-device-bridge.c index d6435530..843c5be4 100644 --- a/src/devices/nm-device-bridge.c +++ b/src/devices/nm-device-bridge.c @@ -15,29 +15,23 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2011 - 2012 Red Hat, Inc. + * Copyright 2011 - 2015 Red Hat, Inc. */ #include "config.h" -#include <glib.h> -#include <glib/gi18n.h> - #include <stdlib.h> -#include "gsystem-local-alloc.h" +#include "nm-default.h" #include "nm-device-bridge.h" -#include "nm-logging.h" #include "NetworkManagerUtils.h" #include "nm-device-private.h" -#include "nm-dbus-glib-types.h" -#include "nm-dbus-manager.h" #include "nm-enum-types.h" #include "nm-platform.h" #include "nm-device-factory.h" #include "nm-core-internal.h" -#include "nm-device-bridge-glue.h" +#include "nmdbus-device-bridge.h" #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceBridge); @@ -50,13 +44,6 @@ typedef struct { int dummy; } NMDeviceBridgePrivate; -enum { - PROP_0, - PROP_SLAVES, - - LAST_PROP -}; - /******************************************************************/ static NMDeviceCapabilities @@ -103,7 +90,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) return FALSE; mac_address = nm_setting_bridge_get_mac_address (s_bridge); - if (mac_address) { + if (mac_address && nm_device_is_real (device)) { const char *hw_addr; hw_addr = nm_device_get_hw_address (device); @@ -156,6 +143,7 @@ static const Option master_options[] = { { NM_SETTING_BRIDGE_HELLO_TIME, "hello_time", TRUE, TRUE }, { NM_SETTING_BRIDGE_MAX_AGE, "max_age", TRUE, TRUE }, { NM_SETTING_BRIDGE_AGEING_TIME, "ageing_time", TRUE, TRUE }, + { NM_SETTING_BRIDGE_MULTICAST_SNOOPING, "multicast_snooping", FALSE, FALSE }, { NULL, NULL } }; @@ -211,9 +199,9 @@ commit_option (NMDevice *device, NMSetting *setting, const Option *option, gbool value = g_strdup_printf ("%u", uval); if (slave) - nm_platform_slave_set_option (NM_PLATFORM_GET, ifindex, option->sysname, value); + nm_platform_sysctl_slave_set_option (NM_PLATFORM_GET, ifindex, option->sysname, value); else - nm_platform_master_set_option (NM_PLATFORM_GET, ifindex, option->sysname, value); + nm_platform_sysctl_master_set_option (NM_PLATFORM_GET, ifindex, option->sysname, value); } static void @@ -257,7 +245,7 @@ update_connection (NMDevice *device, NMConnection *connection) } for (option = master_options; option->name; option++) { - gs_free char *str = nm_platform_master_get_option (NM_PLATFORM_GET, ifindex, option->sysname); + gs_free char *str = nm_platform_sysctl_master_get_option (NM_PLATFORM_GET, ifindex, option->sysname); int value; if (str) { @@ -296,7 +284,7 @@ master_update_slave_connection (NMDevice *device, } for (option = slave_options; option->name; option++) { - gs_free char *str = nm_platform_slave_get_option (NM_PLATFORM_GET, ifindex_slave, option->sysname); + gs_free char *str = nm_platform_sysctl_slave_get_option (NM_PLATFORM_GET, ifindex_slave, option->sysname); int value; if (str) { @@ -322,7 +310,7 @@ static NMActStageReturn act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) { NMActStageReturn ret; - NMConnection *connection = nm_device_get_connection (device); + NMConnection *connection = nm_device_get_applied_connection (device); g_assert (connection); @@ -356,18 +344,16 @@ enslave_slave (NMDevice *device, nm_device_get_ip_iface (slave)); } - g_object_notify (G_OBJECT (device), NM_DEVICE_BRIDGE_SLAVES); - return TRUE; } -static gboolean +static void release_slave (NMDevice *device, NMDevice *slave, gboolean configure) { NMDeviceBridge *self = NM_DEVICE_BRIDGE (device); - gboolean success = TRUE; + gboolean success; if (configure) { success = nm_platform_link_release (NM_PLATFORM_GET, @@ -385,49 +371,57 @@ release_slave (NMDevice *device, _LOGI (LOGD_BRIDGE, "bridge port %s was detached", nm_device_get_ip_iface (slave)); } - - g_object_notify (G_OBJECT (device), NM_DEVICE_BRIDGE_SLAVES); - return success; } -/******************************************************************/ - -static void -nm_device_bridge_init (NMDeviceBridge * self) +static gboolean +create_and_realize (NMDevice *device, + NMConnection *connection, + NMDevice *parent, + const NMPlatformLink **out_plink, + GError **error) { -} + NMSettingBridge *s_bridge; + const char *iface = nm_device_get_iface (device); + const char *hwaddr; + guint8 mac_address[NM_UTILS_HWADDR_LEN_MAX]; + NMPlatformError plerr; -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - GPtrArray *slaves; - GSList *list, *iter; - - switch (prop_id) { - case PROP_SLAVES: - slaves = g_ptr_array_new (); - list = nm_device_master_get_slaves (NM_DEVICE (object)); - for (iter = list; iter; iter = iter->next) - g_ptr_array_add (slaves, g_strdup (nm_device_get_path (NM_DEVICE (iter->data)))); - g_slist_free (list); - g_value_take_boxed (value, slaves); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; + g_assert (iface); + + s_bridge = nm_connection_get_setting_bridge (connection); + g_assert (s_bridge); + hwaddr = nm_setting_bridge_get_mac_address (s_bridge); + if (hwaddr) { + if (!nm_utils_hwaddr_aton (hwaddr, mac_address, ETH_ALEN)) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "Invalid hardware address '%s'", + hwaddr); + return FALSE; + } + } + + plerr = nm_platform_link_bridge_add (NM_PLATFORM_GET, + iface, + hwaddr ? mac_address : NULL, + hwaddr ? ETH_ALEN : 0, + out_plink); + if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, + "Failed to create bridge interface '%s' for '%s': %s", + iface, + nm_connection_get_id (connection), + nm_platform_error_to_string (plerr)); + return FALSE; } + + return TRUE; } +/******************************************************************/ + static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) +nm_device_bridge_init (NMDeviceBridge * self) { - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } } static void @@ -438,11 +432,7 @@ nm_device_bridge_class_init (NMDeviceBridgeClass *klass) g_type_class_add_private (object_class, sizeof (NMDeviceBridgePrivate)); - parent_class->connection_type = NM_SETTING_BRIDGE_SETTING_NAME; - - /* virtual methods */ - object_class->get_property = get_property; - object_class->set_property = set_property; + NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_BRIDGE_SETTING_NAME, NM_LINK_TYPE_BRIDGE) parent_class->get_generic_capabilities = get_generic_capabilities; parent_class->is_available = is_available; @@ -453,21 +443,14 @@ nm_device_bridge_class_init (NMDeviceBridgeClass *klass) parent_class->update_connection = update_connection; parent_class->master_update_slave_connection = master_update_slave_connection; + parent_class->create_and_realize = create_and_realize; parent_class->act_stage1_prepare = act_stage1_prepare; parent_class->enslave_slave = enslave_slave; parent_class->release_slave = release_slave; - /* properties */ - g_object_class_install_property - (object_class, PROP_SLAVES, - g_param_spec_boxed (NM_DEVICE_BRIDGE_SLAVES, "", "", - DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), - G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_bridge_object_info); + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_BRIDGE_SKELETON, + NULL); } /*************************************************************/ @@ -476,61 +459,18 @@ nm_device_bridge_class_init (NMDeviceBridgeClass *klass) #define NM_BRIDGE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BRIDGE_FACTORY, NMBridgeFactory)) static NMDevice * -new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error) -{ - return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BRIDGE, - NM_DEVICE_PLATFORM_DEVICE, plink, - NM_DEVICE_DRIVER, "bridge", - NM_DEVICE_TYPE_DESC, "Bridge", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BRIDGE, - NM_DEVICE_IS_MASTER, TRUE, - NULL); -} - -static NMDevice * -create_virtual_device_for_connection (NMDeviceFactory *factory, - NMConnection *connection, - NMDevice *parent, - GError **error) +create_device (NMDeviceFactory *factory, + const char *iface, + const NMPlatformLink *plink, + NMConnection *connection, + gboolean *out_ignore) { - const char *iface = nm_connection_get_interface_name (connection); - NMSettingBridge *s_bridge; - const char *mac_address_str; - guint8 mac_address[NM_UTILS_HWADDR_LEN_MAX]; - NMPlatformError plerr; - const NMPlatformLink *plink; - - g_assert (iface); - - s_bridge = nm_connection_get_setting_bridge (connection); - g_assert (s_bridge); - - mac_address_str = nm_setting_bridge_get_mac_address (s_bridge); - if (mac_address_str) { - if (!nm_utils_hwaddr_aton (mac_address_str, mac_address, ETH_ALEN)) - mac_address_str = NULL; - } - - plerr = nm_platform_bridge_add (NM_PLATFORM_GET, - iface, - mac_address_str ? mac_address : NULL, - mac_address_str ? ETH_ALEN : 0, - NULL); - if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { - g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, - "Failed to create bridge interface '%s' for '%s': %s", - iface, - nm_connection_get_id (connection), - nm_platform_error_to_string (plerr)); - return NULL; - } - plink = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, iface); - return (NMDevice *) g_object_new (NM_TYPE_DEVICE_BRIDGE, - NM_DEVICE_PLATFORM_DEVICE, plink, + NM_DEVICE_IFACE, iface, NM_DEVICE_DRIVER, "bridge", NM_DEVICE_TYPE_DESC, "Bridge", NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_BRIDGE, + NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_BRIDGE, NM_DEVICE_IS_MASTER, TRUE, NULL); } @@ -538,7 +478,6 @@ create_virtual_device_for_connection (NMDeviceFactory *factory, NM_DEVICE_FACTORY_DEFINE_INTERNAL (BRIDGE, Bridge, bridge, NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_BRIDGE) NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_BRIDGE_SETTING_NAME), - factory_iface->new_link = new_link; - factory_iface->create_virtual_device_for_connection = create_virtual_device_for_connection; + factory_iface->create_device = create_device; ) diff --git a/src/devices/nm-device-bridge.h b/src/devices/nm-device-bridge.h index c11a2c40..46482675 100644 --- a/src/devices/nm-device-bridge.h +++ b/src/devices/nm-device-bridge.h @@ -21,8 +21,7 @@ #ifndef __NETWORKMANAGER_DEVICE_BRIDGE_H__ #define __NETWORKMANAGER_DEVICE_BRIDGE_H__ -#include <glib-object.h> - +#include "nm-default.h" #include "nm-device.h" G_BEGIN_DECLS @@ -34,8 +33,6 @@ G_BEGIN_DECLS #define NM_IS_DEVICE_BRIDGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_BRIDGE)) #define NM_DEVICE_BRIDGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_BRIDGE, NMDeviceBridgeClass)) -#define NM_DEVICE_BRIDGE_SLAVES "slaves" - typedef NMDevice NMDeviceBridge; typedef NMDeviceClass NMDeviceBridgeClass; diff --git a/src/devices/nm-device-ethernet-utils.c b/src/devices/nm-device-ethernet-utils.c index 585f6a0e..9165de31 100644 --- a/src/devices/nm-device-ethernet-utils.c +++ b/src/devices/nm-device-ethernet-utils.c @@ -19,10 +19,9 @@ #include "config.h" #include <string.h> -#include <glib.h> -#include <glib/gi18n.h> #include <nm-connection.h> +#include "nm-default.h" #include "nm-device-ethernet-utils.h" char * diff --git a/src/devices/nm-device-ethernet-utils.h b/src/devices/nm-device-ethernet-utils.h index 5848f7e6..31d645d8 100644 --- a/src/devices/nm-device-ethernet-utils.h +++ b/src/devices/nm-device-ethernet-utils.h @@ -19,7 +19,7 @@ #ifndef __NETWORKMANAGER_DEVICE_ETHERNET_UTILS_H__ #define __NETWORKMANAGER_DEVICE_ETHERNET_UTILS_H__ -#include <glib.h> +#include "nm-default.h" char *nm_device_ethernet_utils_get_default_wired_name (const GSList *connections); diff --git a/src/devices/nm-device-ethernet.c b/src/devices/nm-device-ethernet.c index 2dda84b3..a2396ec8 100644 --- a/src/devices/nm-device-ethernet.c +++ b/src/devices/nm-device-ethernet.c @@ -21,8 +21,6 @@ #include "config.h" -#include <glib.h> -#include <glib/gi18n.h> #include <netinet/in.h> #include <string.h> #include <stdlib.h> @@ -31,7 +29,7 @@ #include <gudev/gudev.h> -#include "nm-glib-compat.h" +#include "nm-default.h" #include "nm-device-ethernet.h" #include "nm-device-private.h" #include "nm-activation-request.h" @@ -40,9 +38,7 @@ #include "nm-supplicant-interface.h" #include "nm-supplicant-config.h" #include "ppp-manager/nm-ppp-manager.h" -#include "nm-logging.h" #include "nm-enum-types.h" -#include "nm-dbus-manager.h" #include "nm-platform.h" #include "nm-platform-utils.h" #include "nm-dcb.h" @@ -53,9 +49,8 @@ #include "nm-device-factory.h" #include "nm-core-internal.h" #include "NetworkManagerUtils.h" -#include "gsystem-local-alloc.h" -#include "nm-device-ethernet-glue.h" +#include "nmdbus-device-ethernet.h" #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceEthernet); @@ -76,8 +71,8 @@ typedef struct Supplicant { NMSupplicantInterface *iface; /* signal handler ids */ - guint iface_error_id; - guint iface_state_id; + gulong iface_error_id; + gulong iface_state_id; /* Timeouts and idles */ guint iface_con_error_cb_id; @@ -109,6 +104,7 @@ typedef struct { char * subchan2; char * subchan3; char * subchannels; /* Composite used for checking unmanaged specs */ + char ** subchannels_dbus; /* Array exported on D-Bus */ char * s390_nettype; GHashTable * s390_options; @@ -121,13 +117,14 @@ typedef struct { /* DCB */ DcbWait dcb_wait; guint dcb_timeout_id; - guint dcb_carrier_id; + gulong dcb_carrier_id; } NMDeviceEthernetPrivate; enum { PROP_0, PROP_PERM_HW_ADDRESS, PROP_SPEED, + PROP_S390_SUBCHANNELS, LAST_PROP }; @@ -230,6 +227,12 @@ _update_s390_subchannels (NMDeviceEthernet *self) } else priv->subchannels = g_strdup (priv->subchan1); + priv->subchannels_dbus = g_new (char *, 3 + 1); + priv->subchannels_dbus[0] = g_strdup (priv->subchan1); + priv->subchannels_dbus[1] = g_strdup (priv->subchan2); + priv->subchannels_dbus[2] = g_strdup (priv->subchan3); + priv->subchannels_dbus[3] = NULL; + driver = nm_device_get_driver (NM_DEVICE (self)); _LOGI (LOGD_DEVICE | LOGD_HW, "found s390 '%s' subchannels [%s]", driver ? driver : "(unknown driver)", priv->subchannels); @@ -276,7 +279,7 @@ clear_secrets_tries (NMDevice *device) req = nm_device_get_act_request (device); if (req) { - connection = nm_act_request_get_connection (req); + connection = nm_act_request_get_applied_connection (req); /* Clear wired secrets tries on success, failure, or when deactivating */ g_object_set_data (G_OBJECT (connection), WIRED_SECRETS_TRIES, NULL); } @@ -301,6 +304,14 @@ nm_device_ethernet_init (NMDeviceEthernet *self) priv->s390_options = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); } +static void +realize_start_notify (NMDevice *device, const NMPlatformLink *plink) +{ + NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->realize_start_notify (device, plink); + + g_object_notify (G_OBJECT (device), NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS); +} + static NMDeviceCapabilities get_generic_capabilities (NMDevice *device) { @@ -315,21 +326,39 @@ get_generic_capabilities (NMDevice *device) } } +static guint32 +_subchannels_count_num (const char * const *array) +{ + int i; + + if (!array) + return 0; + for (i = 0; array[i]; i++) + /* NOP */; + return i; +} + static gboolean match_subchans (NMDeviceEthernet *self, NMSettingWired *s_wired, gboolean *try_mac) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); const char * const *subchans; + guint32 num1, num2; int i; *try_mac = TRUE; subchans = nm_setting_wired_get_s390_subchannels (s_wired); - if (!subchans) + num1 = _subchannels_count_num (subchans); + num2 = _subchannels_count_num ((const char * const *) priv->subchannels_dbus); + /* connection has no subchannels */ + if (num1 == 0) return TRUE; - /* connection requires subchannels but the device has none */ - if (!priv->subchannels) + if (num2 == 0) + return FALSE; + /* number of subchannels differ */ + if (num1 != num2) return FALSE; /* Make sure each subchannel in the connection is a subchannel of this device */ @@ -412,7 +441,7 @@ device_get_setting (NMDevice *device, GType setting_type) if (req) { NMConnection *connection; - connection = nm_act_request_get_connection (req); + connection = nm_act_request_get_applied_connection (req); if (connection) setting = nm_connection_get_setting (connection, setting_type); } @@ -428,15 +457,8 @@ remove_supplicant_timeouts (NMDeviceEthernet *self) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - if (priv->supplicant.con_timeout_id) { - g_source_remove (priv->supplicant.con_timeout_id); - priv->supplicant.con_timeout_id = 0; - } - - if (priv->supplicant_timeout_id) { - g_source_remove (priv->supplicant_timeout_id); - priv->supplicant_timeout_id = 0; - } + nm_clear_g_source (&priv->supplicant.con_timeout_id); + nm_clear_g_source (&priv->supplicant_timeout_id); } static void @@ -477,17 +499,19 @@ supplicant_interface_release (NMDeviceEthernet *self) static void wired_secrets_cb (NMActRequest *req, - guint32 call_id, - NMConnection *connection, + NMActRequestGetSecretsCallId call_id, + NMSettingsConnection *connection, GError *error, gpointer user_data) { NMDeviceEthernet *self = NM_DEVICE_ETHERNET (user_data); NMDevice *dev = NM_DEVICE (self); - g_return_if_fail (req == nm_device_get_act_request (dev)); + if (req != nm_device_get_act_request (dev)) + return; + g_return_if_fail (nm_device_get_state (dev) == NM_DEVICE_STATE_NEED_AUTH); - g_return_if_fail (nm_act_request_get_connection (req) == connection); + g_return_if_fail (nm_act_request_get_settings_connection (req) == connection); if (error) { _LOGW (LOGD_ETHER, "%s", error->message); @@ -505,7 +529,7 @@ link_timeout_cb (gpointer user_data) NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); NMDevice *dev = NM_DEVICE (self); NMActRequest *req; - NMConnection *connection; + NMConnection *applied_connection; const char *setting_name; priv->supplicant_timeout_id = 0; @@ -526,9 +550,10 @@ link_timeout_cb (gpointer user_data) if (nm_device_get_state (dev) != NM_DEVICE_STATE_CONFIG) goto time_out; - connection = nm_act_request_get_connection (req); - nm_connection_clear_secrets (connection); - setting_name = nm_connection_need_secrets (connection, NULL); + nm_active_connection_clear_secrets (NM_ACTIVE_CONNECTION (req)); + + applied_connection = nm_act_request_get_applied_connection (req); + setting_name = nm_connection_need_secrets (applied_connection, NULL); if (!setting_name) goto time_out; @@ -554,7 +579,8 @@ time_out: } static NMSupplicantConfig * -build_supplicant_config (NMDeviceEthernet *self) +build_supplicant_config (NMDeviceEthernet *self, + GError **error) { const char *con_uuid; NMSupplicantConfig *config = NULL; @@ -562,7 +588,7 @@ build_supplicant_config (NMDeviceEthernet *self) NMConnection *connection; guint32 mtu; - connection = nm_device_get_connection (NM_DEVICE (self)); + connection = nm_device_get_applied_connection (NM_DEVICE (self)); g_assert (connection); con_uuid = nm_connection_get_uuid (connection); mtu = nm_platform_link_get_mtu (NM_PLATFORM_GET, @@ -571,10 +597,9 @@ build_supplicant_config (NMDeviceEthernet *self) config = nm_supplicant_config_new (); security = nm_connection_get_setting_802_1x (connection); - if (!nm_supplicant_config_add_setting_8021x (config, security, con_uuid, mtu, TRUE)) { - _LOGW (LOGD_DEVICE, "Couldn't add 802.1X security setting to supplicant config."); - g_object_unref (config); - config = NULL; + if (!nm_supplicant_config_add_setting_8021x (config, security, con_uuid, mtu, TRUE, error)) { + g_prefix_error (error, "802-1x-setting: "); + g_clear_object (&config); } return config; @@ -593,6 +618,7 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, NMSupplicantConfig *config; gboolean success = FALSE; NMDeviceState devstate; + GError *error = NULL; if (new_state == old_state) return; @@ -605,18 +631,22 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, switch (new_state) { case NM_SUPPLICANT_INTERFACE_STATE_READY: - config = build_supplicant_config (self); + config = build_supplicant_config (self, &error); if (config) { - success = nm_supplicant_interface_set_config (priv->supplicant.iface, config); + success = nm_supplicant_interface_set_config (priv->supplicant.iface, config, &error); g_object_unref (config); if (!success) { _LOGE (LOGD_DEVICE | LOGD_ETHER, - "Activation: (ethernet) couldn't send security configuration to the supplicant."); + "Activation: (ethernet) couldn't send security configuration to the supplicant: %s", + error ? error->message : "<BUG>"); + g_clear_error (&error); } } else { - _LOGW (LOGD_DEVICE | LOGD_ETHER, - "Activation: (ethernet) couldn't build security configuration."); + _LOGE (LOGD_DEVICE | LOGD_ETHER, + "Activation: (ethernet) couldn't build security configuration: %s", + error ? error->message : "<BUG>"); + g_clear_error (&error); } if (!success) { @@ -701,19 +731,19 @@ handle_auth_or_fail (NMDeviceEthernet *self, { const char *setting_name; guint32 tries; - NMConnection *connection; + NMConnection *applied_connection; - connection = nm_act_request_get_connection (req); - g_assert (connection); + applied_connection = nm_act_request_get_applied_connection (req); - tries = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (connection), WIRED_SECRETS_TRIES)); + tries = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (applied_connection), WIRED_SECRETS_TRIES)); if (tries > 3) return NM_ACT_STAGE_RETURN_FAILURE; nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); - nm_connection_clear_secrets (connection); - setting_name = nm_connection_need_secrets (connection, NULL); + nm_active_connection_clear_secrets (NM_ACTIVE_CONNECTION (req)); + + setting_name = nm_connection_need_secrets (applied_connection, NULL); if (setting_name) { NMSecretAgentGetSecretsFlags flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION; @@ -721,7 +751,7 @@ handle_auth_or_fail (NMDeviceEthernet *self, flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW; nm_act_request_get_secrets (req, setting_name, flags, NULL, wired_secrets_cb, self); - g_object_set_data (G_OBJECT (connection), WIRED_SECRETS_TRIES, GUINT_TO_POINTER (++tries)); + g_object_set_data (G_OBJECT (applied_connection), WIRED_SECRETS_TRIES, GUINT_TO_POINTER (++tries)); } else _LOGI (LOGD_DEVICE, "Cleared secrets, but setting didn't need any secrets."); @@ -751,7 +781,7 @@ supplicant_connection_timeout_cb (gpointer user_data) req = nm_device_get_act_request (device); g_assert (req); - connection = nm_act_request_get_connection (req); + connection = nm_act_request_get_applied_connection (req); g_assert (connection); /* Ask for new secrets only if we've never activated this connection @@ -873,7 +903,7 @@ nm_8021x_stage2_config (NMDeviceEthernet *self, NMDeviceStateReason *reason) const char *setting_name; NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; - connection = nm_device_get_connection (NM_DEVICE (self)); + connection = nm_device_get_applied_connection (NM_DEVICE (self)); g_assert (connection); security = nm_connection_get_setting_802_1x (connection); if (!security) { @@ -959,7 +989,7 @@ pppoe_stage3_ip4_config_start (NMDeviceEthernet *self, NMDeviceStateReason *reas req = nm_device_get_act_request (NM_DEVICE (self)); g_assert (req); - connection = nm_act_request_get_connection (req); + connection = nm_act_request_get_applied_connection (req); g_assert (req); s_pppoe = nm_connection_get_setting_pppoe (connection); @@ -967,19 +997,18 @@ pppoe_stage3_ip4_config_start (NMDeviceEthernet *self, NMDeviceStateReason *reas priv->ppp_manager = nm_ppp_manager_new (nm_device_get_iface (NM_DEVICE (self))); if (nm_ppp_manager_start (priv->ppp_manager, req, nm_setting_pppoe_get_username (s_pppoe), 30, &err)) { - g_signal_connect (priv->ppp_manager, "state-changed", - G_CALLBACK (ppp_state_changed), - self); + g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_STATE_CHANGED, + G_CALLBACK (ppp_state_changed), + self); g_signal_connect (priv->ppp_manager, "ip4-config", - G_CALLBACK (ppp_ip4_config), - self); + G_CALLBACK (ppp_ip4_config), + self); ret = NM_ACT_STAGE_RETURN_POSTPONE; } else { _LOGW (LOGD_DEVICE, "PPPoE failed to start: %s", err->message); g_error_free (err); - g_object_unref (priv->ppp_manager); - priv->ppp_manager = NULL; + nm_exported_object_clear_and_unexport (&priv->ppp_manager); *reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED; } @@ -994,10 +1023,7 @@ dcb_timeout_cleanup (NMDevice *device) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); - if (priv->dcb_timeout_id) { - g_source_remove (priv->dcb_timeout_id); - priv->dcb_timeout_id = 0; - } + nm_clear_g_source (&priv->dcb_timeout_id); } static void @@ -1005,10 +1031,7 @@ dcb_carrier_cleanup (NMDevice *device) { NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (device); - if (priv->dcb_carrier_id) { - g_signal_handler_disconnect (device, priv->dcb_carrier_id); - priv->dcb_carrier_id = 0; - } + nm_clear_g_signal_handler (device, &priv->dcb_carrier_id); } static void dcb_state (NMDevice *device, gboolean timeout); @@ -1280,7 +1303,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) } /* PPPoE setup */ - if (nm_connection_is_type (nm_device_get_connection (device), + if (nm_connection_is_type (nm_device_get_applied_connection (device), NM_SETTING_PPPOE_SETTING_NAME)) { NMSettingPpp *s_ppp; @@ -1335,7 +1358,7 @@ ip4_config_pre_commit (NMDevice *device, NMIP4Config *config) if (NM_DEVICE_ETHERNET_GET_PRIVATE (device)->ppp_manager) return; - connection = nm_device_get_connection (device); + connection = nm_device_get_applied_connection (device); g_assert (connection); s_wired = nm_connection_get_setting_wired (connection); g_assert (s_wired); @@ -1357,20 +1380,14 @@ deactivate (NMDevice *device) /* Clear wired secrets tries when deactivating */ clear_secrets_tries (device); - if (priv->pppoe_wait_id) { - g_source_remove (priv->pppoe_wait_id); - priv->pppoe_wait_id = 0; - } + nm_clear_g_source (&priv->pppoe_wait_id); if (priv->pending_ip4_config) { g_object_unref (priv->pending_ip4_config); priv->pending_ip4_config = NULL; } - if (priv->ppp_manager) { - g_object_unref (priv->ppp_manager); - priv->ppp_manager = NULL; - } + nm_exported_object_clear_and_unexport (&priv->ppp_manager); supplicant_interface_release (self); @@ -1547,16 +1564,8 @@ update_connection (NMDevice *device, NMConnection *connection) /* We don't set the MTU as we don't know whether it was set explicitly */ /* s390 */ - if (priv->subchannels) { - char **subchannels = g_new (char *, 3 + 1); - - subchannels[0] = g_strdup (priv->subchan1); - subchannels[1] = g_strdup (priv->subchan2); - subchannels[2] = g_strdup (priv->subchan3); - subchannels[3] = NULL; - g_object_set (s_wired, NM_SETTING_WIRED_S390_SUBCHANNELS, subchannels, NULL); - g_strfreev (subchannels); - } + if (priv->subchannels_dbus) + g_object_set (s_wired, NM_SETTING_WIRED_S390_SUBCHANNELS, priv->subchannels_dbus, NULL); if (priv->s390_nettype) g_object_set (s_wired, NM_SETTING_WIRED_S390_NETTYPE, priv->s390_nettype, NULL); g_hash_table_iter_init (&iter, priv->s390_options); @@ -1598,10 +1607,44 @@ link_changed (NMDevice *device, NMPlatformLink *info) { NMDeviceEthernet *self = NM_DEVICE_ETHERNET (device); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); + static const guint8 zero_hwaddr[ETH_ALEN]; + const guint8 *hwaddr; + gsize hwaddrlen = 0; NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->link_changed (device, info); if (!priv->subchan1 && info->initialized) _update_s390_subchannels (self); + + if (!nm_device_get_initial_hw_address (device)) { + hwaddr = nm_platform_link_get_address (NM_PLATFORM_GET, + nm_device_get_ifindex (self), + &hwaddrlen); + if (!nm_utils_hwaddr_matches (hwaddr, hwaddrlen, zero_hwaddr, ETH_ALEN)) { + _LOGD (LOGD_DEVICE, "device got a valid hw address"); + nm_device_update_hw_address (self); + nm_device_update_initial_hw_address (self); + if (nm_device_get_state (device) == NM_DEVICE_STATE_UNAVAILABLE) { + /* + * If the device is UNAVAILABLE, any previous try to + * bring it up probably has failed because of the + * invalid hardware address; try again. + */ + nm_device_bring_up (self, TRUE, NULL); + nm_device_queue_recheck_available (device, + NM_DEVICE_STATE_REASON_NONE, + NM_DEVICE_STATE_REASON_NONE); + } + } + } +} + +static gboolean +is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags) +{ + if (!NM_DEVICE_CLASS (nm_device_ethernet_parent_class)->is_available (device, flags)) + return FALSE; + + return !!nm_device_get_initial_hw_address (device); } static void @@ -1610,10 +1653,7 @@ dispose (GObject *object) NMDeviceEthernet *self = NM_DEVICE_ETHERNET (object); NMDeviceEthernetPrivate *priv = NM_DEVICE_ETHERNET_GET_PRIVATE (self); - if (priv->pppoe_wait_id) { - g_source_remove (priv->pppoe_wait_id); - priv->pppoe_wait_id = 0; - } + nm_clear_g_source (&priv->pppoe_wait_id); dcb_timeout_cleanup (NM_DEVICE (self)); dcb_carrier_cleanup (NM_DEVICE (self)); @@ -1632,6 +1672,7 @@ finalize (GObject *object) g_free (priv->subchan2); g_free (priv->subchan3); g_free (priv->subchannels); + g_strfreev (priv->subchannels_dbus); g_free (priv->s390_nettype); g_hash_table_destroy (priv->s390_options); @@ -1652,6 +1693,9 @@ get_property (GObject *object, guint prop_id, case PROP_SPEED: g_value_set_uint (value, priv->speed); break; + case PROP_S390_SUBCHANNELS: + g_value_set_boxed (value, priv->subchannels_dbus); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1677,7 +1721,7 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass) g_type_class_add_private (object_class, sizeof (NMDeviceEthernetPrivate)); - parent_class->connection_type = NM_SETTING_WIRED_SETTING_NAME; + NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_WIRED_SETTING_NAME, NM_LINK_TYPE_ETHERNET) /* virtual methods */ object_class->constructor = constructor; @@ -1687,6 +1731,7 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass) object_class->set_property = set_property; parent_class->get_generic_capabilities = get_generic_capabilities; + parent_class->realize_start_notify = realize_start_notify; parent_class->check_connection_compatible = check_connection_compatible; parent_class->complete_connection = complete_connection; parent_class->new_default_connection = new_default_connection; @@ -1700,6 +1745,7 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass) parent_class->update_connection = update_connection; parent_class->carrier_changed = carrier_changed; parent_class->link_changed = link_changed; + parent_class->is_available = is_available; parent_class->state_changed = device_state_changed; @@ -1718,9 +1764,16 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), - G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_ethernet_object_info); + g_object_class_install_property + (object_class, PROP_S390_SUBCHANNELS, + g_param_spec_boxed (NM_DEVICE_ETHERNET_S390_SUBCHANNELS, "", "", + G_TYPE_STRV, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_ETHERNET_SKELETON, + NULL); } /*************************************************************/ @@ -1729,18 +1782,23 @@ nm_device_ethernet_class_init (NMDeviceEthernetClass *klass) #define NM_ETHERNET_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_ETHERNET_FACTORY, NMEthernetFactory)) static NMDevice * -new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error) +create_device (NMDeviceFactory *factory, + const char *iface, + const NMPlatformLink *plink, + NMConnection *connection, + gboolean *out_ignore) { return (NMDevice *) g_object_new (NM_TYPE_DEVICE_ETHERNET, - NM_DEVICE_PLATFORM_DEVICE, plink, + NM_DEVICE_IFACE, iface, NM_DEVICE_TYPE_DESC, "Ethernet", NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_ETHERNET, + NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_ETHERNET, NULL); } NM_DEVICE_FACTORY_DEFINE_INTERNAL (ETHERNET, Ethernet, ethernet, NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_ETHERNET) NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_PPPOE_SETTING_NAME), - factory_iface->new_link = new_link; + factory_iface->create_device = create_device; ) diff --git a/src/devices/nm-device-ethernet.h b/src/devices/nm-device-ethernet.h index ad9ce856..2d284822 100644 --- a/src/devices/nm-device-ethernet.h +++ b/src/devices/nm-device-ethernet.h @@ -22,8 +22,6 @@ #ifndef __NETWORKMANAGER_DEVICE_ETHERNET_H__ #define __NETWORKMANAGER_DEVICE_ETHERNET_H__ -#include <glib-object.h> - #include "nm-device.h" G_BEGIN_DECLS @@ -37,6 +35,7 @@ G_BEGIN_DECLS #define NM_DEVICE_ETHERNET_PERMANENT_HW_ADDRESS "perm-hw-address" #define NM_DEVICE_ETHERNET_SPEED "speed" +#define NM_DEVICE_ETHERNET_S390_SUBCHANNELS "s390-subchannels" typedef NMDevice NMDeviceEthernet; typedef NMDeviceClass NMDeviceEthernetClass; diff --git a/src/devices/nm-device-factory.c b/src/devices/nm-device-factory.c index 13034808..75731b14 100644 --- a/src/devices/nm-device-factory.c +++ b/src/devices/nm-device-factory.c @@ -27,12 +27,14 @@ #include <gmodule.h> #include "nm-device-factory.h" -#include "nm-logging.h" +#include "nm-default.h" #include "nm-platform.h" const NMLinkType _nm_device_factory_no_default_links[] = { NM_LINK_TYPE_NONE }; const char *_nm_device_factory_no_default_settings[] = { NULL }; +G_DEFINE_INTERFACE (NMDeviceFactory, nm_device_factory, G_TYPE_OBJECT) + enum { DEVICE_ADDED, COMPONENT_ADDED, @@ -79,86 +81,64 @@ nm_device_factory_start (NMDeviceFactory *factory) } NMDevice * -nm_device_factory_new_link (NMDeviceFactory *factory, - NMPlatformLink *plink, - gboolean *out_ignore, - GError **error) +nm_device_factory_create_device (NMDeviceFactory *factory, + const char *iface, + const NMPlatformLink *plink, + NMConnection *connection, + gboolean *out_ignore, + GError **error) { - NMDeviceFactory *interface; + NMDeviceFactoryInterface *interface; const NMLinkType *link_types = NULL; const char **setting_types = NULL; int i; - g_return_val_if_fail (factory != NULL, NULL); - g_return_val_if_fail (plink != NULL, NULL); + g_return_val_if_fail (factory, NULL); + g_return_val_if_fail (iface && *iface, NULL); + g_return_val_if_fail (plink || connection, NULL); + g_return_val_if_fail (!plink || !connection, NULL); - /* Ensure the factory can create interfaces for this connection */ nm_device_factory_get_supported_types (factory, &link_types, &setting_types); - for (i = 0; link_types[i] > NM_LINK_TYPE_UNKNOWN; i++) { - if (plink->type == link_types[i]) - break; - } - if (link_types[i] == NM_LINK_TYPE_UNKNOWN) { - g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, - "Device factory %s does not support link type %s (%d)", - G_OBJECT_TYPE_NAME (factory), - plink->kind, plink->type); - return NULL; - } + if (plink) { + g_return_val_if_fail (strcmp (iface, plink->name) == 0, NULL); - interface = NM_DEVICE_FACTORY_GET_INTERFACE (factory); - if (!interface->new_link) { - g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, - "Device factory %s cannot manage new devices", - G_OBJECT_TYPE_NAME (factory)); - return NULL; - } - - return interface->new_link (factory, plink, out_ignore, error); -} - -NMDevice * -nm_device_factory_create_virtual_device_for_connection (NMDeviceFactory *factory, - NMConnection *connection, - NMDevice *parent, - GError **error) -{ - NMDeviceFactory *interface; - const char **setting_types = NULL; - gboolean found = FALSE; - int i; + for (i = 0; link_types[i] > NM_LINK_TYPE_UNKNOWN; i++) { + if (plink->type == link_types[i]) + break; + } - g_return_val_if_fail (factory, NULL); - g_return_val_if_fail (connection, NULL); - g_return_val_if_fail (!error || !*error, NULL); - - /* Ensure the factory can create interfaces for this connection */ - nm_device_factory_get_supported_types (factory, NULL, &setting_types); - for (i = 0; setting_types && setting_types[i]; i++) { - if (nm_connection_is_type (connection, setting_types[i])) { - found = TRUE; - break; + if (link_types[i] == NM_LINK_TYPE_UNKNOWN) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, + "Device factory %s does not support link type %s (%d)", + G_OBJECT_TYPE_NAME (factory), + plink->kind, plink->type); + return NULL; + } + } else if (connection) { + for (i = 0; setting_types && setting_types[i]; i++) { + if (nm_connection_is_type (connection, setting_types[i])) + break; } - } - if (!found) { - g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, - "Device factory %s does not support connection type %s", - G_OBJECT_TYPE_NAME (factory), - nm_connection_get_connection_type (connection)); - return NULL; + if (!setting_types[i]) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + "Device factory %s does not support connection type %s", + G_OBJECT_TYPE_NAME (factory), + nm_connection_get_connection_type (connection)); + return NULL; + } } interface = NM_DEVICE_FACTORY_GET_INTERFACE (factory); - if (!interface->create_virtual_device_for_connection) { + if (!interface->create_device) { g_set_error (error, NM_MANAGER_ERROR, NM_MANAGER_ERROR_FAILED, - "Device factory %s cannot create virtual devices", + "Device factory %s cannot manage new devices", G_OBJECT_TYPE_NAME (factory)); return NULL; } - return interface->create_virtual_device_for_connection (factory, connection, parent, error); + return interface->create_device (factory, iface, plink, connection, out_ignore); } const char * @@ -210,7 +190,7 @@ nm_device_factory_get_virtual_iface_name (NMDeviceFactory *factory, /*******************************************************************/ static void -default_init (NMDeviceFactory *factory_iface) +nm_device_factory_default_init (NMDeviceFactoryInterface *factory_iface) { factory_iface->get_virtual_iface_name = get_virtual_iface_name; @@ -218,37 +198,18 @@ default_init (NMDeviceFactory *factory_iface) signals[DEVICE_ADDED] = g_signal_new (NM_DEVICE_FACTORY_DEVICE_ADDED, NM_TYPE_DEVICE_FACTORY, G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMDeviceFactory, device_added), + G_STRUCT_OFFSET (NMDeviceFactoryInterface, device_added), NULL, NULL, NULL, G_TYPE_NONE, 1, NM_TYPE_DEVICE); signals[COMPONENT_ADDED] = g_signal_new (NM_DEVICE_FACTORY_COMPONENT_ADDED, NM_TYPE_DEVICE_FACTORY, G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (NMDeviceFactory, component_added), + G_STRUCT_OFFSET (NMDeviceFactoryInterface, component_added), g_signal_accumulator_true_handled, NULL, NULL, G_TYPE_BOOLEAN, 1, G_TYPE_OBJECT); } -GType -nm_device_factory_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - if (g_once_init_enter (&g_define_type_id__volatile)) { - GType g_define_type_id = - g_type_register_static_simple (G_TYPE_INTERFACE, - g_intern_static_string ("NMDeviceFactory"), - sizeof (NMDeviceFactory), - (GClassInitFunc) default_init, - 0, - (GInstanceInitFunc) NULL, - (GTypeFlags) 0); - g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_OBJECT); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - return g_define_type_id__volatile; -} - /*******************************************************************/ static GSList *internal_types = NULL; @@ -325,19 +286,20 @@ nm_device_factory_manager_for_each_factory (NMDeviceFactoryManagerFactoryFunc ca NMDeviceFactory *factory; GSList *list_iter, *list = NULL; - g_return_if_fail (factories_by_link); - g_return_if_fail (factories_by_setting); - - g_hash_table_iter_init (&iter, factories_by_link); - while (g_hash_table_iter_next (&iter, NULL, (gpointer) &factory)) { - if (!g_slist_find (list, factory)) - list = g_slist_prepend (list, factory); + if (factories_by_link) { + g_hash_table_iter_init (&iter, factories_by_link); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &factory)) { + if (!g_slist_find (list, factory)) + list = g_slist_prepend (list, factory); + } } - g_hash_table_iter_init (&iter, factories_by_setting); - while (g_hash_table_iter_next (&iter, NULL, (gpointer) &factory)) { - if (!g_slist_find (list, factory)) - list = g_slist_prepend (list, factory); + if (factories_by_setting) { + g_hash_table_iter_init (&iter, factories_by_setting); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &factory)) { + if (!g_slist_find (list, factory)) + list = g_slist_prepend (list, factory); + } } for (list_iter = list; list_iter; list_iter = list_iter->next) diff --git a/src/devices/nm-device-factory.h b/src/devices/nm-device-factory.h index 34c056d2..9b7cb35a 100644 --- a/src/devices/nm-device-factory.h +++ b/src/devices/nm-device-factory.h @@ -21,9 +21,6 @@ #ifndef __NETWORKMANAGER_DEVICE_FACTORY_H__ #define __NETWORKMANAGER_DEVICE_FACTORY_H__ -#include <glib.h> -#include <glib-object.h> - #include "nm-dbus-interface.h" #include "nm-device.h" @@ -56,13 +53,13 @@ typedef NMDeviceFactory * (*NMDeviceFactoryCreateFunc) (GError **error); #define NM_TYPE_DEVICE_FACTORY (nm_device_factory_get_type ()) #define NM_DEVICE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_FACTORY, NMDeviceFactory)) #define NM_IS_DEVICE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_FACTORY)) -#define NM_DEVICE_FACTORY_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_DEVICE_FACTORY, NMDeviceFactory)) +#define NM_DEVICE_FACTORY_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_DEVICE_FACTORY, NMDeviceFactoryInterface)) /* signals */ #define NM_DEVICE_FACTORY_COMPONENT_ADDED "component-added" #define NM_DEVICE_FACTORY_DEVICE_ADDED "device-added" -struct _NMDeviceFactory { +typedef struct { GTypeInterface g_iface; /** @@ -87,51 +84,7 @@ struct _NMDeviceFactory { * Start the factory and discover any existing devices that the factory * can manage. */ - void (*start) (NMDeviceFactory *factory); - - /** - * new_link: - * @factory: the #NMDeviceFactory - * @plink: the new link - * @out_ignore: on return, %TRUE if the link should be ignored - * @error: error if the link could be claimed but an error occurred - * - * The NetworkManager core was notified of a new link which the plugin - * may want to claim and create a #NMDevice subclass for. If the link - * represents a device which the factory does not support, or the link - * is supported but the device could not be created, %NULL should be - * returned and @error should be set. - * - * If the plugin cannot create a #NMDevice for the link and wants the - * core to ignore it, set @out_ignore to %TRUE and return no error. - * - * @plink is guaranteed to be one of the types the factory returns in - * get_supported_types(). - * - * Returns: the #NMDevice if the link was claimed and created, %NULL if not - */ - NMDevice * (*new_link) (NMDeviceFactory *factory, - NMPlatformLink *plink, - gboolean *out_ignore, - GError **error); - - /** - * create_virtual_device_for_connection: - * @factory: the #NMDeviceFactory - * @connection: the #NMConnection - * @error: a @GError in case of failure - * - * Virtual device types (such as team, bond, bridge) may need to be created. - * This function tries to create a device based on the given @connection. - * - * Returns: the newly created #NMDevice. If the factory does not support the - * connection type, it should return %NULL and leave @error unset. On error - * it should set @error and return %NULL. - */ - NMDevice * (*create_virtual_device_for_connection) (NMDeviceFactory *factory, - NMConnection *connection, - NMDevice *parent, - GError **error); + void (*start) (NMDeviceFactory *factory); /** * get_connection_parent: @@ -162,6 +115,30 @@ struct _NMDeviceFactory { NMConnection *connection, const char *parent_iface); + /** + * create_device: + * @factory: the #NMDeviceFactory + * @iface: the interface name of the device + * @plink: the #NMPlatformLink if backed by a kernel device + * @connection: the #NMConnection if not backed by a kernel device + * @out_ignore: on return, %TRUE if the link should be ignored + * + * The plugin should create a new unrealized device using the details given + * by @iface and @plink or @connection. If both @iface and @plink are given, + * they are guaranteed to match. If both @iface and @connection are given, + * @iface is guaranteed to be the interface name that @connection specifies. + * + * If the plugin cannot create a #NMDevice for the link and wants the + * core to ignore it, set @out_ignore to %TRUE and return %NULL. + * + * Returns: the new unrealized #NMDevice, or %NULL + */ + NMDevice * (*create_device) (NMDeviceFactory *factory, + const char *iface, + const NMPlatformLink *plink, + NMConnection *connection, + gboolean *out_ignore); + /* Signals */ /** @@ -187,7 +164,7 @@ struct _NMDeviceFactory { * Returns: %TRUE if the component was claimed by a device, %FALSE if not */ gboolean (*component_added) (NMDeviceFactory *factory, GObject *component); -}; +} NMDeviceFactoryInterface; GType nm_device_factory_get_type (void); @@ -204,15 +181,12 @@ char * nm_device_factory_get_virtual_iface_name (NMDeviceFactory *factory, void nm_device_factory_start (NMDeviceFactory *factory); -NMDevice * nm_device_factory_new_link (NMDeviceFactory *factory, - NMPlatformLink *plink, - gboolean *out_ignore, - GError **error); - -NMDevice * nm_device_factory_create_virtual_device_for_connection (NMDeviceFactory *factory, - NMConnection *connection, - NMDevice *parent, - GError **error); +NMDevice * nm_device_factory_create_device (NMDeviceFactory *factory, + const char *iface, + const NMPlatformLink *plink, + NMConnection *connection, + gboolean *out_ignore, + GError **error); /* For use by implementations */ gboolean nm_device_factory_emit_component_added (NMDeviceFactory *factory, @@ -249,7 +223,7 @@ extern const char *_nm_device_factory_no_default_settings[]; typedef GObjectClass NM##mixed##FactoryClass; \ \ static GType nm_##lower##_factory_get_type (void); \ - static void device_factory_interface_init (NMDeviceFactory *factory_iface); \ + static void device_factory_interface_init (NMDeviceFactoryInterface *factory_iface); \ \ G_DEFINE_TYPE_EXTENDED (NM##mixed##Factory, nm_##lower##_factory, G_TYPE_OBJECT, 0, \ G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_FACTORY, device_factory_interface_init) \ @@ -262,14 +236,14 @@ extern const char *_nm_device_factory_no_default_settings[]; static void __attribute__((constructor)) \ register_device_factory_internal_##lower (void) \ { \ - g_type_init (); \ + nm_g_type_init (); \ g_type_ensure (NM_TYPE_##upper##_FACTORY); \ } \ \ NM_DEVICE_FACTORY_DECLARE_TYPES(st_code) \ \ static void \ - device_factory_interface_init (NMDeviceFactory *factory_iface) \ + device_factory_interface_init (NMDeviceFactoryInterface *factory_iface) \ { \ factory_iface->get_supported_types = get_supported_types; \ dfi_code \ diff --git a/src/devices/nm-device-generic.c b/src/devices/nm-device-generic.c index 5841d834..2e9c134a 100644 --- a/src/devices/nm-device-generic.c +++ b/src/devices/nm-device-generic.c @@ -24,11 +24,9 @@ #include "nm-device-private.h" #include "nm-enum-types.h" #include "nm-platform.h" -#include "nm-glib-compat.h" -#include "nm-dbus-manager.h" #include "nm-core-internal.h" -#include "nm-device-generic-glue.h" +#include "nmdbus-device-generic.h" G_DEFINE_TYPE (NMDeviceGeneric, nm_device_generic, NM_TYPE_DEVICE) @@ -62,6 +60,21 @@ get_type_description (NMDevice *device) return NM_DEVICE_CLASS (nm_device_generic_parent_class)->get_type_description (device); } +static void +realize_start_notify (NMDevice *device, const NMPlatformLink *plink) +{ + NMDeviceGeneric *self = NM_DEVICE_GENERIC (device); + NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE (self); + int ifindex; + + NM_DEVICE_CLASS (nm_device_generic_parent_class)->realize_start_notify (device, plink); + + g_clear_pointer (&priv->type_description, g_free); + ifindex = nm_device_get_ip_ifindex (NM_DEVICE (self)); + if (ifindex > 0) + priv->type_description = g_strdup (nm_platform_link_get_type_name (NM_PLATFORM_GET, ifindex)); +} + static gboolean check_connection_compatible (NMDevice *device, NMConnection *connection) { @@ -98,12 +111,12 @@ update_connection (NMDevice *device, NMConnection *connection) /**************************************************************/ NMDevice * -nm_device_generic_new (NMPlatformLink *platform_device) +nm_device_generic_new (const NMPlatformLink *plink) { - g_return_val_if_fail (platform_device != NULL, NULL); + g_return_val_if_fail (plink != NULL, NULL); return (NMDevice *) g_object_new (NM_TYPE_DEVICE_GENERIC, - NM_DEVICE_PLATFORM_DEVICE, platform_device, + NM_DEVICE_IFACE, plink->name, NM_DEVICE_TYPE_DESC, "Generic", NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_GENERIC, NULL); @@ -112,23 +125,22 @@ nm_device_generic_new (NMPlatformLink *platform_device) static void nm_device_generic_init (NMDeviceGeneric *self) { - nm_device_set_initial_unmanaged_flag (NM_DEVICE (self), NM_UNMANAGED_DEFAULT, TRUE); } -static void -constructed (GObject *object) +static GObject * +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) { - NMDeviceGeneric *self = NM_DEVICE_GENERIC (object); - NMDeviceGenericPrivate *priv = NM_DEVICE_GENERIC_GET_PRIVATE (self); + GObject *object; - if (!priv->type_description) { - int ifindex = nm_device_get_ip_ifindex (NM_DEVICE (self)); + object = G_OBJECT_CLASS (nm_device_generic_parent_class)->constructor (type, + n_construct_params, + construct_params); - if (ifindex != 0) - priv->type_description = g_strdup (nm_platform_link_get_type_name (NM_PLATFORM_GET, ifindex)); - } + nm_device_set_unmanaged_flags_initial (NM_DEVICE (object), NM_UNMANAGED_DEFAULT, TRUE); - G_OBJECT_CLASS (nm_device_generic_parent_class)->constructed (object); + return object; } static void @@ -184,13 +196,14 @@ nm_device_generic_class_init (NMDeviceGenericClass *klass) g_type_class_add_private (klass, sizeof (NMDeviceGenericPrivate)); - parent_class->connection_type = NM_SETTING_GENERIC_SETTING_NAME; + NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_GENERIC_SETTING_NAME, NM_LINK_TYPE_ANY) - object_class->constructed = constructed; + object_class->constructor = constructor; object_class->dispose = dispose; object_class->get_property = get_property; object_class->set_property = set_property; + parent_class->realize_start_notify = realize_start_notify; parent_class->get_generic_capabilities = get_generic_capabilities; parent_class->get_type_description = get_type_description; parent_class->check_connection_compatible = check_connection_compatible; @@ -204,7 +217,7 @@ nm_device_generic_class_init (NMDeviceGenericClass *klass) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); - nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), - G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_generic_object_info); + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_GENERIC_SKELETON, + NULL); } diff --git a/src/devices/nm-device-generic.h b/src/devices/nm-device-generic.h index c889b1dd..9303a278 100644 --- a/src/devices/nm-device-generic.h +++ b/src/devices/nm-device-generic.h @@ -21,8 +21,6 @@ #ifndef __NETWORKMANAGER_DEVICE_GENERIC_H__ #define __NETWORKMANAGER_DEVICE_GENERIC_H__ -#include <glib-object.h> - #include "nm-device.h" G_BEGIN_DECLS @@ -47,7 +45,7 @@ typedef struct { GType nm_device_generic_get_type (void); -NMDevice *nm_device_generic_new (NMPlatformLink *platform_device); +NMDevice *nm_device_generic_new (const NMPlatformLink *plink); G_END_DECLS diff --git a/src/devices/nm-device-gre.c b/src/devices/nm-device-gre.c deleted file mode 100644 index b3510d2e..00000000 --- a/src/devices/nm-device-gre.c +++ /dev/null @@ -1,283 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2013 Red Hat, Inc. - */ - -#include "config.h" - -#include <string.h> -#include <arpa/inet.h> - -#include "nm-device-gre.h" -#include "nm-device-private.h" -#include "nm-dbus-manager.h" -#include "nm-logging.h" -#include "nm-manager.h" -#include "nm-platform.h" -#include "nm-device-factory.h" -#include "nm-core-internal.h" - -#include "nm-device-gre-glue.h" - -#include "nm-device-logging.h" -_LOG_DECLARE_SELF(NMDeviceGre); - -G_DEFINE_TYPE (NMDeviceGre, nm_device_gre, NM_TYPE_DEVICE_GENERIC) - -#define NM_DEVICE_GRE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_GRE, NMDeviceGrePrivate)) - -typedef struct { - NMPlatformGreProperties props; -} NMDeviceGrePrivate; - -enum { - PROP_0, - PROP_PARENT, - PROP_INPUT_FLAGS, - PROP_OUTPUT_FLAGS, - PROP_INPUT_KEY, - PROP_OUTPUT_KEY, - PROP_LOCAL, - PROP_REMOTE, - PROP_TTL, - PROP_TOS, - PROP_PATH_MTU_DISCOVERY, - - LAST_PROP -}; - -/**************************************************************/ - -static void -update_properties (NMDevice *device) -{ - NMDeviceGre *self = NM_DEVICE_GRE (device); - NMDeviceGrePrivate *priv = NM_DEVICE_GRE_GET_PRIVATE (self); - GObject *object = G_OBJECT (device); - NMPlatformGreProperties props; - - if (!nm_platform_gre_get_properties (NM_PLATFORM_GET, nm_device_get_ifindex (device), &props)) { - _LOGW (LOGD_HW, "could not read gre properties"); - return; - } - - g_object_freeze_notify (object); - - if (priv->props.parent_ifindex != props.parent_ifindex) - g_object_notify (object, NM_DEVICE_GRE_PARENT); - if (priv->props.input_flags != props.input_flags) - g_object_notify (object, NM_DEVICE_GRE_INPUT_FLAGS); - if (priv->props.output_flags != props.output_flags) - g_object_notify (object, NM_DEVICE_GRE_OUTPUT_FLAGS); - if (priv->props.input_key != props.input_key) - g_object_notify (object, NM_DEVICE_GRE_INPUT_KEY); - if (priv->props.output_key != props.output_key) - g_object_notify (object, NM_DEVICE_GRE_OUTPUT_KEY); - if (priv->props.local != props.local) - g_object_notify (object, NM_DEVICE_GRE_LOCAL); - if (priv->props.remote != props.remote) - g_object_notify (object, NM_DEVICE_GRE_REMOTE); - if (priv->props.ttl != props.ttl) - g_object_notify (object, NM_DEVICE_GRE_TTL); - if (priv->props.tos != props.tos) - g_object_notify (object, NM_DEVICE_GRE_TOS); - if (priv->props.path_mtu_discovery != props.path_mtu_discovery) - g_object_notify (object, NM_DEVICE_GRE_PATH_MTU_DISCOVERY); - - memcpy (&priv->props, &props, sizeof (NMPlatformGreProperties)); - - g_object_thaw_notify (object); -} - -static void -link_changed (NMDevice *device, NMPlatformLink *info) -{ - NM_DEVICE_CLASS (nm_device_gre_parent_class)->link_changed (device, info); - update_properties (device); -} - -/**************************************************************/ - -static void -nm_device_gre_init (NMDeviceGre *self) -{ -} - -static void -constructed (GObject *object) -{ - update_properties (NM_DEVICE (object)); - - G_OBJECT_CLASS (nm_device_gre_parent_class)->constructed (object); -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMDeviceGrePrivate *priv = NM_DEVICE_GRE_GET_PRIVATE (object); - char buf[INET_ADDRSTRLEN]; - NMDevice *parent; - - switch (prop_id) { - case PROP_PARENT: - parent = nm_manager_get_device_by_ifindex (nm_manager_get (), priv->props.parent_ifindex); - g_value_set_boxed (value, parent ? nm_device_get_path (parent) : "/"); - break; - case PROP_INPUT_FLAGS: - g_value_set_uint (value, priv->props.input_flags); - break; - case PROP_OUTPUT_FLAGS: - g_value_set_uint (value, priv->props.output_flags); - break; - case PROP_INPUT_KEY: - g_value_set_uint (value, priv->props.input_key); - break; - case PROP_OUTPUT_KEY: - g_value_set_uint (value, priv->props.output_key); - break; - case PROP_LOCAL: - g_value_set_string (value, inet_ntop (AF_INET, &priv->props.local, buf, sizeof (buf))); - break; - case PROP_REMOTE: - g_value_set_string (value, inet_ntop (AF_INET, &priv->props.remote, buf, sizeof (buf))); - break; - case PROP_TTL: - g_value_set_uchar (value, priv->props.ttl); - break; - case PROP_TOS: - g_value_set_uchar (value, priv->props.tos); - break; - case PROP_PATH_MTU_DISCOVERY: - g_value_set_boolean (value, priv->props.path_mtu_discovery); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -nm_device_gre_class_init (NMDeviceGreClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); - - g_type_class_add_private (klass, sizeof (NMDeviceGrePrivate)); - - object_class->constructed = constructed; - object_class->get_property = get_property; - - device_class->link_changed = link_changed; - - /* properties */ - g_object_class_install_property - (object_class, PROP_PARENT, - g_param_spec_boxed (NM_DEVICE_GRE_PARENT, "", "", - DBUS_TYPE_G_OBJECT_PATH, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_INPUT_FLAGS, - g_param_spec_uint (NM_DEVICE_GRE_INPUT_FLAGS, "", "", - 0, G_MAXUINT16, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_OUTPUT_FLAGS, - g_param_spec_uint (NM_DEVICE_GRE_OUTPUT_FLAGS, "", "", - 0, G_MAXUINT16, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_INPUT_KEY, - g_param_spec_uint (NM_DEVICE_GRE_INPUT_KEY, "", "", - 0, G_MAXUINT32, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_OUTPUT_KEY, - g_param_spec_uint (NM_DEVICE_GRE_OUTPUT_KEY, "", "", - 0, G_MAXUINT32, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_LOCAL, - g_param_spec_string (NM_DEVICE_GRE_LOCAL, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_REMOTE, - g_param_spec_string (NM_DEVICE_GRE_REMOTE, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_TTL, - g_param_spec_uchar (NM_DEVICE_GRE_TTL, "", "", - 0, 255, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_TOS, - g_param_spec_uchar (NM_DEVICE_GRE_TOS, "", "", - 0, 255, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_PATH_MTU_DISCOVERY, - g_param_spec_boolean (NM_DEVICE_GRE_PATH_MTU_DISCOVERY, "", "", - FALSE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), - G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_gre_object_info); -} - -/*************************************************************/ - -#define NM_TYPE_GRE_FACTORY (nm_gre_factory_get_type ()) -#define NM_GRE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_GRE_FACTORY, NMGreFactory)) - -static NMDevice * -new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error) -{ - return (NMDevice *) g_object_new (NM_TYPE_DEVICE_GRE, - NM_DEVICE_PLATFORM_DEVICE, plink, - NM_DEVICE_TYPE_DESC, "Gre", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_GENERIC, - NULL); -} - -NM_DEVICE_FACTORY_DEFINE_INTERNAL (GRE, Gre, gre, - NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_GRE, NM_LINK_TYPE_GRETAP), - factory_iface->new_link = new_link; - ) - diff --git a/src/devices/nm-device-gre.h b/src/devices/nm-device-gre.h deleted file mode 100644 index 7acff5f7..00000000 --- a/src/devices/nm-device-gre.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 2013 Red Hat, Inc. - */ - -#ifndef __NETWORKMANAGER_DEVICE_GRE_H__ -#define __NETWORKMANAGER_DEVICE_GRE_H__ - -#include <glib-object.h> - -#include "nm-device-generic.h" - -G_BEGIN_DECLS - -#define NM_TYPE_DEVICE_GRE (nm_device_gre_get_type ()) -#define NM_DEVICE_GRE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_GRE, NMDeviceGre)) -#define NM_DEVICE_GRE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_GRE, NMDeviceGreClass)) -#define NM_IS_DEVICE_GRE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_GRE)) -#define NM_IS_DEVICE_GRE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_GRE)) -#define NM_DEVICE_GRE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_GRE, NMDeviceGreClass)) - -#define NM_DEVICE_GRE_PARENT "parent" -#define NM_DEVICE_GRE_INPUT_FLAGS "input-flags" -#define NM_DEVICE_GRE_OUTPUT_FLAGS "output-flags" -#define NM_DEVICE_GRE_INPUT_KEY "input-key" -#define NM_DEVICE_GRE_OUTPUT_KEY "output-key" -#define NM_DEVICE_GRE_LOCAL "local" -#define NM_DEVICE_GRE_REMOTE "remote" -#define NM_DEVICE_GRE_TTL "ttl" -#define NM_DEVICE_GRE_TOS "tos" -#define NM_DEVICE_GRE_PATH_MTU_DISCOVERY "path-mtu-discovery" - -typedef NMDeviceGeneric NMDeviceGre; -typedef NMDeviceGenericClass NMDeviceGreClass; - -GType nm_device_gre_get_type (void); - -G_END_DECLS - -#endif /* NM_DEVICE_GRE_H */ diff --git a/src/devices/nm-device-infiniband.c b/src/devices/nm-device-infiniband.c index c1571fd9..45df49fe 100644 --- a/src/devices/nm-device-infiniband.c +++ b/src/devices/nm-device-infiniband.c @@ -20,25 +20,20 @@ #include "config.h" -#include <glib.h> -#include <glib/gi18n.h> - #include <linux/if_infiniband.h> +#include "nm-default.h" #include "nm-device-infiniband.h" -#include "nm-logging.h" #include "NetworkManagerUtils.h" #include "nm-device-private.h" #include "nm-enum-types.h" -#include "nm-dbus-manager.h" #include "nm-activation-request.h" #include "nm-ip4-config.h" #include "nm-platform.h" #include "nm-device-factory.h" #include "nm-core-internal.h" -#include "nm-device-infiniband-glue.h" - +#include "nmdbus-device-infiniband.h" G_DEFINE_TYPE (NMDeviceInfiniband, nm_device_infiniband, NM_TYPE_DEVICE) @@ -57,10 +52,7 @@ enum { LAST_PROP }; -static void -nm_device_infiniband_init (NMDeviceInfiniband * self) -{ -} +/*************************************************************/ static NMDeviceCapabilities get_generic_capabilities (NMDevice *dev) @@ -82,7 +74,7 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) NMSettingInfiniband *s_infiniband; const char *transport_mode; char *mode_path; - gboolean ok; + gboolean ok, no_firmware = FALSE; g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); @@ -93,7 +85,7 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) req = nm_device_get_act_request (dev); g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); - connection = nm_act_request_get_connection (req); + connection = nm_act_request_get_applied_connection (req); g_assert (connection); s_infiniband = nm_connection_get_setting_infiniband (connection); g_assert (s_infiniband); @@ -113,8 +105,11 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) } } + /* With some drivers the interface must be down to set transport mode */ + nm_device_take_down (dev, TRUE); ok = nm_platform_sysctl_set (NM_PLATFORM_GET, mode_path, transport_mode); g_free (mode_path); + nm_device_bring_up (dev, TRUE, &no_firmware); if (!ok) { *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; @@ -131,7 +126,7 @@ ip4_config_pre_commit (NMDevice *self, NMIP4Config *config) NMSettingInfiniband *s_infiniband; guint32 mtu; - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); g_assert (connection); s_infiniband = nm_connection_get_setting_infiniband (connection); g_assert (s_infiniband); @@ -157,7 +152,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) if (!s_infiniband) return FALSE; - if (s_infiniband) { + if (nm_device_is_real (device)) { const char *mac; mac = nm_setting_infiniband_get_mac_address (s_infiniband); @@ -234,12 +229,69 @@ update_connection (NMDevice *device, NMConnection *connection) ifindex = nm_device_get_ifindex (device); if (ifindex > 0) { - if (!nm_platform_infiniband_get_info (NM_PLATFORM_GET, ifindex, NULL, NULL, &transport_mode)) + if (!nm_platform_link_infiniband_get_properties (NM_PLATFORM_GET, ifindex, NULL, NULL, &transport_mode)) transport_mode = "datagram"; } g_object_set (G_OBJECT (s_infiniband), NM_SETTING_INFINIBAND_TRANSPORT_MODE, transport_mode, NULL); } +static gboolean +create_and_realize (NMDevice *device, + NMConnection *connection, + NMDevice *parent, + const NMPlatformLink **out_plink, + GError **error) +{ + NMSettingInfiniband *s_infiniband; + int parent_ifindex, p_key; + NMPlatformError plerr; + + if (!NM_IS_DEVICE_INFINIBAND (parent)) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, + "Parent interface %s must be an InfiniBand interface", + nm_device_get_iface (parent)); + return FALSE; + } + + s_infiniband = nm_connection_get_setting_infiniband (connection); + + /* Can only create partitions at this time */ + p_key = nm_setting_infiniband_get_p_key (s_infiniband); + if (p_key < 0) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, + "only InfiniBand partitions can be created"); + return FALSE; + } + + parent_ifindex = nm_device_get_ifindex (parent); + if (parent_ifindex <= 0) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, + "failed to get InfiniBand parent %s ifindex", + nm_device_get_iface (parent)); + return FALSE; + } + + plerr = nm_platform_link_infiniband_add (NM_PLATFORM_GET, parent_ifindex, p_key, out_plink); + if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, + "Failed to create InfiniBand P_Key interface '%s' for '%s': %s", + nm_device_get_iface (device), + nm_connection_get_id (connection), + nm_platform_error_to_string (plerr)); + return FALSE; + } + + NM_DEVICE_INFINIBAND_GET_PRIVATE (device)->is_partition = TRUE; + return TRUE; +} + +/*************************************************************/ + +static void +nm_device_infiniband_init (NMDeviceInfiniband * self) +{ +} + static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) @@ -276,10 +328,13 @@ nm_device_infiniband_class_init (NMDeviceInfinibandClass *klass) g_type_class_add_private (object_class, sizeof (NMDeviceInfinibandPrivate)); + NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_INFINIBAND_SETTING_NAME, NM_LINK_TYPE_INFINIBAND) + /* virtual methods */ object_class->get_property = get_property; object_class->set_property = set_property; + parent_class->create_and_realize = create_and_realize; parent_class->get_generic_capabilities = get_generic_capabilities; parent_class->check_connection_compatible = check_connection_compatible; parent_class->complete_connection = complete_connection; @@ -296,9 +351,9 @@ nm_device_infiniband_class_init (NMDeviceInfinibandClass *klass) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); - nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), - G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_infiniband_object_info); + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_INFINIBAND_SKELETON, + NULL); } /*************************************************************/ @@ -307,60 +362,33 @@ nm_device_infiniband_class_init (NMDeviceInfinibandClass *klass) #define NM_INFINIBAND_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_INFINIBAND_FACTORY, NMInfinibandFactory)) static NMDevice * -new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error) +create_device (NMDeviceFactory *factory, + const char *iface, + const NMPlatformLink *plink, + NMConnection *connection, + gboolean *out_ignore) { - return (NMDevice *) g_object_new (NM_TYPE_DEVICE_INFINIBAND, - NM_DEVICE_PLATFORM_DEVICE, plink, - NM_DEVICE_TYPE_DESC, "InfiniBand", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_INFINIBAND, - NM_DEVICE_INFINIBAND_IS_PARTITION, (plink->parent > 0 || plink->parent == NM_PLATFORM_LINK_OTHER_NETNS), - NULL); -} - -static NMDevice * -create_virtual_device_for_connection (NMDeviceFactory *factory, - NMConnection *connection, - NMDevice *parent, - GError **error) -{ - NMSettingInfiniband *s_infiniband; - int p_key, parent_ifindex; - const char *iface; - NMPlatformError plerr; - const NMPlatformLink *plink; - - if (!NM_IS_DEVICE_INFINIBAND (parent)) { - g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, - "Parent interface %s must be an InfiniBand interface", - nm_device_get_iface (parent)); - return NULL; - } - - s_infiniband = nm_connection_get_setting_infiniband (connection); - - iface = nm_setting_infiniband_get_virtual_interface_name (s_infiniband); - g_assert (iface); - - parent_ifindex = nm_device_get_ifindex (parent); - p_key = nm_setting_infiniband_get_p_key (s_infiniband); - - plerr = nm_platform_infiniband_partition_add (NM_PLATFORM_GET, parent_ifindex, p_key, NULL); - if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { - g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, - "Failed to create InfiniBand P_Key interface '%s' for '%s': %s", - iface, - nm_connection_get_id (connection), - nm_platform_error_to_string (plerr)); - return NULL; + gboolean is_partition = FALSE; + + if (plink) + is_partition = (plink->parent > 0 || plink->parent == NM_PLATFORM_LINK_OTHER_NETNS); + else if (connection) { + NMSettingInfiniband *s_infiniband; + + s_infiniband = nm_connection_get_setting_infiniband (connection); + g_return_val_if_fail (s_infiniband, NULL); + is_partition = !!nm_setting_infiniband_get_parent (s_infiniband) + || ( nm_setting_infiniband_get_p_key (s_infiniband) >= 0 + && nm_setting_infiniband_get_mac_address (s_infiniband)); } - plink = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, iface); return (NMDevice *) g_object_new (NM_TYPE_DEVICE_INFINIBAND, - NM_DEVICE_PLATFORM_DEVICE, plink, - NM_DEVICE_DRIVER, nm_device_get_driver (parent), + NM_DEVICE_IFACE, iface, NM_DEVICE_TYPE_DESC, "InfiniBand", NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_INFINIBAND, - NM_DEVICE_INFINIBAND_IS_PARTITION, TRUE, + NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_INFINIBAND, + /* XXX: Partition should probably be a different link type! */ + NM_DEVICE_INFINIBAND_IS_PARTITION, is_partition, NULL); } @@ -400,8 +428,7 @@ get_virtual_iface_name (NMDeviceFactory *factory, NM_DEVICE_FACTORY_DEFINE_INTERNAL (INFINIBAND, Infiniband, infiniband, NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_INFINIBAND) NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_INFINIBAND_SETTING_NAME), - factory_iface->new_link = new_link; - factory_iface->create_virtual_device_for_connection = create_virtual_device_for_connection; + factory_iface->create_device = create_device; factory_iface->get_connection_parent = get_connection_parent; factory_iface->get_virtual_iface_name = get_virtual_iface_name; ) diff --git a/src/devices/nm-device-infiniband.h b/src/devices/nm-device-infiniband.h index b81b762a..cac9a79d 100644 --- a/src/devices/nm-device-infiniband.h +++ b/src/devices/nm-device-infiniband.h @@ -21,8 +21,6 @@ #ifndef __NETWORKMANAGER_DEVICE_INFINIBAND_H__ #define __NETWORKMANAGER_DEVICE_INFINIBAND_H__ -#include <glib-object.h> - #include "nm-device.h" G_BEGIN_DECLS diff --git a/src/devices/nm-device-ip-tunnel.c b/src/devices/nm-device-ip-tunnel.c new file mode 100644 index 00000000..6d0df059 --- /dev/null +++ b/src/devices/nm-device-ip-tunnel.c @@ -0,0 +1,1052 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2015 Red Hat, Inc. + */ + +#include "config.h" + +#include <string.h> +#include <netinet/in.h> +#include <linux/if.h> +#include <linux/ip.h> +#include <linux/if_tunnel.h> + +#include "nm-device-ip-tunnel.h" +#include "nm-device-private.h" +#include "nm-default.h" +#include "nm-manager.h" +#include "nm-platform.h" +#include "nm-device-factory.h" +#include "nm-core-internal.h" +#include "nm-connection-provider.h" +#include "nm-activation-request.h" +#include "nm-ip4-config.h" + +#include "nmdbus-device-ip-tunnel.h" + +#include "nm-device-logging.h" +_LOG_DECLARE_SELF(NMDeviceIPTunnel); + +G_DEFINE_TYPE (NMDeviceIPTunnel, nm_device_ip_tunnel, NM_TYPE_DEVICE) + +#define NM_DEVICE_IP_TUNNEL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_IP_TUNNEL, NMDeviceIPTunnelPrivate)) + +typedef struct { + NMIPTunnelMode mode; + NMDevice *parent; + int parent_ifindex; + char *local; + char *remote; + guint8 ttl; + guint8 tos; + gboolean path_mtu_discovery; + int addr_family; + char *input_key; + char *output_key; + guint8 encap_limit; + guint32 flow_label; +} NMDeviceIPTunnelPrivate; + +enum { + PROP_0, + PROP_MODE, + PROP_PARENT, + PROP_LOCAL, + PROP_REMOTE, + PROP_TTL, + PROP_TOS, + PROP_PATH_MTU_DISCOVERY, + PROP_INPUT_KEY, + PROP_OUTPUT_KEY, + PROP_ENCAPSULATION_LIMIT, + PROP_FLOW_LABEL, + + LAST_PROP +}; + +/**************************************************************/ + +static gboolean +address_equal_pp (int family, const char *a, const char *b) +{ + char buffer1[sizeof (struct in6_addr)] = { }; + char buffer2[sizeof (struct in6_addr)] = { }; + + g_return_val_if_fail (family == AF_INET || family == AF_INET6, FALSE); + + if (a) + inet_pton (family, a, buffer1); + if (b) + inet_pton (family, b, buffer2); + + return !memcmp (buffer1, buffer2, + family == AF_INET ? sizeof (in_addr_t) : sizeof (struct in6_addr)); +} + +static gboolean +address_equal_pn (int family, const char *a, const void *b) +{ + char buffer1[sizeof (struct in6_addr)] = { }; + + g_return_val_if_fail (family == AF_INET || family == AF_INET6, FALSE); + + if (a) + inet_pton (family, a, buffer1); + + return !memcmp (buffer1, b, + family == AF_INET ? sizeof (in_addr_t) : sizeof (struct in6_addr)); + +} + +static void +update_properties_from_ifindex (NMDevice *device, int ifindex) +{ + NMDeviceIPTunnel *self = NM_DEVICE_IP_TUNNEL (device); + NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (self); + GObject *object = G_OBJECT (device); + NMDevice *parent; + int parent_ifindex; + in_addr_t local4, remote4; + struct in6_addr local6, remote6; + guint8 ttl = 0, tos = 0, encap_limit = 0; + gboolean pmtud = FALSE; + guint32 flow_label = 0; + char *key; + + if (ifindex <= 0) { +clear: + if (priv->parent || priv->parent_ifindex) { + g_clear_object (&priv->parent); + priv->parent_ifindex = 0; + g_object_notify (object, NM_DEVICE_IP_TUNNEL_PARENT); + } + if (priv->local) { + g_clear_pointer (&priv->local, g_free); + g_object_notify (object, NM_DEVICE_IP_TUNNEL_LOCAL); + } + if (priv->remote) { + g_clear_pointer (&priv->remote, g_free); + g_object_notify (object, NM_DEVICE_IP_TUNNEL_REMOTE); + } + if (priv->input_key) { + g_clear_pointer (&priv->input_key, g_free); + g_object_notify (object, NM_DEVICE_IP_TUNNEL_INPUT_KEY); + } + if (priv->output_key) { + g_clear_pointer (&priv->output_key, g_free); + g_object_notify (object, NM_DEVICE_IP_TUNNEL_OUTPUT_KEY); + } + + goto out; + } + + if (priv->mode == NM_IP_TUNNEL_MODE_GRE) { + const NMPlatformLnkGre *lnk; + + lnk = nm_platform_link_get_lnk_gre (NM_PLATFORM_GET, ifindex, NULL); + if (!lnk) { + _LOGW (LOGD_HW, "could not read %s properties", "gre"); + goto clear; + } + + parent_ifindex = lnk->parent_ifindex; + local4 = lnk->local; + remote4 = lnk->remote; + ttl = lnk->ttl; + tos = lnk->tos; + pmtud = lnk->path_mtu_discovery; + + if (NM_FLAGS_HAS (lnk->input_flags, NM_GRE_KEY)) { + key = g_strdup_printf ("%u", lnk->input_key); + if (g_strcmp0 (priv->input_key, key)) { + g_free (priv->input_key); + priv->input_key = key; + g_object_notify (object, NM_DEVICE_IP_TUNNEL_INPUT_KEY); + } else + g_free (key); + } else { + if (priv->input_key) { + g_clear_pointer (&priv->input_key, g_free); + g_object_notify (object, NM_DEVICE_IP_TUNNEL_INPUT_KEY); + } + } + + if (NM_FLAGS_HAS (lnk->output_flags, NM_GRE_KEY)) { + key = g_strdup_printf ("%u", lnk->output_key); + if (g_strcmp0 (priv->output_key, key)) { + g_free (priv->output_key); + priv->output_key = key; + g_object_notify (object, NM_DEVICE_IP_TUNNEL_OUTPUT_KEY); + } else + g_free (key); + } else { + if (priv->output_key) { + g_clear_pointer (&priv->output_key, g_free); + g_object_notify (object, NM_DEVICE_IP_TUNNEL_OUTPUT_KEY); + } + } + } else if (priv->mode == NM_IP_TUNNEL_MODE_SIT) { + const NMPlatformLnkSit *lnk; + + lnk = nm_platform_link_get_lnk_sit (NM_PLATFORM_GET, ifindex, NULL); + if (!lnk) { + _LOGW (LOGD_HW, "could not read %s properties", "sit"); + goto clear; + } + + parent_ifindex = lnk->parent_ifindex; + local4 = lnk->local; + remote4 = lnk->remote; + ttl = lnk->ttl; + tos = lnk->tos; + pmtud = lnk->path_mtu_discovery; + } else if (priv->mode == NM_IP_TUNNEL_MODE_IPIP) { + const NMPlatformLnkIpIp *lnk; + + lnk = nm_platform_link_get_lnk_ipip (NM_PLATFORM_GET, ifindex, NULL); + if (!lnk) { + _LOGW (LOGD_HW, "could not read %s properties", "ipip"); + goto clear; + } + + parent_ifindex = lnk->parent_ifindex; + local4 = lnk->local; + remote4 = lnk->remote; + ttl = lnk->ttl; + tos = lnk->tos; + pmtud = lnk->path_mtu_discovery; + } else if ( priv->mode == NM_IP_TUNNEL_MODE_IPIP6 + || priv->mode == NM_IP_TUNNEL_MODE_IP6IP6) { + const NMPlatformLnkIp6Tnl *lnk; + + lnk = nm_platform_link_get_lnk_ip6tnl (NM_PLATFORM_GET, ifindex, NULL); + if (!lnk) { + _LOGW (LOGD_HW, "could not read %s properties", "ip6tnl"); + goto clear; + } + + parent_ifindex = lnk->parent_ifindex; + local6 = lnk->local; + remote6 = lnk->remote; + ttl = lnk->ttl; + tos = lnk->tclass; + encap_limit = lnk->encap_limit; + flow_label = lnk->flow_label; + } else + g_return_if_reached (); + + if (priv->parent_ifindex != parent_ifindex) { + g_clear_object (&priv->parent); + priv->parent_ifindex = parent_ifindex; + parent = nm_manager_get_device_by_ifindex (nm_manager_get (), parent_ifindex); + if (parent) + priv->parent = g_object_ref (parent); + g_object_notify (object, NM_DEVICE_IP_TUNNEL_PARENT); + } + + if (priv->addr_family == AF_INET) { + if (!address_equal_pn (AF_INET, priv->local, &local4)) { + g_clear_pointer (&priv->local, g_free); + if (local4) + priv->local = g_strdup (nm_utils_inet4_ntop (local4, NULL)); + g_object_notify (object, NM_DEVICE_IP_TUNNEL_LOCAL); + } + + if (!address_equal_pn (AF_INET, priv->remote, &remote4)) { + g_clear_pointer (&priv->remote, g_free); + if (remote4) + priv->remote = g_strdup (nm_utils_inet4_ntop (remote4, NULL)); + g_object_notify (object, NM_DEVICE_IP_TUNNEL_REMOTE); + } + } else { + if (!address_equal_pn (AF_INET6, priv->local, &local6)) { + g_clear_pointer (&priv->local, g_free); + if (memcmp (&local6, &in6addr_any, sizeof (in6addr_any))) + priv->local = g_strdup (nm_utils_inet6_ntop (&local6, NULL)); + g_object_notify (object, NM_DEVICE_IP_TUNNEL_LOCAL); + } + + if (!address_equal_pn (AF_INET6, priv->remote, &remote6)) { + g_clear_pointer (&priv->remote, g_free); + if (memcmp (&remote6, &in6addr_any, sizeof (in6addr_any))) + priv->remote = g_strdup (nm_utils_inet6_ntop (&remote6, NULL)); + g_object_notify (object, NM_DEVICE_IP_TUNNEL_REMOTE); + } + } + +out: + + if (priv->ttl != ttl) { + priv->ttl = ttl; + g_object_notify (object, NM_DEVICE_IP_TUNNEL_TTL); + } + + if (priv->tos != tos) { + priv->tos = tos; + g_object_notify (object, NM_DEVICE_IP_TUNNEL_TOS); + } + + if (priv->path_mtu_discovery != pmtud) { + priv->path_mtu_discovery = pmtud; + g_object_notify (object, NM_DEVICE_IP_TUNNEL_PATH_MTU_DISCOVERY); + } + + if (priv->encap_limit != encap_limit) { + priv->encap_limit = encap_limit; + g_object_notify (object, NM_DEVICE_IP_TUNNEL_ENCAPSULATION_LIMIT); + } + + if (priv->flow_label != flow_label) { + priv->flow_label = flow_label; + g_object_notify (object, NM_DEVICE_IP_TUNNEL_FLOW_LABEL); + } +} + +static void +update_properties (NMDevice *device) +{ + update_properties_from_ifindex (device, nm_device_get_ifindex (device)); +} + +static void +link_changed (NMDevice *device, NMPlatformLink *info) +{ + NM_DEVICE_CLASS (nm_device_ip_tunnel_parent_class)->link_changed (device, info); + update_properties (device); +} + +static gboolean +complete_connection (NMDevice *device, + NMConnection *connection, + const char *specific_object, + const GSList *existing_connections, + GError **error) +{ + NMSettingIPTunnel *s_ip_tunnel; + + nm_utils_complete_generic (connection, + NM_SETTING_IP_TUNNEL_SETTING_NAME, + existing_connections, + NULL, + _("IP tunnel connection"), + NULL, + TRUE); + + s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection); + if (!s_ip_tunnel) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, + "A 'tunnel' setting is required."); + return FALSE; + } + + return TRUE; +} + +static void +update_connection (NMDevice *device, NMConnection *connection) +{ + NMDeviceIPTunnel *self = NM_DEVICE_IP_TUNNEL (device); + NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (self); + NMSettingIPTunnel *s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection); + NMDevice *parent = NULL; + const char *setting_parent, *new_parent; + + if (!s_ip_tunnel) { + s_ip_tunnel = (NMSettingIPTunnel *) nm_setting_ip_tunnel_new (); + nm_connection_add_setting (connection, (NMSetting *) s_ip_tunnel); + } + + if (nm_setting_ip_tunnel_get_mode (s_ip_tunnel) != priv->mode) + g_object_set (G_OBJECT (s_ip_tunnel), NM_SETTING_IP_TUNNEL_MODE, priv->mode, NULL); + + if (priv->parent_ifindex > 0) + parent = nm_manager_get_device_by_ifindex (nm_manager_get (), priv->parent_ifindex); + + /* Update parent in the connection; default to parent's interface name */ + if (parent) { + new_parent = nm_device_get_iface (parent); + setting_parent = nm_setting_ip_tunnel_get_parent (s_ip_tunnel); + if (setting_parent && nm_utils_is_uuid (setting_parent)) { + NMConnection *parent_connection; + + /* Don't change a parent specified by UUID if it's still valid */ + parent_connection = nm_connection_provider_get_connection_by_uuid (nm_connection_provider_get (), + setting_parent); + if (parent_connection && nm_device_check_connection_compatible (parent, parent_connection)) + new_parent = NULL; + } + if (new_parent) + g_object_set (s_ip_tunnel, NM_SETTING_IP_TUNNEL_PARENT, new_parent, NULL); + } else + g_object_set (s_ip_tunnel, NM_SETTING_IP_TUNNEL_PARENT, NULL, NULL); + + if (!address_equal_pp (priv->addr_family, + nm_setting_ip_tunnel_get_local (s_ip_tunnel), + priv->local)) + g_object_set (G_OBJECT (s_ip_tunnel), NM_SETTING_IP_TUNNEL_LOCAL, priv->local, NULL); + + if (!address_equal_pp (priv->addr_family, + nm_setting_ip_tunnel_get_remote (s_ip_tunnel), + priv->remote)) + g_object_set (G_OBJECT (s_ip_tunnel), NM_SETTING_IP_TUNNEL_REMOTE, priv->remote, NULL); + + if (nm_setting_ip_tunnel_get_ttl (s_ip_tunnel) != priv->ttl) + g_object_set (G_OBJECT (s_ip_tunnel), NM_SETTING_IP_TUNNEL_TTL, priv->ttl, NULL); + + if (nm_setting_ip_tunnel_get_tos (s_ip_tunnel) != priv->tos) + g_object_set (G_OBJECT (s_ip_tunnel), NM_SETTING_IP_TUNNEL_TOS, priv->tos, NULL); + + if (nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel) != priv->path_mtu_discovery) { + g_object_set (G_OBJECT (s_ip_tunnel), + NM_SETTING_IP_TUNNEL_PATH_MTU_DISCOVERY, + priv->path_mtu_discovery, + NULL); + } + + if (nm_setting_ip_tunnel_get_encapsulation_limit (s_ip_tunnel) != priv->encap_limit) { + g_object_set (G_OBJECT (s_ip_tunnel), + NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT, + priv->encap_limit, + NULL); + } + + if (nm_setting_ip_tunnel_get_flow_label (s_ip_tunnel) != priv->flow_label) { + g_object_set (G_OBJECT (s_ip_tunnel), + NM_SETTING_IP_TUNNEL_FLOW_LABEL, + priv->flow_label, + NULL); + } + + if (priv->mode == NM_IP_TUNNEL_MODE_GRE || priv->mode == NM_IP_TUNNEL_MODE_IP6GRE) { + if (g_strcmp0 (nm_setting_ip_tunnel_get_input_key (s_ip_tunnel), priv->input_key)) { + g_object_set (G_OBJECT (s_ip_tunnel), + NM_SETTING_IP_TUNNEL_INPUT_KEY, + priv->input_key, + NULL); + } + if (g_strcmp0 (nm_setting_ip_tunnel_get_output_key (s_ip_tunnel), priv->output_key)) { + g_object_set (G_OBJECT (s_ip_tunnel), + NM_SETTING_IP_TUNNEL_OUTPUT_KEY, + priv->output_key, + NULL); + } + } +} + +static gboolean +match_parent (NMDevice *dev_parent, const char *setting_parent) +{ + g_return_val_if_fail (setting_parent, FALSE); + + if (!dev_parent) + return FALSE; + + if (nm_utils_is_uuid (setting_parent)) { + NMActRequest *parent_req; + NMConnection *parent_connection; + + /* If the parent is a UUID, the connection matches if our parent + * device has that connection activated. + */ + parent_req = nm_device_get_act_request (dev_parent); + if (!parent_req) + return FALSE; + + parent_connection = nm_active_connection_get_applied_connection (NM_ACTIVE_CONNECTION (parent_req)); + if (!parent_connection) + return FALSE; + + if (g_strcmp0 (setting_parent, nm_connection_get_uuid (parent_connection)) != 0) + return FALSE; + } else { + /* interface name */ + if (g_strcmp0 (setting_parent, nm_device_get_ip_iface (dev_parent)) != 0) + return FALSE; + } + + return TRUE; +} + +static gboolean +check_connection_compatible (NMDevice *device, NMConnection *connection) +{ + NMDeviceIPTunnel *self = NM_DEVICE_IP_TUNNEL (device); + NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (self); + NMSettingIPTunnel *s_ip_tunnel; + const char *parent; + + if (!NM_DEVICE_CLASS (nm_device_ip_tunnel_parent_class)->check_connection_compatible (device, connection)) + return FALSE; + + s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection); + if (!s_ip_tunnel) + return FALSE; + + if (nm_setting_ip_tunnel_get_mode (s_ip_tunnel) != priv->mode) + return FALSE; + + if (nm_device_is_real (device)) { + /* Check parent interface; could be an interface name or a UUID */ + parent = nm_setting_ip_tunnel_get_parent (s_ip_tunnel); + if (parent) { + if (!match_parent (priv->parent, parent)) + return FALSE; + } + + if (!address_equal_pp (priv->addr_family, + nm_setting_ip_tunnel_get_local (s_ip_tunnel), + priv->local)) + return FALSE; + + if (!address_equal_pp (priv->addr_family, + nm_setting_ip_tunnel_get_remote (s_ip_tunnel), + priv->remote)) + return FALSE; + + if (nm_setting_ip_tunnel_get_ttl (s_ip_tunnel) != priv->ttl) + return FALSE; + + if (nm_setting_ip_tunnel_get_tos (s_ip_tunnel) != priv->tos) + return FALSE; + + if (priv->addr_family == AF_INET) { + if (nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel) != priv->path_mtu_discovery) + return FALSE; + } else { + if (nm_setting_ip_tunnel_get_encapsulation_limit (s_ip_tunnel) != priv->encap_limit) + return FALSE; + + if (nm_setting_ip_tunnel_get_flow_label (s_ip_tunnel) != priv->flow_label) + return FALSE; + } + } + + return TRUE; +} + +static NMIPTunnelMode +platform_link_to_tunnel_mode (const NMPlatformLink *link) +{ + const NMPlatformLnkIp6Tnl *lnk; + + switch (link->type) { + case NM_LINK_TYPE_GRE: + return NM_IP_TUNNEL_MODE_GRE; + case NM_LINK_TYPE_IP6TNL: + lnk = nm_platform_link_get_lnk_ip6tnl (NM_PLATFORM_GET, link->ifindex, NULL); + if (lnk->proto == IPPROTO_IPIP) + return NM_IP_TUNNEL_MODE_IPIP6; + else if (lnk->proto == IPPROTO_IPV6) + return NM_IP_TUNNEL_MODE_IP6IP6; + else + return NM_IP_TUNNEL_MODE_UKNOWN; + case NM_LINK_TYPE_IPIP: + return NM_IP_TUNNEL_MODE_IPIP; + case NM_LINK_TYPE_SIT: + return NM_IP_TUNNEL_MODE_SIT; + default: + g_return_val_if_reached (NM_IP_TUNNEL_MODE_UKNOWN); + } +} + +static NMLinkType +tunnel_mode_to_link_type (NMIPTunnelMode tunnel_mode) +{ + switch (tunnel_mode) { + case NM_IP_TUNNEL_MODE_GRE: + return NM_LINK_TYPE_GRE; + case NM_IP_TUNNEL_MODE_IPIP6: + case NM_IP_TUNNEL_MODE_IP6IP6: + return NM_LINK_TYPE_IP6TNL; + case NM_IP_TUNNEL_MODE_IPIP: + return NM_LINK_TYPE_IPIP; + case NM_IP_TUNNEL_MODE_SIT: + return NM_LINK_TYPE_SIT; + default: + g_return_val_if_reached (NM_LINK_TYPE_UNKNOWN); + } +} + +/**************************************************************/ + +static void +nm_device_ip_tunnel_init (NMDeviceIPTunnel *self) +{ +} + +static void +constructed (GObject *object) +{ + NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (object); + + if ( priv->mode == NM_IP_TUNNEL_MODE_IPIP6 + || priv->mode == NM_IP_TUNNEL_MODE_IP6IP6) + priv->addr_family = AF_INET6; + else + priv->addr_family = AF_INET; + + G_OBJECT_CLASS (nm_device_ip_tunnel_parent_class)->constructed (object); +} + +static gboolean +create_and_realize (NMDevice *device, + NMConnection *connection, + NMDevice *parent, + const NMPlatformLink **out_plink, + GError **error) +{ + const char *iface = nm_device_get_iface (device); + NMSettingIPTunnel *s_ip_tunnel; + NMPlatformError plerr; + NMPlatformLnkGre lnk_gre = { }; + NMPlatformLnkSit lnk_sit = { }; + NMPlatformLnkIpIp lnk_ipip = { }; + NMPlatformLnkIp6Tnl lnk_ip6tnl = { }; + const char *str; + gint64 val; + + s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection); + g_assert (s_ip_tunnel); + + switch (nm_setting_ip_tunnel_get_mode (s_ip_tunnel)) { + case NM_IP_TUNNEL_MODE_GRE: + if (parent) + lnk_gre.parent_ifindex = nm_device_get_ifindex (parent); + + str = nm_setting_ip_tunnel_get_local (s_ip_tunnel); + if (str) + inet_pton (AF_INET, str, &lnk_gre.local); + + str = nm_setting_ip_tunnel_get_remote (s_ip_tunnel); + g_assert (str); + inet_pton (AF_INET, str, &lnk_gre.remote); + + lnk_gre.ttl = nm_setting_ip_tunnel_get_ttl (s_ip_tunnel); + lnk_gre.tos = nm_setting_ip_tunnel_get_tos (s_ip_tunnel); + lnk_gre.path_mtu_discovery = nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel); + + val = _nm_utils_ascii_str_to_int64 (nm_setting_ip_tunnel_get_input_key (s_ip_tunnel), + 10, + 0, + G_MAXUINT32, + -1); + if (val != -1) { + lnk_gre.input_key = val; + lnk_gre.input_flags = NM_GRE_KEY; + } + + val = _nm_utils_ascii_str_to_int64 (nm_setting_ip_tunnel_get_output_key (s_ip_tunnel), + 10, + 0, + G_MAXUINT32, + -1); + if (val != -1) { + lnk_gre.output_key = val; + lnk_gre.output_flags = NM_GRE_KEY; + } + + plerr = nm_platform_link_gre_add (NM_PLATFORM_GET, iface, &lnk_gre, out_plink); + if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, + "Failed to create GRE interface '%s' for '%s': %s", + iface, + nm_connection_get_id (connection), + nm_platform_error_to_string (plerr)); + return FALSE; + } + break; + case NM_IP_TUNNEL_MODE_SIT: + if (parent) + lnk_sit.parent_ifindex = nm_device_get_ifindex (parent); + + str = nm_setting_ip_tunnel_get_local (s_ip_tunnel); + if (str) + inet_pton (AF_INET, str, &lnk_sit.local); + + str = nm_setting_ip_tunnel_get_remote (s_ip_tunnel); + g_assert (str); + inet_pton (AF_INET, str, &lnk_sit.remote); + + lnk_sit.ttl = nm_setting_ip_tunnel_get_ttl (s_ip_tunnel); + lnk_sit.tos = nm_setting_ip_tunnel_get_tos (s_ip_tunnel); + lnk_sit.path_mtu_discovery = nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel); + + plerr = nm_platform_link_sit_add (NM_PLATFORM_GET, iface, &lnk_sit, out_plink); + if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, + "Failed to create SIT interface '%s' for '%s': %s", + iface, + nm_connection_get_id (connection), + nm_platform_error_to_string (plerr)); + return FALSE; + } + break; + case NM_IP_TUNNEL_MODE_IPIP: + if (parent) + lnk_ipip.parent_ifindex = nm_device_get_ifindex (parent); + + str = nm_setting_ip_tunnel_get_local (s_ip_tunnel); + if (str) + inet_pton (AF_INET, str, &lnk_ipip.local); + + str = nm_setting_ip_tunnel_get_remote (s_ip_tunnel); + g_assert (str); + inet_pton (AF_INET, str, &lnk_ipip.remote); + + lnk_ipip.ttl = nm_setting_ip_tunnel_get_ttl (s_ip_tunnel); + lnk_ipip.tos = nm_setting_ip_tunnel_get_tos (s_ip_tunnel); + lnk_ipip.path_mtu_discovery = nm_setting_ip_tunnel_get_path_mtu_discovery (s_ip_tunnel); + + plerr = nm_platform_link_ipip_add (NM_PLATFORM_GET, iface, &lnk_ipip, out_plink); + if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, + "Failed to create IPIP interface '%s' for '%s': %s", + iface, + nm_connection_get_id (connection), + nm_platform_error_to_string (plerr)); + return FALSE; + } + break; + case NM_IP_TUNNEL_MODE_IPIP6: + case NM_IP_TUNNEL_MODE_IP6IP6: + if (parent) + lnk_ip6tnl.parent_ifindex = nm_device_get_ifindex (parent); + + str = nm_setting_ip_tunnel_get_local (s_ip_tunnel); + if (str) + inet_pton (AF_INET6, str, &lnk_ip6tnl.local); + + str = nm_setting_ip_tunnel_get_remote (s_ip_tunnel); + g_assert (str); + inet_pton (AF_INET6, str, &lnk_ip6tnl.remote); + + lnk_ip6tnl.ttl = nm_setting_ip_tunnel_get_ttl (s_ip_tunnel); + lnk_ip6tnl.tclass = nm_setting_ip_tunnel_get_tos (s_ip_tunnel); + lnk_ip6tnl.encap_limit = nm_setting_ip_tunnel_get_encapsulation_limit (s_ip_tunnel); + lnk_ip6tnl.flow_label = nm_setting_ip_tunnel_get_flow_label (s_ip_tunnel); + lnk_ip6tnl.proto = nm_setting_ip_tunnel_get_mode (s_ip_tunnel) == NM_IP_TUNNEL_MODE_IPIP6 ? IPPROTO_IPIP : IPPROTO_IPV6; + + plerr = nm_platform_link_ip6tnl_add (NM_PLATFORM_GET, iface, &lnk_ip6tnl, out_plink); + if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, + "Failed to create IPIP interface '%s' for '%s': %s", + iface, + nm_connection_get_id (connection), + nm_platform_error_to_string (plerr)); + return FALSE; + } + break; + default: + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, + "Failed to create IP tunnel interface '%s' for '%s': mode %d not supported", + iface, + nm_connection_get_id (connection), + (int) nm_setting_ip_tunnel_get_mode (s_ip_tunnel)); + return FALSE; + } + + return TRUE; +} + +static void +realize_start_notify (NMDevice *device, const NMPlatformLink *plink) +{ + NM_DEVICE_CLASS (nm_device_ip_tunnel_parent_class)->realize_start_notify (device, plink); + + update_properties (device); +} + +static void +ip4_config_pre_commit (NMDevice *device, NMIP4Config *config) +{ + NMConnection *connection; + NMSettingIPTunnel *s_ip_tunnel; + guint32 mtu; + + connection = nm_device_get_applied_connection (device); + g_assert (connection); + s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection); + g_assert (s_ip_tunnel); + + /* MTU override */ + mtu = nm_setting_ip_tunnel_get_mtu (s_ip_tunnel); + if (mtu) + nm_ip4_config_set_mtu (config, mtu, NM_IP_CONFIG_SOURCE_USER); +} + +static void +unrealize_notify (NMDevice *device) +{ + NM_DEVICE_CLASS (nm_device_ip_tunnel_parent_class)->unrealize_notify (device); + + update_properties_from_ifindex (device, 0); +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (object); + NMDevice *parent; + + switch (prop_id) { + case PROP_MODE: + g_value_set_uint (value, priv->mode); + break; + case PROP_PARENT: + parent = nm_manager_get_device_by_ifindex (nm_manager_get (), priv->parent_ifindex); + nm_utils_g_value_set_object_path (value, parent); + break; + case PROP_LOCAL: + g_value_set_string (value, priv->local); + break; + case PROP_REMOTE: + g_value_set_string (value, priv->remote); + break; + case PROP_TTL: + g_value_set_uchar (value, priv->ttl); + break; + case PROP_TOS: + g_value_set_uchar (value, priv->tos); + break; + case PROP_PATH_MTU_DISCOVERY: + g_value_set_boolean (value, priv->path_mtu_discovery); + break; + case PROP_INPUT_KEY: + g_value_set_string (value, priv->input_key); + break; + case PROP_OUTPUT_KEY: + g_value_set_string (value, priv->output_key); + break; + case PROP_ENCAPSULATION_LIMIT: + g_value_set_uchar (value, priv->encap_limit); + break; + case PROP_FLOW_LABEL: + g_value_set_uint (value, priv->flow_label); + 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) +{ + NMDeviceIPTunnelPrivate *priv = NM_DEVICE_IP_TUNNEL_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_MODE: + priv->mode = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +nm_device_ip_tunnel_class_init (NMDeviceIPTunnelClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMDeviceIPTunnelPrivate)); + + object_class->constructed = constructed; + object_class->get_property = get_property; + object_class->set_property = set_property; + + device_class->link_changed = link_changed; + device_class->complete_connection = complete_connection; + device_class->update_connection = update_connection; + device_class->check_connection_compatible = check_connection_compatible; + device_class->create_and_realize = create_and_realize; + device_class->ip4_config_pre_commit = ip4_config_pre_commit; + device_class->realize_start_notify = realize_start_notify; + device_class->unrealize_notify = unrealize_notify; + + NM_DEVICE_CLASS_DECLARE_TYPES (klass, + NM_SETTING_IP_TUNNEL_SETTING_NAME, + NM_LINK_TYPE_GRE, + NM_LINK_TYPE_IP6TNL, + NM_LINK_TYPE_IPIP, + NM_LINK_TYPE_SIT); + + /* properties */ + g_object_class_install_property + (object_class, PROP_MODE, + g_param_spec_uint (NM_DEVICE_IP_TUNNEL_MODE, "", "", + 0, G_MAXUINT, 0, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + /* properties */ + g_object_class_install_property + (object_class, PROP_PARENT, + g_param_spec_string (NM_DEVICE_IP_TUNNEL_PARENT, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_LOCAL, + g_param_spec_string (NM_DEVICE_IP_TUNNEL_LOCAL, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_REMOTE, + g_param_spec_string (NM_DEVICE_IP_TUNNEL_REMOTE, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_TTL, + g_param_spec_uchar (NM_DEVICE_IP_TUNNEL_TTL, "", "", + 0, 255, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_TOS, + g_param_spec_uchar (NM_DEVICE_IP_TUNNEL_TOS, "", "", + 0, 255, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_PATH_MTU_DISCOVERY, + g_param_spec_boolean (NM_DEVICE_IP_TUNNEL_PATH_MTU_DISCOVERY, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_INPUT_KEY, + g_param_spec_string (NM_DEVICE_IP_TUNNEL_INPUT_KEY, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_OUTPUT_KEY, + g_param_spec_string (NM_DEVICE_IP_TUNNEL_OUTPUT_KEY, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_ENCAPSULATION_LIMIT, + g_param_spec_uchar (NM_DEVICE_IP_TUNNEL_ENCAPSULATION_LIMIT, "", "", + 0, 255, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_FLOW_LABEL, + g_param_spec_uint (NM_DEVICE_IP_TUNNEL_FLOW_LABEL, "", "", + 0, (1 << 20) - 1, 0, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_IPTUNNEL_SKELETON, + NULL); +} +/*************************************************************/ + +#define NM_TYPE_IP_TUNNEL_FACTORY (nm_ip_tunnel_factory_get_type ()) +#define NM_IP_TUNNEL_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_IP_TUNNEL_FACTORY, NMIPTunnelFactory)) + +static NMDevice * +create_device (NMDeviceFactory *factory, + const char *iface, + const NMPlatformLink *plink, + NMConnection *connection, + gboolean *out_ignore) +{ + NMSettingIPTunnel *s_ip_tunnel; + NMIPTunnelMode mode; + NMLinkType link_type; + + if (connection) { + s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection); + mode = nm_setting_ip_tunnel_get_mode (s_ip_tunnel); + link_type = tunnel_mode_to_link_type (mode); + } else { + link_type = plink->type; + mode = platform_link_to_tunnel_mode (plink); + } + + if (mode == NM_IP_TUNNEL_MODE_UKNOWN) + return NULL; + + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_IP_TUNNEL, + NM_DEVICE_IFACE, iface, + NM_DEVICE_TYPE_DESC, "IPTunnel", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_IP_TUNNEL, + NM_DEVICE_LINK_TYPE, link_type, + NM_DEVICE_IP_TUNNEL_MODE, mode, + NULL); +} + +static const char * +get_connection_parent (NMDeviceFactory *factory, NMConnection *connection) +{ + NMSettingIPTunnel *s_ip_tunnel; + + g_return_val_if_fail (nm_connection_is_type (connection, NM_SETTING_IP_TUNNEL_SETTING_NAME), NULL); + + s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection); + g_assert (s_ip_tunnel); + + return nm_setting_ip_tunnel_get_parent (s_ip_tunnel); +} + +static char * +get_virtual_iface_name (NMDeviceFactory *factory, + NMConnection *connection, + const char *parent_iface) +{ + const char *ifname; + NMSettingIPTunnel *s_ip_tunnel; + + g_return_val_if_fail (nm_connection_is_type (connection, NM_SETTING_IP_TUNNEL_SETTING_NAME), NULL); + + s_ip_tunnel = nm_connection_get_setting_ip_tunnel (connection); + g_assert (s_ip_tunnel); + + if (nm_setting_ip_tunnel_get_parent (s_ip_tunnel) && !parent_iface) + return NULL; + + ifname = nm_connection_get_interface_name (connection); + + return g_strdup (ifname); +} + +NM_DEVICE_FACTORY_DEFINE_INTERNAL (IP_TUNNEL, IPTunnel, ip_tunnel, + NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_GRE, NM_LINK_TYPE_SIT, NM_LINK_TYPE_IPIP) + NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_IP_TUNNEL_SETTING_NAME), + factory_iface->create_device = create_device; + factory_iface->get_connection_parent = get_connection_parent; + factory_iface->get_virtual_iface_name = get_virtual_iface_name; +) diff --git a/src/devices/nm-device-ip-tunnel.h b/src/devices/nm-device-ip-tunnel.h new file mode 100644 index 00000000..11cb5bce --- /dev/null +++ b/src/devices/nm-device-ip-tunnel.h @@ -0,0 +1,60 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2015 Red Hat, Inc. + */ + +#ifndef __NETWORKMANAGER_DEVICE_IP_TUNNEL_H__ +#define __NETWORKMANAGER_DEVICE_IP_TUNNEL_H__ + +#include "nm-core-types.h" +#include "nm-device.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_IP_TUNNEL (nm_device_ip_tunnel_get_type ()) +#define NM_DEVICE_IP_TUNNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_IP_TUNNEL, NMDeviceIPTunnel)) +#define NM_DEVICE_IP_TUNNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_IP_TUNNEL, NMDeviceIPTunnelClass)) +#define NM_IS_DEVICE_IP_TUNNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_IP_TUNNEL)) +#define NM_IS_DEVICE_IP_TUNNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_IP_TUNNEL)) +#define NM_DEVICE_IP_TUNNEL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_IP_TUNNEL, NMDeviceIPTunnelClass)) + +#define NM_DEVICE_IP_TUNNEL_MODE "mode" +#define NM_DEVICE_IP_TUNNEL_PARENT "parent" +#define NM_DEVICE_IP_TUNNEL_LOCAL "local" +#define NM_DEVICE_IP_TUNNEL_REMOTE "remote" +#define NM_DEVICE_IP_TUNNEL_TTL "ttl" +#define NM_DEVICE_IP_TUNNEL_TOS "tos" +#define NM_DEVICE_IP_TUNNEL_PATH_MTU_DISCOVERY "path-mtu-discovery" +#define NM_DEVICE_IP_TUNNEL_INPUT_KEY "input-key" +#define NM_DEVICE_IP_TUNNEL_OUTPUT_KEY "output-key" +#define NM_DEVICE_IP_TUNNEL_ENCAPSULATION_LIMIT "encapsulation-limit" +#define NM_DEVICE_IP_TUNNEL_FLOW_LABEL "flow-label" + +typedef struct { + NMDevice parent; +} NMDeviceIPTunnel; + +typedef struct { + NMDeviceClass parent; +} NMDeviceIPTunnelClass; + +GType nm_device_ip_tunnel_get_type (void); + +G_END_DECLS + +#endif /* NM_DEVICE_IP_TUNNEL_H */ diff --git a/src/devices/nm-device-logging.h b/src/devices/nm-device-logging.h index f3b76ee8..6255d6f3 100644 --- a/src/devices/nm-device-logging.h +++ b/src/devices/nm-device-logging.h @@ -21,7 +21,7 @@ #ifndef __NETWORKMANAGER_DEVICE_LOGGING_H__ #define __NETWORKMANAGER_DEVICE_LOGGING_H__ -#include "nm-logging.h" +#include "nm-default.h" #include "nm-device.h" #define _LOG_DECLARE_SELF(t) \ diff --git a/src/devices/nm-device-macvlan.c b/src/devices/nm-device-macvlan.c index 2a815cfd..8123a793 100644 --- a/src/devices/nm-device-macvlan.c +++ b/src/devices/nm-device-macvlan.c @@ -15,32 +15,41 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2013 Red Hat, Inc. + * Copyright 2013 - 2015 Red Hat, Inc. */ #include "config.h" #include <string.h> +#include "nm-default.h" #include "nm-device-macvlan.h" #include "nm-device-private.h" -#include "nm-dbus-manager.h" -#include "nm-logging.h" +#include "nm-connection-provider.h" +#include "nm-activation-request.h" #include "nm-manager.h" #include "nm-platform.h" #include "nm-device-factory.h" +#include "nm-setting-macvlan.h" +#include "nm-setting-wired.h" +#include "nm-active-connection.h" +#include "nm-ip4-config.h" +#include "nm-utils.h" -#include "nm-device-macvlan-glue.h" +#include "nmdbus-device-macvlan.h" #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceMacvlan); -G_DEFINE_TYPE (NMDeviceMacvlan, nm_device_macvlan, NM_TYPE_DEVICE_GENERIC) +G_DEFINE_TYPE (NMDeviceMacvlan, nm_device_macvlan, NM_TYPE_DEVICE) #define NM_DEVICE_MACVLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_MACVLAN, NMDeviceMacvlanPrivate)) typedef struct { - NMPlatformMacvlanProperties props; + int parent_ifindex; + gulong parent_state_id; + NMDevice *parent; + NMPlatformLnkMacvlan props; } NMDeviceMacvlanPrivate; enum { @@ -48,37 +57,147 @@ enum { PROP_PARENT, PROP_MODE, PROP_NO_PROMISC, + PROP_TAP, LAST_PROP }; -/**************************************************************/ +static int modes[][2] = { + { NM_SETTING_MACVLAN_MODE_VEPA, MACVLAN_MODE_VEPA }, + { NM_SETTING_MACVLAN_MODE_BRIDGE, MACVLAN_MODE_BRIDGE }, + { NM_SETTING_MACVLAN_MODE_PRIVATE, MACVLAN_MODE_PRIVATE }, + { NM_SETTING_MACVLAN_MODE_PASSTHRU, MACVLAN_MODE_PASSTHRU }, +}; + +static int +setting_mode_to_platform (int mode) +{ + guint i; + + for (i = 0; i < G_N_ELEMENTS (modes); i++) { + if (modes[i][0] == mode) + return modes[i][1]; + } + + return 0; +} + +static int +platform_mode_to_setting (int mode) +{ + guint i; + + for (i = 0; i < G_N_ELEMENTS (modes); i++) { + if (modes[i][1] == mode) + return modes[i][0]; + } + + return 0; +} + +static const char * +platform_mode_to_string (guint mode) +{ + switch (mode) { + case MACVLAN_MODE_PRIVATE: + return "private"; + case MACVLAN_MODE_VEPA: + return "vepa"; + case MACVLAN_MODE_BRIDGE: + return "bridge"; + case MACVLAN_MODE_PASSTHRU: + return "passthru"; + default: + return "unknown"; + } +} /**************************************************************/ static void +parent_state_changed (NMDevice *parent, + NMDeviceState new_state, + NMDeviceState old_state, + NMDeviceStateReason reason, + gpointer user_data) +{ + NMDeviceMacvlan *self = NM_DEVICE_MACVLAN (user_data); + + /* We'll react to our own carrier state notifications. Ignore the parent's. */ + if (reason == NM_DEVICE_STATE_REASON_CARRIER) + return; + + nm_device_set_unmanaged_flags (NM_DEVICE (self), NM_UNMANAGED_PARENT, !nm_device_get_managed (parent), reason); +} + +static void +nm_device_macvlan_set_parent (NMDeviceMacvlan *self, NMDevice *parent) + { + NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE (self); + NMDevice *device = NM_DEVICE (self); + + if (parent == priv->parent) + return; + + if (priv->parent_state_id) + nm_clear_g_signal_handler (priv->parent, &priv->parent_state_id); + + g_clear_object (&priv->parent); + + if (parent) { + priv->parent = g_object_ref (parent); + priv->parent_state_id = g_signal_connect (priv->parent, + "state-changed", + G_CALLBACK (parent_state_changed), + device); + + /* Set parent-dependent unmanaged flag */ + nm_device_set_unmanaged_flags (device, + NM_UNMANAGED_PARENT, + !nm_device_get_managed (parent), + NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED); + } + + /* Recheck availability now that the parent has changed */ + nm_device_queue_recheck_available (self, + NM_DEVICE_STATE_REASON_PARENT_CHANGED, + NM_DEVICE_STATE_REASON_PARENT_CHANGED); + g_object_notify (G_OBJECT (device), NM_DEVICE_MACVLAN_PARENT); +} + +static void update_properties (NMDevice *device) { NMDeviceMacvlan *self = NM_DEVICE_MACVLAN (device); NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE (device); GObject *object = G_OBJECT (device); - NMPlatformMacvlanProperties props; + const NMPlatformLnkMacvlan *props; + const NMPlatformLink *plink; + NMDevice *parent = NULL; - if (!nm_platform_macvlan_get_properties (NM_PLATFORM_GET, nm_device_get_ifindex (device), &props)) { - _LOGW (LOGD_HW, "could not read macvlan properties"); + if (priv->props.tap) + props = nm_platform_link_get_lnk_macvtap (NM_PLATFORM_GET, nm_device_get_ifindex (device), &plink); + else + props = nm_platform_link_get_lnk_macvlan (NM_PLATFORM_GET, nm_device_get_ifindex (device), &plink); + + if (!props) { + _LOGW (LOGD_HW, "could not get %s properties", priv->props.tap ? "macvtap" : "macvlan"); return; } g_object_freeze_notify (object); - if (priv->props.parent_ifindex != props.parent_ifindex) - g_object_notify (object, NM_DEVICE_MACVLAN_PARENT); - if (g_strcmp0 (priv->props.mode, props.mode) != 0) + if (priv->parent_ifindex != plink->parent) { + parent = nm_manager_get_device_by_ifindex (nm_manager_get (), plink->parent); + nm_device_macvlan_set_parent (self, parent); + } + if (priv->props.mode != props->mode) g_object_notify (object, NM_DEVICE_MACVLAN_MODE); - if (priv->props.no_promisc != props.no_promisc) + if (priv->props.no_promisc != props->no_promisc) g_object_notify (object, NM_DEVICE_MACVLAN_NO_PROMISC); - memcpy (&priv->props, &props, sizeof (NMPlatformMacvlanProperties)); + priv->parent_ifindex = plink->parent; + priv->props = *props; g_object_thaw_notify (object); } @@ -90,19 +209,370 @@ link_changed (NMDevice *device, NMPlatformLink *info) update_properties (device); } +static gboolean +create_and_realize (NMDevice *device, + NMConnection *connection, + NMDevice *parent, + const NMPlatformLink **out_plink, + GError **error) +{ + const char *iface = nm_device_get_iface (device); + NMPlatformError plerr; + NMSettingMacvlan *s_macvlan; + NMPlatformLnkMacvlan lnk = { }; + int parent_ifindex; + + s_macvlan = nm_connection_get_setting_macvlan (connection); + g_assert (s_macvlan); + + parent_ifindex = nm_device_get_ifindex (parent); + g_warn_if_fail (parent_ifindex > 0); + + lnk.mode = setting_mode_to_platform (nm_setting_macvlan_get_mode (s_macvlan)); + if (!lnk.mode) { + nm_log_info (LOGD_DEVICE, "unsupported MACVLAN mode %u in connection %s", + nm_setting_macvlan_get_mode (s_macvlan), + nm_connection_get_uuid (connection)); + return FALSE; + } + lnk.no_promisc = !nm_setting_macvlan_get_promiscuous (s_macvlan); + lnk.tap = nm_setting_macvlan_get_tap (s_macvlan); + + plerr = nm_platform_link_macvlan_add (NM_PLATFORM_GET, iface, parent_ifindex, &lnk, out_plink); + if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, + "Failed to create %s interface '%s' for '%s': %s", + lnk.tap ? "macvtap" : "macvlan", + iface, + nm_connection_get_id (connection), + nm_platform_error_to_string (plerr)); + return FALSE; + } + + return TRUE; +} + +/******************************************************************/ + +static NMDeviceCapabilities +get_generic_capabilities (NMDevice *dev) +{ + /* We assume MACVLAN interfaces always support carrier detect */ + return NM_DEVICE_CAP_CARRIER_DETECT | NM_DEVICE_CAP_IS_SOFTWARE; +} + +static gboolean +bring_up (NMDevice *dev, gboolean *no_firmware) +{ + gboolean success = FALSE; + guint i = 20; + + while (i-- > 0 && !success) { + success = NM_DEVICE_CLASS (nm_device_macvlan_parent_class)->bring_up (dev, no_firmware); + g_usleep (50); + } + + return success; +} + +/******************************************************************/ + +static gboolean +is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags) +{ + if (!NM_DEVICE_MACVLAN_GET_PRIVATE (device)->parent) + return FALSE; + + return NM_DEVICE_CLASS (nm_device_macvlan_parent_class)->is_available (device, flags); +} + +static void +notify_new_device_added (NMDevice *device, NMDevice *new_device) +{ + NMDeviceMacvlan *self = NM_DEVICE_MACVLAN (device); + NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE (self); + + if (priv->parent) + return; + + if (!nm_device_is_real (device)) + return; + + update_properties (device); + + if ( priv->parent_ifindex <= 0 + || nm_device_get_ifindex (new_device) != priv->parent_ifindex) + return; + + priv->parent_ifindex = nm_device_get_ifindex (new_device); + nm_device_macvlan_set_parent (self, new_device); +} + /**************************************************************/ + +static gboolean +match_parent (NMDeviceMacvlan *self, const char *parent) +{ + NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE (self); + + g_return_val_if_fail (parent != NULL, FALSE); + + if (!priv->parent) + return FALSE; + + if (nm_utils_is_uuid (parent)) { + NMActRequest *parent_req; + NMConnection *parent_connection; + + /* If the parent is a UUID, the connection matches if our parent + * device has that connection activated. + */ + + parent_req = nm_device_get_act_request (priv->parent); + if (!parent_req) + return FALSE; + + parent_connection = nm_active_connection_get_applied_connection (NM_ACTIVE_CONNECTION (parent_req)); + if (!parent_connection) + return FALSE; + + if (g_strcmp0 (parent, nm_connection_get_uuid (parent_connection)) != 0) + return FALSE; + } else { + /* interface name */ + if (g_strcmp0 (parent, nm_device_get_ip_iface (priv->parent)) != 0) + return FALSE; + } + + return TRUE; +} + +static gboolean +match_hwaddr (NMDevice *device, NMConnection *connection, gboolean fail_if_no_hwaddr) +{ + NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE (device); + NMSettingWired *s_wired; + const char *setting_mac; + const char *parent_mac; + + s_wired = nm_connection_get_setting_wired (connection); + if (!s_wired) + return !fail_if_no_hwaddr; + + setting_mac = nm_setting_wired_get_mac_address (s_wired); + if (!setting_mac) + return !fail_if_no_hwaddr; + + if (!priv->parent) + return !fail_if_no_hwaddr; + + parent_mac = nm_device_get_hw_address (priv->parent); + + return nm_utils_hwaddr_matches (setting_mac, -1, parent_mac, -1); +} + +static gboolean +check_connection_compatible (NMDevice *device, NMConnection *connection) +{ + NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE (device); + NMSettingMacvlan *s_macvlan; + const char *parent, *iface = NULL; + + if (!NM_DEVICE_CLASS (nm_device_macvlan_parent_class)->check_connection_compatible (device, connection)) + return FALSE; + + s_macvlan = nm_connection_get_setting_macvlan (connection); + if (!s_macvlan) + return FALSE; + + if (nm_setting_macvlan_get_tap (s_macvlan) != priv->props.tap) + return FALSE; + + /* Before the device is realized some properties will not be set */ + if (nm_device_is_real (device)) { + + if (setting_mode_to_platform (nm_setting_macvlan_get_mode (s_macvlan)) != priv->props.mode) + return FALSE; + + if (nm_setting_macvlan_get_promiscuous (s_macvlan) == priv->props.no_promisc) + return FALSE; + + /* Check parent interface; could be an interface name or a UUID */ + parent = nm_setting_macvlan_get_parent (s_macvlan); + if (parent) { + if (!match_parent (NM_DEVICE_MACVLAN (device), parent)) + return FALSE; + } else { + /* Parent could be a MAC address in an NMSettingWired */ + if (!match_hwaddr (device, connection, TRUE)) + return FALSE; + } + } + + /* Ensure the interface name matches */ + iface = nm_connection_get_interface_name (connection); + if (iface) { + if (g_strcmp0 (nm_device_get_ip_iface (device), iface) != 0) + return FALSE; + } + + return TRUE; +} + +static gboolean +complete_connection (NMDevice *device, + NMConnection *connection, + const char *specific_object, + const GSList *existing_connections, + GError **error) +{ + NMSettingMacvlan *s_macvlan; + + nm_utils_complete_generic (connection, + NM_SETTING_MACVLAN_SETTING_NAME, + existing_connections, + NULL, + _("MACVLAN connection"), + NULL, + TRUE); + + s_macvlan = nm_connection_get_setting_macvlan (connection); + if (!s_macvlan) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, + "A 'macvlan' setting is required."); + return FALSE; + } + + /* If there's no MACVLAN interface, no parent, and no hardware address in the + * settings, then there's not enough information to complete the setting. + */ + if ( !nm_setting_macvlan_get_parent (s_macvlan) + && !match_hwaddr (device, connection, TRUE)) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, + "The 'macvlan' setting had no interface name, parent, or hardware address."); + return FALSE; + } + + return TRUE; +} + static void -nm_device_macvlan_init (NMDeviceMacvlan *self) +update_connection (NMDevice *device, NMConnection *connection) +{ + NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE (device); + NMSettingMacvlan *s_macvlan = nm_connection_get_setting_macvlan (connection); + const char *setting_parent, *new_parent; + int new_mode; + + if (!s_macvlan) { + s_macvlan = (NMSettingMacvlan *) nm_setting_macvlan_new (); + nm_connection_add_setting (connection, (NMSetting *) s_macvlan); + } + + new_mode = platform_mode_to_setting (priv->props.mode); + if (new_mode != nm_setting_macvlan_get_mode (s_macvlan)) + g_object_set (s_macvlan, NM_SETTING_MACVLAN_MODE, new_mode, NULL); + + if (priv->props.no_promisc == nm_setting_macvlan_get_promiscuous (s_macvlan)) + g_object_set (s_macvlan, NM_SETTING_MACVLAN_PROMISCUOUS, !priv->props.no_promisc, NULL); + + + if (priv->props.tap != nm_setting_macvlan_get_tap (s_macvlan)) + g_object_set (s_macvlan, NM_SETTING_MACVLAN_TAP, !!priv->props.tap, NULL); + + /* Update parent in the connection; default to parent's interface name */ + if (priv->parent) { + new_parent = nm_device_get_iface (priv->parent); + setting_parent = nm_setting_macvlan_get_parent (s_macvlan); + if (setting_parent && nm_utils_is_uuid (setting_parent)) { + NMConnection *parent_connection; + + /* Don't change a parent specified by UUID if it's still valid */ + parent_connection = nm_connection_provider_get_connection_by_uuid (nm_connection_provider_get (), setting_parent); + if (parent_connection && nm_device_check_connection_compatible (priv->parent, parent_connection)) + new_parent = NULL; + } + if (new_parent) + g_object_set (s_macvlan, NM_SETTING_MACVLAN_PARENT, new_parent, NULL); + } else + g_object_set (s_macvlan, NM_SETTING_MACVLAN_PARENT, NULL, NULL); + +} + +static NMActStageReturn +act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) { + NMActRequest *req; + NMConnection *connection; + NMSettingWired *s_wired; + const char *cloned_mac; + NMActStageReturn ret; + + g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + ret = NM_DEVICE_CLASS (nm_device_macvlan_parent_class)->act_stage1_prepare (dev, reason); + if (ret != NM_ACT_STAGE_RETURN_SUCCESS) + return ret; + + req = nm_device_get_act_request (dev); + g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + connection = nm_act_request_get_applied_connection (req); + g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + s_wired = nm_connection_get_setting_wired (connection); + if (s_wired) { + /* Set device MAC address if the connection wants to change it */ + cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); + if (cloned_mac) + nm_device_set_hw_addr (dev, cloned_mac, "set", LOGD_HW); + } + + return TRUE; +} + +static void +ip4_config_pre_commit (NMDevice *device, NMIP4Config *config) +{ + NMConnection *connection; + NMSettingWired *s_wired; + guint32 mtu; + + connection = nm_device_get_applied_connection (device); + g_assert (connection); + + s_wired = nm_connection_get_setting_wired (connection); + if (s_wired) { + mtu = nm_setting_wired_get_mtu (s_wired); + if (mtu) + nm_ip4_config_set_mtu (config, mtu, NM_IP_CONFIG_SOURCE_USER); + } +} + +static void +realize_start_notify (NMDevice *device, const NMPlatformLink *plink) +{ + NM_DEVICE_CLASS (nm_device_macvlan_parent_class)->realize_start_notify (device, plink); + + update_properties (device); } static void -constructed (GObject *object) +deactivate (NMDevice *device) { - update_properties (NM_DEVICE (object)); + /* Reset MAC address back to initial address */ + if (nm_device_get_initial_hw_address (device)) { + nm_device_set_hw_addr (device, nm_device_get_initial_hw_address (device), + "reset", LOGD_DEVICE); + } +} - G_OBJECT_CLASS (nm_device_macvlan_parent_class)->constructed (object); +/******************************************************************/ + +static void +nm_device_macvlan_init (NMDeviceMacvlan *self) +{ } static void @@ -114,18 +584,21 @@ get_property (GObject *object, guint prop_id, switch (prop_id) { case PROP_PARENT: - if (priv->props.parent_ifindex > 0) - parent = nm_manager_get_device_by_ifindex (nm_manager_get (), priv->props.parent_ifindex); + if (priv->parent_ifindex > 0) + parent = nm_manager_get_device_by_ifindex (nm_manager_get (), priv->parent_ifindex); else parent = NULL; - g_value_set_boxed (value, parent ? nm_device_get_path (parent) : "/"); + nm_utils_g_value_set_object_path (value, parent); break; case PROP_MODE: - g_value_set_string (value, priv->props.mode); + g_value_set_string (value, platform_mode_to_string (priv->props.mode)); break; case PROP_NO_PROMISC: g_value_set_boolean (value, priv->props.no_promisc); break; + case PROP_TAP: + g_value_set_boolean (value, priv->props.tap); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -133,6 +606,21 @@ get_property (GObject *object, guint prop_id, } static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMDeviceMacvlanPrivate *priv = NM_DEVICE_MACVLAN_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_TAP: + priv->props.tap = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); @@ -140,18 +628,33 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass) g_type_class_add_private (klass, sizeof (NMDeviceMacvlanPrivate)); - object_class->constructed = constructed; - object_class->get_property = get_property; + NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_MACVLAN, NM_LINK_TYPE_MACVTAP) + object_class->get_property = get_property; + object_class->set_property = set_property; + + device_class->act_stage1_prepare = act_stage1_prepare; + device_class->bring_up = bring_up; + device_class->check_connection_compatible = check_connection_compatible; + device_class->complete_connection = complete_connection; + device_class->connection_type = NM_SETTING_MACVLAN_SETTING_NAME; + device_class->create_and_realize = create_and_realize; + device_class->deactivate = deactivate; + device_class->get_generic_capabilities = get_generic_capabilities; + device_class->ip4_config_pre_commit = ip4_config_pre_commit; + device_class->is_available = is_available; device_class->link_changed = link_changed; + device_class->notify_new_device_added = notify_new_device_added; + device_class->realize_start_notify = realize_start_notify; + device_class->update_connection = update_connection; /* properties */ g_object_class_install_property (object_class, PROP_PARENT, - g_param_spec_boxed (NM_DEVICE_MACVLAN_PARENT, "", "", - DBUS_TYPE_G_OBJECT_PATH, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + g_param_spec_string (NM_DEVICE_MACVLAN_PARENT, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_MODE, @@ -167,9 +670,17 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), - G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_macvlan_object_info); + g_object_class_install_property + (object_class, PROP_TAP, + g_param_spec_boolean (NM_DEVICE_MACVLAN_TAP, "", "", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_MACVLAN_SKELETON, + NULL); } /*************************************************************/ @@ -178,17 +689,85 @@ nm_device_macvlan_class_init (NMDeviceMacvlanClass *klass) #define NM_MACVLAN_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_MACVLAN_FACTORY, NMMacvlanFactory)) static NMDevice * -new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error) +create_device (NMDeviceFactory *factory, + const char *iface, + const NMPlatformLink *plink, + NMConnection *connection, + gboolean *out_ignore) { + NMSettingMacvlan *s_macvlan; + NMLinkType link_type; + gboolean tap; + + if (connection) { + s_macvlan = nm_connection_get_setting_macvlan (connection); + g_assert (s_macvlan); + tap = nm_setting_macvlan_get_tap (s_macvlan); + } else { + g_assert (plink); + tap = plink->type == NM_LINK_TYPE_MACVTAP; + } + + link_type = tap ? NM_LINK_TYPE_MACVTAP : NM_LINK_TYPE_MACVLAN; + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_MACVLAN, - NM_DEVICE_PLATFORM_DEVICE, plink, + NM_DEVICE_IFACE, iface, NM_DEVICE_TYPE_DESC, "Macvlan", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_GENERIC, + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_MACVLAN, + NM_DEVICE_LINK_TYPE, link_type, + NM_DEVICE_MACVLAN_TAP, tap, NULL); } +static const char * +get_connection_parent (NMDeviceFactory *factory, NMConnection *connection) +{ + NMSettingMacvlan *s_macvlan; + NMSettingWired *s_wired; + const char *parent = NULL; + + g_return_val_if_fail (nm_connection_is_type (connection, NM_SETTING_MACVLAN_SETTING_NAME), NULL); + + s_macvlan = nm_connection_get_setting_macvlan (connection); + g_assert (s_macvlan); + + parent = nm_setting_macvlan_get_parent (s_macvlan); + if (parent) + return parent; + + /* Try the hardware address from the MACVLAN connection's hardware setting */ + s_wired = nm_connection_get_setting_wired (connection); + if (s_wired) + return nm_setting_wired_get_mac_address (s_wired); + + return NULL; +} + +static char * +get_virtual_iface_name (NMDeviceFactory *factory, + NMConnection *connection, + const char *parent_iface) +{ + NMSettingMacvlan *s_macvlan; + const char *ifname; + + g_return_val_if_fail (nm_connection_is_type (connection, NM_SETTING_MACVLAN_SETTING_NAME), NULL); + + s_macvlan = nm_connection_get_setting_macvlan (connection); + g_assert (s_macvlan); + + if (!parent_iface) + return NULL; + + ifname = nm_connection_get_interface_name (connection); + return g_strdup (ifname); +} + NM_DEVICE_FACTORY_DEFINE_INTERNAL (MACVLAN, Macvlan, macvlan, - NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_MACVLAN, NM_LINK_TYPE_MACVTAP), - factory_iface->new_link = new_link; + NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_MACVLAN, NM_LINK_TYPE_MACVTAP) + NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_MACVLAN_SETTING_NAME), + factory_iface->create_device = create_device; + factory_iface->get_connection_parent = get_connection_parent; + factory_iface->get_virtual_iface_name = get_virtual_iface_name; ) diff --git a/src/devices/nm-device-macvlan.h b/src/devices/nm-device-macvlan.h index 24f15437..89f670bd 100644 --- a/src/devices/nm-device-macvlan.h +++ b/src/devices/nm-device-macvlan.h @@ -21,9 +21,7 @@ #ifndef __NETWORKMANAGER_DEVICE_MACVLAN_H__ #define __NETWORKMANAGER_DEVICE_MACVLAN_H__ -#include <glib-object.h> - -#include "nm-device-generic.h" +#include "nm-device.h" G_BEGIN_DECLS @@ -37,9 +35,10 @@ G_BEGIN_DECLS #define NM_DEVICE_MACVLAN_PARENT "parent" #define NM_DEVICE_MACVLAN_MODE "mode" #define NM_DEVICE_MACVLAN_NO_PROMISC "no-promisc" +#define NM_DEVICE_MACVLAN_TAP "tap" -typedef NMDeviceGeneric NMDeviceMacvlan; -typedef NMDeviceGenericClass NMDeviceMacvlanClass; +typedef NMDevice NMDeviceMacvlan; +typedef NMDeviceClass NMDeviceMacvlanClass; GType nm_device_macvlan_get_type (void); diff --git a/src/devices/nm-device-private.h b/src/devices/nm-device-private.h index f34969ac..5010e906 100644 --- a/src/devices/nm-device-private.h +++ b/src/devices/nm-device-private.h @@ -24,9 +24,9 @@ #include "nm-device.h" -/* This file should only be used by subclasses of NMDevice */ +#include "nm-default.h" -#define NM_DEVICE_PLATFORM_DEVICE "platform-device" +/* This file should only be used by subclasses of NMDevice */ enum NMActStageReturn { NM_ACT_STAGE_RETURN_FAILURE = 0, @@ -91,7 +91,7 @@ gboolean nm_device_get_enslaved (NMDevice *device); NMDevice *nm_device_master_get_slave_by_ifindex (NMDevice *dev, int ifindex); void nm_device_master_check_slave_physical_port (NMDevice *self, NMDevice *slave, - guint64 log_domain); + NMLogDomain log_domain); void nm_device_set_carrier (NMDevice *self, gboolean carrier); @@ -106,4 +106,11 @@ void nm_device_set_wwan_ip6_config (NMDevice *device, NMIP6Config *config); gboolean nm_device_ipv6_sysctl_set (NMDevice *self, const char *property, const char *value); +#define NM_DEVICE_CLASS_DECLARE_TYPES(klass, conn_type, ...) \ + NM_DEVICE_CLASS (klass)->connection_type = conn_type; \ + { \ + static const NMLinkType link_types[] = { __VA_ARGS__, NM_LINK_TYPE_NONE }; \ + NM_DEVICE_CLASS (klass)->link_types = link_types; \ + } + #endif /* NM_DEVICE_PRIVATE_H */ diff --git a/src/devices/nm-device-tun.c b/src/devices/nm-device-tun.c index 5aaff8b1..91ef8fe7 100644 --- a/src/devices/nm-device-tun.c +++ b/src/devices/nm-device-tun.c @@ -15,41 +15,43 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2013 Red Hat, Inc. + * Copyright 2013 - 2015 Red Hat, Inc. */ #include "config.h" #include <stdlib.h> #include <string.h> +#include <sys/types.h> +#include "nm-default.h" +#include "nm-activation-request.h" #include "nm-device-tun.h" #include "nm-device-private.h" -#include "nm-dbus-manager.h" -#include "nm-logging.h" +#include "nm-ip4-config.h" #include "nm-platform.h" #include "nm-device-factory.h" +#include "nm-setting-tun.h" +#include "nm-core-internal.h" -#include "nm-device-tun-glue.h" +#include "nmdbus-device-tun.h" #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceTun); -G_DEFINE_TYPE (NMDeviceTun, nm_device_tun, NM_TYPE_DEVICE_GENERIC) +G_DEFINE_TYPE (NMDeviceTun, nm_device_tun, NM_TYPE_DEVICE) #define NM_DEVICE_TUN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_TUN, NMDeviceTunPrivate)) typedef struct { NMPlatformTunProperties props; const char *mode; - guint delay_tun_get_properties_id; } NMDeviceTunPrivate; enum { PROP_0, PROP_OWNER, PROP_GROUP, - PROP_FLAGS, PROP_MODE, PROP_NO_PI, PROP_VNET_HDR, @@ -64,11 +66,26 @@ reload_tun_properties (NMDeviceTun *self) NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); GObject *object = G_OBJECT (self); NMPlatformTunProperties props; - - if (!nm_platform_tun_get_properties (NM_PLATFORM_GET, nm_device_get_ifindex (NM_DEVICE (self)), &props)) { - _LOGD (LOGD_HW, "could not read tun properties"); - return; - } + int ifindex; + + ifindex = nm_device_get_ifindex (NM_DEVICE (self)); + if (ifindex > 0) { + if (!nm_platform_link_tun_get_properties (NM_PLATFORM_GET, ifindex, &props)) { + _LOGD (LOGD_DEVICE, "tun-properties: cannot loading tun properties from platform for ifindex %d", ifindex); + ifindex = 0; + } else if (g_strcmp0 (priv->mode, props.mode) != 0) { + /* if the mode differs, we ignore what we loaded. A NMDeviceTun cannot + * change the mode after construction. */ + _LOGD (LOGD_DEVICE, "tun-properties: loading tun properties yielded tun-mode %s%s%s, but %s%s%s expected (ifindex %d)", + NM_PRINT_FMT_QUOTE_STRING (props.mode), + NM_PRINT_FMT_QUOTE_STRING (priv->mode), + ifindex); + ifindex = 0; + } + } else + _LOGD (LOGD_DEVICE, "tun-properties: ignore loading properties due to missing ifindex"); + if (ifindex <= 0) + memset (&props, 0, sizeof (props)); g_object_freeze_notify (object); @@ -97,54 +114,251 @@ link_changed (NMDevice *device, NMPlatformLink *info) } static gboolean -delay_tun_get_properties_cb (gpointer user_data) +complete_connection (NMDevice *device, + NMConnection *connection, + const char *specific_object, + const GSList *existing_connections, + GError **error) { - NMDeviceTun *self = user_data; - NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); + NMSettingTun *s_tun; + + nm_utils_complete_generic (connection, + NM_SETTING_TUN_SETTING_NAME, + existing_connections, + NULL, + _("TUN connection"), + NULL, + TRUE); + + s_tun = nm_connection_get_setting_tun (connection); + if (!s_tun) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, + "A 'tun' setting is required."); + return FALSE; + } - priv->delay_tun_get_properties_id = 0; + return TRUE; +} - reload_tun_properties (self); +static int +tun_mode_from_string (const char *string) +{ + if (!g_strcmp0 (string, "tap")) + return NM_SETTING_TUN_MODE_TAP; + else + return NM_SETTING_TUN_MODE_TUN; +} - return G_SOURCE_REMOVE; +static void +update_connection (NMDevice *device, NMConnection *connection) +{ + NMDeviceTun *self = NM_DEVICE_TUN (device); + NMSettingTun *s_tun = nm_connection_get_setting_tun (connection); + NMPlatformTunProperties props; + NMSettingTunMode mode; + gint64 user, group; + char *str; + + if (!s_tun) { + s_tun = (NMSettingTun *) nm_setting_tun_new (); + nm_connection_add_setting (connection, (NMSetting *) s_tun); + } + + if (!nm_platform_link_tun_get_properties (NM_PLATFORM_GET, nm_device_get_ifindex (device), &props)) { + _LOGW (LOGD_HW, "failed to get TUN interface info while updating connection."); + return; + } + + mode = tun_mode_from_string (props.mode); + + if (mode != nm_setting_tun_get_mode (s_tun)) + g_object_set (G_OBJECT (s_tun), NM_SETTING_TUN_MODE, mode, NULL); + + user = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_owner (s_tun), 10, 0, G_MAXINT32, -1); + group = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_group (s_tun), 10, 0, G_MAXINT32, -1); + + if (props.owner != user) { + str = props.owner >= 0 ? g_strdup_printf ("%" G_GINT32_FORMAT, (gint32) props.owner) : NULL; + g_object_set (G_OBJECT (s_tun), NM_SETTING_TUN_OWNER, str, NULL); + g_free (str); + } + + if (props.group != group) { + str = props.group >= 0 ? g_strdup_printf ("%" G_GINT32_FORMAT, (gint32) props.group) : NULL; + g_object_set (G_OBJECT (s_tun), NM_SETTING_TUN_GROUP, str, NULL); + g_free (str); + } + + if ((!props.no_pi) != nm_setting_tun_get_pi (s_tun)) + g_object_set (G_OBJECT (s_tun), NM_SETTING_TUN_PI, !props.no_pi, NULL); + if (props.vnet_hdr != nm_setting_tun_get_vnet_hdr (s_tun)) + g_object_set (G_OBJECT (s_tun), NM_SETTING_TUN_VNET_HDR, props.vnet_hdr, NULL); + if (props.multi_queue != nm_setting_tun_get_multi_queue (s_tun)) + g_object_set (G_OBJECT (s_tun), NM_SETTING_TUN_MULTI_QUEUE, props.multi_queue, NULL); } -/**************************************************************/ +static gboolean +create_and_realize (NMDevice *device, + NMConnection *connection, + NMDevice *parent, + const NMPlatformLink **out_plink, + GError **error) +{ + const char *iface = nm_device_get_iface (device); + NMPlatformError plerr; + NMSettingTun *s_tun; + gint64 user, group; + + s_tun = nm_connection_get_setting_tun (connection); + g_assert (s_tun); + + user = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_owner (s_tun), 10, 0, G_MAXINT32, -1); + group = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_group (s_tun), 10, 0, G_MAXINT32, -1); + + plerr = nm_platform_link_tun_add (NM_PLATFORM_GET, iface, + nm_setting_tun_get_mode (s_tun) == NM_SETTING_TUN_MODE_TAP, + user, group, + nm_setting_tun_get_pi (s_tun), + nm_setting_tun_get_vnet_hdr (s_tun), + nm_setting_tun_get_multi_queue (s_tun), + out_plink); + if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, + "Failed to create TUN/TAP interface '%s' for '%s': %s", + iface, + nm_connection_get_id (connection), + nm_platform_error_to_string (plerr)); + return FALSE; + } + + return TRUE; +} static void -nm_device_tun_init (NMDeviceTun *self) +realize_start_notify (NMDevice *device, const NMPlatformLink *plink) { + NM_DEVICE_CLASS (nm_device_tun_parent_class)->realize_start_notify (device, plink); + reload_tun_properties (device); } -static void -constructed (GObject *object) +static gboolean +check_connection_compatible (NMDevice *device, NMConnection *connection) { - NMDeviceTun *self = NM_DEVICE_TUN (object); - gboolean properties_read; + NMDeviceTun *self = NM_DEVICE_TUN (device); NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); + NMSettingTunMode mode; + NMSettingTun *s_tun; + gint64 user, group; + + if (!NM_DEVICE_CLASS (nm_device_tun_parent_class)->check_connection_compatible (device, connection)) + return FALSE; + + s_tun = nm_connection_get_setting_tun (connection); + if (!s_tun) + return FALSE; + + if (nm_device_is_real (device)) { + mode = tun_mode_from_string (priv->mode); + if (mode != nm_setting_tun_get_mode (s_tun)) + return FALSE; + + user = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_owner (s_tun), 10, 0, G_MAXINT32, -1); + group = _nm_utils_ascii_str_to_int64 (nm_setting_tun_get_group (s_tun), 10, 0, G_MAXINT32, -1); + + if (user != priv->props.owner) + return FALSE; + if (group != priv->props.group) + return FALSE; + if (nm_setting_tun_get_pi (s_tun) == priv->props.no_pi) + return FALSE; + if (nm_setting_tun_get_vnet_hdr (s_tun) != priv->props.vnet_hdr) + return FALSE; + if (nm_setting_tun_get_multi_queue (s_tun) != priv->props.multi_queue) + return FALSE; + } - properties_read = nm_platform_tun_get_properties (NM_PLATFORM_GET, nm_device_get_ifindex (NM_DEVICE (self)), &priv->props); + return TRUE; +} - G_OBJECT_CLASS (nm_device_tun_parent_class)->constructed (object); +static NMActStageReturn +act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) +{ + NMDeviceTun *self = NM_DEVICE_TUN (device); + NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); + NMActRequest *req; + NMConnection *connection; + NMSettingWired *s_wired; + const char *cloned_mac; + NMActStageReturn ret; + + g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + ret = NM_DEVICE_CLASS (nm_device_tun_parent_class)->act_stage1_prepare (device, reason); + if (ret != NM_ACT_STAGE_RETURN_SUCCESS) + return ret; + + /* Nothing to do for TUN devices */ + if (g_strcmp0 (priv->mode, "tap")) + return NM_ACT_STAGE_RETURN_SUCCESS; + + req = nm_device_get_act_request (device); + g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + connection = nm_act_request_get_applied_connection (req); + g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + s_wired = nm_connection_get_setting_wired (connection); + if (s_wired) { + /* Set device MAC address if the connection wants to change it */ + cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); + if (cloned_mac) + nm_device_set_hw_addr (device, cloned_mac, "set", LOGD_DEVICE); + } + + return NM_ACT_STAGE_RETURN_SUCCESS; +} - if (!properties_read) { - /* Error reading the tun properties. Maybe this was due to a race. Try again a bit later. */ - _LOGD (LOGD_HW, "could not read tun properties (retry)"); - priv->delay_tun_get_properties_id = g_timeout_add_seconds (1, delay_tun_get_properties_cb, self); +static void +ip4_config_pre_commit (NMDevice *device, NMIP4Config *config) +{ + NMConnection *connection; + NMSettingWired *s_wired; + guint32 mtu; + + connection = nm_device_get_applied_connection (device); + g_assert (connection); + + s_wired = nm_connection_get_setting_wired (connection); + if (s_wired) { + mtu = nm_setting_wired_get_mtu (s_wired); + if (mtu) + nm_ip4_config_set_mtu (config, mtu, NM_IP_CONFIG_SOURCE_USER); } } static void -dispose (GObject *object) +unrealize_notify (NMDevice *device) { - NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (object); + NMDeviceTun *self = NM_DEVICE_TUN (device); + NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (self); + GParamSpec **properties; + guint n_properties, i; - if (priv->delay_tun_get_properties_id) { - g_source_remove (priv->delay_tun_get_properties_id); - priv->delay_tun_get_properties_id = 0; - } + NM_DEVICE_CLASS (nm_device_tun_parent_class)->unrealize_notify (device); + + memset (&priv->props, 0, sizeof (NMPlatformTunProperties)); + + properties = g_object_class_list_properties (G_OBJECT_GET_CLASS (self), &n_properties); + for (i = 0; i < n_properties; i++) + g_object_notify_by_pspec (G_OBJECT (self), properties[i]); + g_free (properties); +} - G_OBJECT_CLASS (nm_device_tun_parent_class)->dispose (object); +/**************************************************************/ + +static void +nm_device_tun_init (NMDeviceTun *self) +{ } static void @@ -214,12 +428,22 @@ nm_device_tun_class_init (NMDeviceTunClass *klass) g_type_class_add_private (klass, sizeof (NMDeviceTunPrivate)); - object_class->constructed = constructed; + NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_TUN, NM_LINK_TYPE_TAP) + object_class->get_property = get_property; object_class->set_property = set_property; - object_class->dispose = dispose; + + device_class->connection_type = NM_SETTING_TUN_SETTING_NAME; device_class->link_changed = link_changed; + device_class->complete_connection = complete_connection; + device_class->check_connection_compatible = check_connection_compatible; + device_class->create_and_realize = create_and_realize; + device_class->realize_start_notify = realize_start_notify; + device_class->unrealize_notify = unrealize_notify; + device_class->update_connection = update_connection; + device_class->act_stage1_prepare = act_stage1_prepare; + device_class->ip4_config_pre_commit = ip4_config_pre_commit; /* properties */ g_object_class_install_property @@ -258,9 +482,9 @@ nm_device_tun_class_init (NMDeviceTunClass *klass) FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), - G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_tun_object_info); + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_TUN_SKELETON, + NULL); } @@ -270,29 +494,49 @@ nm_device_tun_class_init (NMDeviceTunClass *klass) #define NM_TUN_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_TUN_FACTORY, NMTunFactory)) static NMDevice * -new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error) +create_device (NMDeviceFactory *factory, + const char *iface, + const NMPlatformLink *plink, + NMConnection *connection, + gboolean *out_ignore) { - const char *mode = NULL; - - if (plink->type == NM_LINK_TYPE_TUN) - mode = "tun"; - else if (plink->type == NM_LINK_TYPE_TAP) - mode = "tap"; - else { - g_warn_if_reached (); - mode = "unknown"; + NMSettingTun *s_tun; + NMLinkType link_type = NM_LINK_TYPE_UNKNOWN; + const char *mode; + + if (plink) { + link_type = plink->type; + } else if (connection) { + s_tun = nm_connection_get_setting_tun (connection); + if (!s_tun) + return NULL; + switch (nm_setting_tun_get_mode (s_tun)) { + case NM_SETTING_TUN_MODE_TUN: + link_type = NM_LINK_TYPE_TUN; + break; + case NM_SETTING_TUN_MODE_TAP: + link_type = NM_LINK_TYPE_TAP; + break; + case NM_SETTING_TUN_MODE_UNKNOWN: + g_return_val_if_reached (NULL); + } } + g_return_val_if_fail (link_type != NM_LINK_TYPE_UNKNOWN, NULL); + mode = link_type == NM_LINK_TYPE_TUN ? "tun" : "tap"; + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_TUN, - NM_DEVICE_PLATFORM_DEVICE, plink, + NM_DEVICE_IFACE, iface, NM_DEVICE_TYPE_DESC, "Tun", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_GENERIC, + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_TUN, + NM_DEVICE_LINK_TYPE, link_type, NM_DEVICE_TUN_MODE, mode, NULL); } NM_DEVICE_FACTORY_DEFINE_INTERNAL (TUN, Tun, tun, - NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_TUN, NM_LINK_TYPE_TAP), - factory_iface->new_link = new_link; + NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_TUN, NM_LINK_TYPE_TAP) + NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_TUN_SETTING_NAME), + factory_iface->create_device = create_device; ) diff --git a/src/devices/nm-device-tun.h b/src/devices/nm-device-tun.h index 393c5801..32dcfd47 100644 --- a/src/devices/nm-device-tun.h +++ b/src/devices/nm-device-tun.h @@ -21,8 +21,6 @@ #ifndef __NETWORKMANAGER_DEVICE_TUN_H__ #define __NETWORKMANAGER_DEVICE_TUN_H__ -#include <glib-object.h> - #include "nm-device-generic.h" G_BEGIN_DECLS @@ -41,8 +39,8 @@ G_BEGIN_DECLS #define NM_DEVICE_TUN_VNET_HDR "vnet-hdr" #define NM_DEVICE_TUN_MULTI_QUEUE "multi-queue" -typedef NMDeviceGeneric NMDeviceTun; -typedef NMDeviceGenericClass NMDeviceTunClass; +typedef NMDevice NMDeviceTun; +typedef NMDeviceClass NMDeviceTunClass; GType nm_device_tun_get_type (void); diff --git a/src/devices/nm-device-veth.c b/src/devices/nm-device-veth.c index 04f03fbb..a1bf0d21 100644 --- a/src/devices/nm-device-veth.c +++ b/src/devices/nm-device-veth.c @@ -29,13 +29,12 @@ #include "nm-device-veth.h" #include "nm-device-private.h" -#include "nm-logging.h" +#include "nm-default.h" #include "nm-manager.h" #include "nm-platform.h" -#include "nm-dbus-manager.h" #include "nm-device-factory.h" -#include "nm-device-veth-glue.h" +#include "nmdbus-device-veth.h" #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceVeth); @@ -77,17 +76,18 @@ get_peer (NMDeviceVeth *self) { NMDeviceVethPrivate *priv = NM_DEVICE_VETH_GET_PRIVATE (self); NMDevice *device = NM_DEVICE (self), *peer = NULL; - NMPlatformVethProperties props; + int peer_ifindex; if (priv->ever_had_peer) return priv->peer; - if (!nm_platform_veth_get_properties (NM_PLATFORM_GET, nm_device_get_ifindex (device), &props)) { + if (!nm_platform_link_veth_get_properties (NM_PLATFORM_GET, nm_device_get_ifindex (device), &peer_ifindex)) { _LOGW (LOGD_HW, "could not read veth properties"); return NULL; } - peer = nm_manager_get_device_by_ifindex (nm_manager_get (), props.peer); + if (peer_ifindex > 0) + peer = nm_manager_get_device_by_ifindex (nm_manager_get (), peer_ifindex); if (peer && NM_IS_DEVICE_VETH (peer)) { set_peer (self, peer); set_peer (NM_DEVICE_VETH (peer), device); @@ -137,7 +137,7 @@ get_property (GObject *object, guint prop_id, switch (prop_id) { case PROP_PEER: peer = get_peer (self); - g_value_set_boxed (value, peer ? nm_device_get_path (peer) : "/"); + nm_utils_g_value_set_object_path (value, peer); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -153,6 +153,8 @@ nm_device_veth_class_init (NMDeviceVethClass *klass) g_type_class_add_private (klass, sizeof (NMDeviceVethPrivate)); + NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_VETH) + object_class->get_property = get_property; object_class->dispose = dispose; @@ -161,14 +163,14 @@ nm_device_veth_class_init (NMDeviceVethClass *klass) /* properties */ g_object_class_install_property (object_class, PROP_PEER, - g_param_spec_boxed (NM_DEVICE_VETH_PEER, "", "", - DBUS_TYPE_G_OBJECT_PATH, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), - G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_veth_object_info); + g_param_spec_string (NM_DEVICE_VETH_PEER, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_VETH_SKELETON, + NULL); } /*************************************************************/ @@ -177,17 +179,22 @@ nm_device_veth_class_init (NMDeviceVethClass *klass) #define NM_VETH_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VETH_FACTORY, NMVethFactory)) static NMDevice * -new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error) +create_device (NMDeviceFactory *factory, + const char *iface, + const NMPlatformLink *plink, + NMConnection *connection, + gboolean *out_ignore) { return (NMDevice *) g_object_new (NM_TYPE_DEVICE_VETH, - NM_DEVICE_PLATFORM_DEVICE, plink, + NM_DEVICE_IFACE, iface, NM_DEVICE_TYPE_DESC, "Veth", NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_ETHERNET, + NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_VETH, NULL); } NM_DEVICE_FACTORY_DEFINE_INTERNAL (VETH, Veth, veth, NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_VETH), - factory_iface->new_link = new_link; + factory_iface->create_device = create_device; ) diff --git a/src/devices/nm-device-veth.h b/src/devices/nm-device-veth.h index 51e8db45..c7b8ec3a 100644 --- a/src/devices/nm-device-veth.h +++ b/src/devices/nm-device-veth.h @@ -21,8 +21,6 @@ #ifndef __NETWORKMANAGER_DEVICE_VETH_H__ #define __NETWORKMANAGER_DEVICE_VETH_H__ -#include <glib-object.h> - #include "nm-device-ethernet.h" G_BEGIN_DECLS diff --git a/src/devices/nm-device-vlan.c b/src/devices/nm-device-vlan.c index 7cce6593..f8710412 100644 --- a/src/devices/nm-device-vlan.c +++ b/src/devices/nm-device-vlan.c @@ -20,19 +20,15 @@ #include "config.h" -#include <glib.h> -#include <glib/gi18n.h> - #include <sys/socket.h> +#include "nm-default.h" #include "nm-device-vlan.h" #include "nm-manager.h" -#include "nm-logging.h" #include "nm-utils.h" #include "NetworkManagerUtils.h" #include "nm-device-private.h" #include "nm-enum-types.h" -#include "nm-dbus-manager.h" #include "nm-connection-provider.h" #include "nm-activation-request.h" #include "nm-ip4-config.h" @@ -40,9 +36,9 @@ #include "nm-device-factory.h" #include "nm-manager.h" #include "nm-core-internal.h" -#include "gsystem-local-alloc.h" +#include "nmp-object.h" -#include "nm-device-vlan-glue.h" +#include "nmdbus-device-vlan.h" #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceVlan); @@ -52,12 +48,10 @@ G_DEFINE_TYPE (NMDeviceVlan, nm_device_vlan, NM_TYPE_DEVICE) #define NM_DEVICE_VLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_VLAN, NMDeviceVlanPrivate)) typedef struct { - gboolean invalid; - NMDevice *parent; - guint parent_state_id; - guint parent_hwaddr_id; - int vlan_id; + gulong parent_state_id; + gulong parent_hwaddr_id; + guint vlan_id; } NMDeviceVlanPrivate; enum { @@ -65,8 +59,6 @@ enum { PROP_PARENT, PROP_VLAN_ID, - PROP_INT_PARENT_DEVICE, - LAST_PROP }; @@ -85,7 +77,7 @@ parent_state_changed (NMDevice *parent, if (reason == NM_DEVICE_STATE_REASON_CARRIER) return; - nm_device_set_unmanaged (NM_DEVICE (self), NM_UNMANAGED_PARENT, !nm_device_get_managed (parent), reason); + nm_device_set_unmanaged_flags (NM_DEVICE (self), NM_UNMANAGED_PARENT, !nm_device_get_managed (parent), reason); } static void @@ -97,12 +89,13 @@ parent_hwaddr_changed (NMDevice *parent, NMConnection *connection; NMSettingWired *s_wired; const char *cloned_mac = NULL, *new_mac; + NMSettingIPConfig *s_ip6; /* Never touch assumed devices */ if (nm_device_uses_assumed_connection (self)) return; - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); if (!connection) return; @@ -118,12 +111,17 @@ parent_hwaddr_changed (NMDevice *parent, if (new_mac) { nm_device_set_hw_addr (self, nm_device_get_hw_address (parent), "set", LOGD_VLAN); + /* When changing the hw address the interface is taken down, + * removing the IPv6 configuration; reapply it. + */ + s_ip6 = nm_connection_get_setting_ip6_config (connection); + nm_device_reactivate_ip6_config (NM_DEVICE (self), s_ip6, s_ip6); } } } static void -nm_device_vlan_set_parent (NMDeviceVlan *self, NMDevice *parent, gboolean construct) +nm_device_vlan_set_parent (NMDeviceVlan *self, NMDevice *parent) { NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self); NMDevice *device = NM_DEVICE (self); @@ -138,7 +136,7 @@ nm_device_vlan_set_parent (NMDeviceVlan *self, NMDevice *parent, gboolean constr if (parent) { priv->parent = g_object_ref (parent); priv->parent_state_id = g_signal_connect (priv->parent, - "state-changed", + NM_DEVICE_STATE_CHANGED, G_CALLBACK (parent_state_changed), device); @@ -146,16 +144,10 @@ nm_device_vlan_set_parent (NMDeviceVlan *self, NMDevice *parent, gboolean constr G_CALLBACK (parent_hwaddr_changed), device); /* Set parent-dependent unmanaged flag */ - if (construct) { - nm_device_set_initial_unmanaged_flag (device, - NM_UNMANAGED_PARENT, - !nm_device_get_managed (parent)); - } else { - nm_device_set_unmanaged (device, - NM_UNMANAGED_PARENT, - !nm_device_get_managed (parent), - NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED); - } + nm_device_set_unmanaged_flags (device, + NM_UNMANAGED_PARENT, + !nm_device_get_managed (parent), + NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED); } /* Recheck availability now that the parent has changed */ @@ -165,6 +157,117 @@ nm_device_vlan_set_parent (NMDeviceVlan *self, NMDevice *parent, gboolean constr g_object_notify (G_OBJECT (device), NM_DEVICE_VLAN_PARENT); } +static void +update_properties (NMDevice *device) +{ + NMDeviceVlanPrivate *priv; + const NMPlatformLink *plink = NULL; + const NMPlatformLnkVlan *plnk = NULL; + NMDevice *parent = NULL; + int ifindex; + guint vlan_id; + + g_return_if_fail (NM_IS_DEVICE_VLAN (device)); + + priv = NM_DEVICE_VLAN_GET_PRIVATE (device); + + ifindex = nm_device_get_ifindex (device); + + if (ifindex > 0) + plnk = nm_platform_link_get_lnk_vlan (NM_PLATFORM_GET, ifindex, &plink); + if ( plnk + && plink->parent + && plink->parent != NM_PLATFORM_LINK_OTHER_NETNS) + parent = nm_manager_get_device_by_ifindex (nm_manager_get (), plink->parent); + + g_object_freeze_notify ((GObject *) device); + + nm_device_vlan_set_parent ((NMDeviceVlan *) device, parent); + + vlan_id = plnk ? plnk->id : 0; + if (vlan_id != priv->vlan_id) { + priv->vlan_id = vlan_id; + g_object_notify ((GObject *) device, NM_DEVICE_VLAN_ID); + } + + g_object_thaw_notify ((GObject *) device); +} + +static void +realize_start_notify (NMDevice *device, const NMPlatformLink *plink) +{ + NM_DEVICE_CLASS (nm_device_vlan_parent_class)->realize_start_notify (device, plink); + + update_properties (device); +} + +static gboolean +create_and_realize (NMDevice *device, + NMConnection *connection, + NMDevice *parent, + const NMPlatformLink **out_plink, + GError **error) +{ + NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device); + const char *iface = nm_device_get_iface (device); + NMSettingVlan *s_vlan; + int parent_ifindex; + guint vlan_id; + NMPlatformError plerr; + + s_vlan = nm_connection_get_setting_vlan (connection); + g_assert (s_vlan); + + if (!nm_device_supports_vlans (parent)) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "no support for VLANs on interface %s of type %s", + nm_device_get_iface (parent), + nm_device_get_type_desc (parent)); + return FALSE; + } + + parent_ifindex = nm_device_get_ifindex (parent); + g_warn_if_fail (parent_ifindex > 0); + + vlan_id = nm_setting_vlan_get_id (s_vlan); + + plerr = nm_platform_link_vlan_add (NM_PLATFORM_GET, + iface, + parent_ifindex, + vlan_id, + nm_setting_vlan_get_flags (s_vlan), + out_plink); + if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, + "Failed to create VLAN interface '%s' for '%s': %s", + iface, + nm_connection_get_id (connection), + nm_platform_error_to_string (plerr)); + return FALSE; + } + + g_warn_if_fail (priv->parent == NULL); + nm_device_vlan_set_parent (NM_DEVICE_VLAN (device), parent); + if (vlan_id != priv->vlan_id) { + priv->vlan_id = vlan_id; + g_object_notify ((GObject *) device, NM_DEVICE_VLAN_ID); + } + + return TRUE; +} + +static void +unrealize_notify (NMDevice *device) +{ + NM_DEVICE_CLASS (nm_device_vlan_parent_class)->unrealize_notify (device); + + NM_DEVICE_VLAN_GET_PRIVATE (device)->vlan_id = 0; + g_object_notify (G_OBJECT (device), NM_DEVICE_VLAN_ID); + nm_device_vlan_set_parent (NM_DEVICE_VLAN (device), NULL); +} + +/******************************************************************/ + static NMDeviceCapabilities get_generic_capabilities (NMDevice *dev) { @@ -197,34 +300,29 @@ is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags) return NM_DEVICE_CLASS (nm_device_vlan_parent_class)->is_available (device, flags); } -static gboolean -component_added (NMDevice *device, GObject *component) +static void +notify_new_device_added (NMDevice *device, NMDevice *new_device) { NMDeviceVlan *self = NM_DEVICE_VLAN (device); NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self); - NMDevice *added_device; - int parent_ifindex = -1; + const NMPlatformLink *plink; + const NMPlatformLnkVlan *plnk; if (priv->parent) - return FALSE; - - if (!NM_IS_DEVICE (component)) - return FALSE; - added_device = NM_DEVICE (component); + return; - if (!nm_platform_vlan_get_info (NM_PLATFORM_GET, nm_device_get_ifindex (device), &parent_ifindex, NULL)) { - _LOGW (LOGD_VLAN, "failed to get VLAN interface info while checking added component."); - return FALSE; - } + if (!nm_device_is_real (device)) + return; - if ( parent_ifindex <= 0 - || nm_device_get_ifindex (added_device) != parent_ifindex) - return FALSE; + plnk = nm_platform_link_get_lnk_vlan (NM_PLATFORM_GET, nm_device_get_ifindex (device), &plink); + if (!plnk) + return; - nm_device_vlan_set_parent (self, added_device, FALSE); + if ( plink->parent <= 0 + || nm_device_get_ifindex (new_device) != plink->parent) + return; - /* Don't claim parent exclusively */ - return FALSE; + nm_device_vlan_set_parent (self, new_device); } /******************************************************************/ @@ -251,7 +349,7 @@ match_parent (NMDeviceVlan *self, const char *parent) if (!parent_req) return FALSE; - parent_connection = nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (parent_req)); + parent_connection = nm_active_connection_get_applied_connection (NM_ACTIVE_CONNECTION (parent_req)); if (!parent_connection) return FALSE; @@ -300,18 +398,21 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) if (!s_vlan) return FALSE; - if (nm_setting_vlan_get_id (s_vlan) != priv->vlan_id) - return FALSE; - - /* Check parent interface; could be an interface name or a UUID */ - parent = nm_setting_vlan_get_parent (s_vlan); - if (parent) { - if (!match_parent (NM_DEVICE_VLAN (device), parent)) - return FALSE; - } else { - /* Parent could be a MAC address in an NMSettingWired */ - if (!match_hwaddr (device, connection, TRUE)) + /* Before the device is realized some properties will not be set */ + if (nm_device_is_real (device)) { + if (nm_setting_vlan_get_id (s_vlan) != priv->vlan_id) return FALSE; + + /* Check parent interface; could be an interface name or a UUID */ + parent = nm_setting_vlan_get_parent (s_vlan); + if (parent) { + if (!match_parent (NM_DEVICE_VLAN (device), parent)) + return FALSE; + } else { + /* Parent could be a MAC address in an NMSettingWired */ + if (!match_hwaddr (device, connection, TRUE)) + return FALSE; + } } /* Ensure the interface name matches. If not specified we assume a match @@ -328,6 +429,18 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) } static gboolean +check_connection_available (NMDevice *device, + NMConnection *connection, + NMDeviceCheckConAvailableFlags flags, + const char *specific_object) +{ + if (!nm_device_is_real (device)) + return TRUE; + + return NM_DEVICE_CLASS (nm_device_vlan_parent_class)->check_connection_available (device, connection, flags, specific_object); +} + +static gboolean complete_connection (NMDevice *device, NMConnection *connection, const char *specific_object, @@ -367,54 +480,67 @@ complete_connection (NMDevice *device, static void update_connection (NMDevice *device, NMConnection *connection) { - NMDeviceVlan *self = NM_DEVICE_VLAN (device); NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (device); NMSettingVlan *s_vlan = nm_connection_get_setting_vlan (connection); int ifindex = nm_device_get_ifindex (device); - int parent_ifindex = -1, vlan_id = -1; - NMDevice *parent; const char *setting_parent, *new_parent; + const NMPlatformLink *plink; + const NMPObject *polnk; + guint vlan_id; + guint vlan_flags; if (!s_vlan) { s_vlan = (NMSettingVlan *) nm_setting_vlan_new (); nm_connection_add_setting (connection, (NMSetting *) s_vlan); } - if (!nm_platform_vlan_get_info (NM_PLATFORM_GET, ifindex, &parent_ifindex, &vlan_id)) { - _LOGW (LOGD_VLAN, "failed to get VLAN interface info while updating connection."); - return; - } + polnk = nm_platform_link_get_lnk (NM_PLATFORM_GET, ifindex, NM_LINK_TYPE_VLAN, &plink); - if (priv->vlan_id != vlan_id) { - priv->vlan_id = vlan_id; - g_object_notify (G_OBJECT (device), NM_DEVICE_VLAN_ID); - } - - if (vlan_id != nm_setting_vlan_get_id (s_vlan)) - g_object_set (s_vlan, NM_SETTING_VLAN_ID, priv->vlan_id, NULL); - - if (parent_ifindex != NM_PLATFORM_LINK_OTHER_NETNS) - parent = nm_manager_get_device_by_ifindex (nm_manager_get (), parent_ifindex); + if (polnk) + vlan_id = polnk->lnk_vlan.id; else - parent = NULL; - nm_device_vlan_set_parent (NM_DEVICE_VLAN (device), parent, FALSE); + vlan_id = priv->vlan_id; + if (vlan_id != nm_setting_vlan_get_id (s_vlan)) + g_object_set (s_vlan, NM_SETTING_VLAN_ID, vlan_id, NULL); /* Update parent in the connection; default to parent's interface name */ - if (parent) { - new_parent = nm_device_get_iface (parent); + if ( priv->parent + && polnk + && plink->parent > 0 + && nm_device_get_ifindex (priv->parent) == plink->parent) { + new_parent = nm_device_get_iface (priv->parent); setting_parent = nm_setting_vlan_get_parent (s_vlan); if (setting_parent && nm_utils_is_uuid (setting_parent)) { NMConnection *parent_connection; /* Don't change a parent specified by UUID if it's still valid */ parent_connection = nm_connection_provider_get_connection_by_uuid (nm_connection_provider_get (), setting_parent); - if (parent_connection && nm_device_check_connection_compatible (parent, parent_connection)) + if (parent_connection && nm_device_check_connection_compatible (priv->parent, parent_connection)) new_parent = NULL; } if (new_parent) g_object_set (s_vlan, NM_SETTING_VLAN_PARENT, new_parent, NULL); } else g_object_set (s_vlan, NM_SETTING_VLAN_PARENT, NULL, NULL); + + if (polnk) + vlan_flags = polnk->lnk_vlan.flags; + else + vlan_flags = NM_VLAN_FLAG_REORDER_HEADERS; + if (vlan_flags != nm_setting_vlan_get_flags (s_vlan)) + g_object_set (s_vlan, NM_SETTING_VLAN_FLAGS, (NMVlanFlags) vlan_flags, NULL); + + if (polnk) { + _nm_setting_vlan_set_priorities (s_vlan, NM_VLAN_INGRESS_MAP, + polnk->_lnk_vlan.ingress_qos_map, + polnk->_lnk_vlan.n_ingress_qos_map); + _nm_setting_vlan_set_priorities (s_vlan, NM_VLAN_EGRESS_MAP, + polnk->_lnk_vlan.egress_qos_map, + polnk->_lnk_vlan.n_egress_qos_map); + } else { + _nm_setting_vlan_set_priorities (s_vlan, NM_VLAN_INGRESS_MAP, NULL, 0); + _nm_setting_vlan_set_priorities (s_vlan, NM_VLAN_EGRESS_MAP, NULL, 0); + } } static NMActStageReturn @@ -436,7 +562,7 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) req = nm_device_get_act_request (dev); g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); - connection = nm_act_request_get_connection (req); + connection = nm_act_request_get_applied_connection (req); g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE); s_wired = nm_connection_get_setting_wired (connection); @@ -449,20 +575,29 @@ act_stage1_prepare (NMDevice *dev, NMDeviceStateReason *reason) s_vlan = nm_connection_get_setting_vlan (connection); if (s_vlan) { - int ifindex = nm_device_get_ifindex (dev); - int num, i; - guint32 from, to; - - num = nm_setting_vlan_get_num_priorities (s_vlan, NM_VLAN_INGRESS_MAP); - for (i = 0; i < num; i++) { - if (nm_setting_vlan_get_priority (s_vlan, NM_VLAN_INGRESS_MAP, i, &from, &to)) - nm_platform_vlan_set_ingress_map (NM_PLATFORM_GET, ifindex, from, to); - } - num = nm_setting_vlan_get_num_priorities (s_vlan, NM_VLAN_EGRESS_MAP); - for (i = 0; i < num; i++) { - if (nm_setting_vlan_get_priority (s_vlan, NM_VLAN_EGRESS_MAP, i, &from, &to)) - nm_platform_vlan_set_egress_map (NM_PLATFORM_GET, ifindex, from, to); - } + gs_free NMVlanQosMapping *ingress_map = NULL; + gs_free NMVlanQosMapping *egress_map = NULL; + guint n_ingress_map = 0, n_egress_map = 0; + + _nm_setting_vlan_get_priorities (s_vlan, + NM_VLAN_INGRESS_MAP, + &ingress_map, + &n_ingress_map); + _nm_setting_vlan_get_priorities (s_vlan, + NM_VLAN_EGRESS_MAP, + &egress_map, + &n_egress_map); + + nm_platform_link_vlan_change (NM_PLATFORM_GET, + nm_device_get_ifindex (dev), + NM_VLAN_FLAGS_ALL, + nm_setting_vlan_get_flags (s_vlan), + TRUE, + ingress_map, + n_ingress_map, + TRUE, + egress_map, + n_egress_map); } return ret; @@ -475,7 +610,7 @@ ip4_config_pre_commit (NMDevice *device, NMIP4Config *config) NMSettingWired *s_wired; guint32 mtu; - connection = nm_device_get_connection (device); + connection = nm_device_get_applied_connection (device); g_assert (connection); s_wired = nm_connection_get_setting_wired (connection); @@ -502,54 +637,6 @@ nm_device_vlan_init (NMDeviceVlan * self) } static void -constructed (GObject *object) -{ - NMDeviceVlan *self = NM_DEVICE_VLAN (object); - NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (self); - int ifindex = nm_device_get_ifindex (NM_DEVICE (self)); - int parent_ifindex = -1, itype; - int vlan_id; - - if (G_OBJECT_CLASS (nm_device_vlan_parent_class)->constructed) - G_OBJECT_CLASS (nm_device_vlan_parent_class)->constructed (object); - - itype = nm_platform_link_get_type (NM_PLATFORM_GET, ifindex); - if (itype != NM_LINK_TYPE_VLAN) { - _LOGE (LOGD_VLAN, "failed to get VLAN interface type."); - priv->invalid = TRUE; - return; - } - - if (!nm_platform_vlan_get_info (NM_PLATFORM_GET, ifindex, &parent_ifindex, &vlan_id)) { - _LOGW (LOGD_VLAN, "failed to get VLAN interface info."); - priv->invalid = TRUE; - return; - } - - if (parent_ifindex < 0 || vlan_id < 0) { - _LOGW (LOGD_VLAN, "VLAN parent ifindex (%d) or VLAN ID (%d) invalid.", - parent_ifindex, priv->vlan_id); - priv->invalid = TRUE; - return; - } - - if (priv->parent && parent_ifindex != nm_device_get_ip_ifindex (priv->parent)) { - _LOGW (LOGD_VLAN, "VLAN parent %s (%d) and parent ifindex %d don't match.", - nm_device_get_iface (priv->parent), - nm_device_get_ifindex (priv->parent), - parent_ifindex); - priv->invalid = TRUE; - return; - } - - priv->vlan_id = vlan_id; - _LOGI (LOGD_HW | LOGD_VLAN, "VLAN ID %d with parent %s (%d)", - priv->vlan_id, - priv->parent ? nm_device_get_iface (priv->parent) : "unknown", - parent_ifindex); -} - -static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { @@ -557,10 +644,7 @@ get_property (GObject *object, guint prop_id, switch (prop_id) { case PROP_PARENT: - g_value_set_boxed (value, priv->parent ? nm_device_get_path (priv->parent) : "/"); - break; - case PROP_INT_PARENT_DEVICE: - g_value_set_object (value, priv->parent); + nm_utils_g_value_set_object_path (value, priv->parent); break; case PROP_VLAN_ID: g_value_set_uint (value, priv->vlan_id); @@ -575,25 +659,13 @@ static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { - NMDeviceVlanPrivate *priv = NM_DEVICE_VLAN_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_INT_PARENT_DEVICE: - nm_device_vlan_set_parent (NM_DEVICE_VLAN (object), g_value_get_object (value), TRUE); - break; - case PROP_VLAN_ID: - priv->vlan_id = g_value_get_uint (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } static void dispose (GObject *object) { - nm_device_vlan_set_parent (NM_DEVICE_VLAN (object), NULL, FALSE); + nm_device_vlan_set_parent (NM_DEVICE_VLAN (object), NULL); G_OBJECT_CLASS (nm_device_vlan_parent_class)->dispose (object); } @@ -604,53 +676,47 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass) GObjectClass *object_class = G_OBJECT_CLASS (klass); NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); - parent_class->connection_type = NM_SETTING_VLAN_SETTING_NAME; + NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_VLAN_SETTING_NAME, NM_LINK_TYPE_VLAN) g_type_class_add_private (object_class, sizeof (NMDeviceVlanPrivate)); /* virtual methods */ - object_class->constructed = constructed; object_class->get_property = get_property; object_class->set_property = set_property; object_class->dispose = dispose; + parent_class->create_and_realize = create_and_realize; + parent_class->realize_start_notify = realize_start_notify; + parent_class->unrealize_notify = unrealize_notify; parent_class->get_generic_capabilities = get_generic_capabilities; parent_class->bring_up = bring_up; parent_class->act_stage1_prepare = act_stage1_prepare; parent_class->ip4_config_pre_commit = ip4_config_pre_commit; parent_class->deactivate = deactivate; parent_class->is_available = is_available; - parent_class->component_added = component_added; + parent_class->notify_new_device_added = notify_new_device_added; parent_class->check_connection_compatible = check_connection_compatible; + parent_class->check_connection_available = check_connection_available; parent_class->complete_connection = complete_connection; parent_class->update_connection = update_connection; /* properties */ g_object_class_install_property (object_class, PROP_PARENT, - g_param_spec_boxed (NM_DEVICE_VLAN_PARENT, "", "", - DBUS_TYPE_G_OBJECT_PATH, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + g_param_spec_string (NM_DEVICE_VLAN_PARENT, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_VLAN_ID, g_param_spec_uint (NM_DEVICE_VLAN_ID, "", "", 0, 4095, 0, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - /* Internal properties */ - g_object_class_install_property - (object_class, PROP_INT_PARENT_DEVICE, - g_param_spec_object (NM_DEVICE_VLAN_INT_PARENT_DEVICE, "", "", - NM_TYPE_DEVICE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), - G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_vlan_object_info); + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_VLAN_SKELETON, + NULL); } /*************************************************************/ @@ -659,98 +725,19 @@ nm_device_vlan_class_init (NMDeviceVlanClass *klass) #define NM_VLAN_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VLAN_FACTORY, NMVlanFactory)) static NMDevice * -new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error) +create_device (NMDeviceFactory *factory, + const char *iface, + const NMPlatformLink *plink, + NMConnection *connection, + gboolean *out_ignore) { - int parent_ifindex = -1; - NMDevice *parent, *device; - - /* Find the parent device */ - if (!nm_platform_vlan_get_info (NM_PLATFORM_GET, plink->ifindex, &parent_ifindex, NULL)) { - g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, - "VLAN parent ifindex unknown"); - return NULL; - } - if (parent_ifindex > 0) - parent = nm_manager_get_device_by_ifindex (nm_manager_get (), parent_ifindex); - else - parent = NULL; - - device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_VLAN, - NM_DEVICE_PLATFORM_DEVICE, plink, - NM_DEVICE_VLAN_INT_PARENT_DEVICE, parent, - NM_DEVICE_DRIVER, "8021q", - NM_DEVICE_TYPE_DESC, "VLAN", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_VLAN, - NULL); - if (NM_DEVICE_VLAN_GET_PRIVATE (device)->invalid) { - g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, - "VLAN initialization failed"); - g_object_unref (device); - device = NULL; - } - - return device; -} - -static NMDevice * -create_virtual_device_for_connection (NMDeviceFactory *factory, - NMConnection *connection, - NMDevice *parent, - GError **error) -{ - NMDevice *device; - NMSettingVlan *s_vlan; - gs_free char *iface = NULL; - NMPlatformError plerr; - const NMPlatformLink *plink; - - if (!NM_IS_DEVICE (parent)) { - g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, - "VLAN interfaces must have parents"); - return NULL; - } - - s_vlan = nm_connection_get_setting_vlan (connection); - g_assert (s_vlan); - - iface = g_strdup (nm_connection_get_interface_name (connection)); - if (!iface) { - iface = nm_utils_new_vlan_name (nm_device_get_ip_iface (parent), - nm_setting_vlan_get_id (s_vlan)); - } - - plerr = nm_platform_vlan_add (NM_PLATFORM_GET, - iface, - nm_device_get_ifindex (parent), - nm_setting_vlan_get_id (s_vlan), - nm_setting_vlan_get_flags (s_vlan), - NULL); - if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { - g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, - "Failed to create VLAN interface '%s' for '%s': %s", - iface, - nm_connection_get_id (connection), - nm_platform_error_to_string (plerr)); - return NULL; - } - plink = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, iface); - - device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_VLAN, - NM_DEVICE_PLATFORM_DEVICE, plink, - NM_DEVICE_VLAN_INT_PARENT_DEVICE, parent, - NM_DEVICE_DRIVER, "8021q", - NM_DEVICE_TYPE_DESC, "VLAN", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_VLAN, - NULL); - if (NM_DEVICE_VLAN_GET_PRIVATE (device)->invalid) { - g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, - "Failed to create VLAN interface '%s' for '%s': initialization failed", - iface, nm_connection_get_id (connection)); - g_object_unref (device); - device = NULL; - } - - return device; + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_VLAN, + NM_DEVICE_IFACE, iface, + NM_DEVICE_DRIVER, "8021q", + NM_DEVICE_TYPE_DESC, "VLAN", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_VLAN, + NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_VLAN, + NULL); } static const char * @@ -807,8 +794,7 @@ get_virtual_iface_name (NMDeviceFactory *factory, NM_DEVICE_FACTORY_DEFINE_INTERNAL (VLAN, Vlan, vlan, NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_VLAN) NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_VLAN_SETTING_NAME), - factory_iface->new_link = new_link; - factory_iface->create_virtual_device_for_connection = create_virtual_device_for_connection; + factory_iface->create_device = create_device; factory_iface->get_connection_parent = get_connection_parent; factory_iface->get_virtual_iface_name = get_virtual_iface_name; ) diff --git a/src/devices/nm-device-vlan.h b/src/devices/nm-device-vlan.h index 20fc3453..e31e171d 100644 --- a/src/devices/nm-device-vlan.h +++ b/src/devices/nm-device-vlan.h @@ -21,8 +21,6 @@ #ifndef __NETWORKMANAGER_DEVICE_VLAN_H__ #define __NETWORKMANAGER_DEVICE_VLAN_H__ -#include <glib-object.h> - #include "nm-device.h" G_BEGIN_DECLS @@ -44,9 +42,6 @@ typedef enum { #define NM_DEVICE_VLAN_PARENT "parent" #define NM_DEVICE_VLAN_ID "vlan-id" -/* Internal non-exported properties */ -#define NM_DEVICE_VLAN_INT_PARENT_DEVICE "int-parent-device" - typedef NMDevice NMDeviceVlan; typedef NMDeviceClass NMDeviceVlanClass; diff --git a/src/devices/nm-device-vxlan.c b/src/devices/nm-device-vxlan.c index 186e00de..aab90539 100644 --- a/src/devices/nm-device-vxlan.c +++ b/src/devices/nm-device-vxlan.c @@ -15,49 +15,54 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2013, 2014 Red Hat, Inc. + * Copyright 2013 - 2015 Red Hat, Inc. */ #include "config.h" #include <string.h> +#include "nm-default.h" #include "nm-device-vxlan.h" #include "nm-device-private.h" -#include "nm-dbus-manager.h" -#include "nm-logging.h" #include "nm-manager.h" #include "nm-platform.h" #include "nm-utils.h" #include "nm-device-factory.h" +#include "nm-setting-vxlan.h" +#include "nm-setting-wired.h" +#include "nm-connection-provider.h" +#include "nm-activation-request.h" +#include "nm-ip4-config.h" -#include "nm-device-vxlan-glue.h" +#include "nmdbus-device-vxlan.h" #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceVxlan); -G_DEFINE_TYPE (NMDeviceVxlan, nm_device_vxlan, NM_TYPE_DEVICE_GENERIC) +G_DEFINE_TYPE (NMDeviceVxlan, nm_device_vxlan, NM_TYPE_DEVICE) #define NM_DEVICE_VXLAN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_VXLAN, NMDeviceVxlanPrivate)) typedef struct { - NMPlatformVxlanProperties props; + NMDevice *parent; + NMPlatformLnkVxlan props; } NMDeviceVxlanPrivate; enum { PROP_0, PROP_PARENT, PROP_ID, - PROP_GROUP, PROP_LOCAL, + PROP_GROUP, PROP_TOS, PROP_TTL, PROP_LEARNING, PROP_AGEING, PROP_LIMIT, - PROP_DST_PORT, PROP_SRC_PORT_MIN, PROP_SRC_PORT_MAX, + PROP_DST_PORT, PROP_PROXY, PROP_RSC, PROP_L2MISS, @@ -74,53 +79,60 @@ update_properties (NMDevice *device) NMDeviceVxlan *self = NM_DEVICE_VXLAN (device); NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (device); GObject *object = G_OBJECT (device); - NMPlatformVxlanProperties props; + const NMPlatformLnkVxlan *props; + NMDevice *parent; - if (!nm_platform_vxlan_get_properties (NM_PLATFORM_GET, nm_device_get_ifindex (device), &props)) { - _LOGW (LOGD_HW, "could not read vxlan properties"); + props = nm_platform_link_get_lnk_vxlan (NM_PLATFORM_GET, nm_device_get_ifindex (device), NULL); + if (!props) { + _LOGW (LOGD_HW, "could not get vxlan properties"); return; } g_object_freeze_notify (object); - if (priv->props.parent_ifindex != props.parent_ifindex) + if (priv->props.parent_ifindex != props->parent_ifindex) { + g_clear_object (&priv->parent); + parent = nm_manager_get_device_by_ifindex (nm_manager_get (), props->parent_ifindex); + if (parent) + priv->parent = g_object_ref (parent); g_object_notify (object, NM_DEVICE_VXLAN_PARENT); - if (priv->props.id != props.id) + } + if (priv->props.id != props->id) g_object_notify (object, NM_DEVICE_VXLAN_ID); - if (priv->props.group != props.group) - g_object_notify (object, NM_DEVICE_VXLAN_GROUP); - if (priv->props.local != props.local) + if (priv->props.local != props->local) g_object_notify (object, NM_DEVICE_VXLAN_LOCAL); - if (memcmp (&priv->props.group6, &props.group6, sizeof (props.group6)) != 0) - g_object_notify (object, NM_DEVICE_VXLAN_GROUP); - if (memcmp (&priv->props.local6, &props.local6, sizeof (props.local6)) != 0) + if (memcmp (&priv->props.local6, &props->local6, sizeof (props->local6)) != 0) g_object_notify (object, NM_DEVICE_VXLAN_LOCAL); - if (priv->props.tos != props.tos) + if (priv->props.group != props->group) + g_object_notify (object, NM_DEVICE_VXLAN_GROUP); + if (memcmp (&priv->props.group6, &props->group6, sizeof (props->group6)) != 0) + g_object_notify (object, NM_DEVICE_VXLAN_GROUP); + if (priv->props.tos != props->tos) g_object_notify (object, NM_DEVICE_VXLAN_TOS); - if (priv->props.ttl != props.ttl) + if (priv->props.ttl != props->ttl) g_object_notify (object, NM_DEVICE_VXLAN_TTL); - if (priv->props.learning != props.learning) + if (priv->props.learning != props->learning) g_object_notify (object, NM_DEVICE_VXLAN_LEARNING); - if (priv->props.ageing != props.ageing) + if (priv->props.ageing != props->ageing) g_object_notify (object, NM_DEVICE_VXLAN_AGEING); - if (priv->props.limit != props.limit) + if (priv->props.limit != props->limit) g_object_notify (object, NM_DEVICE_VXLAN_LIMIT); - if (priv->props.dst_port != props.dst_port) - g_object_notify (object, NM_DEVICE_VXLAN_DST_PORT); - if (priv->props.src_port_min != props.src_port_min) + if (priv->props.src_port_min != props->src_port_min) g_object_notify (object, NM_DEVICE_VXLAN_SRC_PORT_MIN); - if (priv->props.src_port_max != props.src_port_max) + if (priv->props.src_port_max != props->src_port_max) g_object_notify (object, NM_DEVICE_VXLAN_SRC_PORT_MAX); - if (priv->props.proxy != props.proxy) + if (priv->props.dst_port != props->dst_port) + g_object_notify (object, NM_DEVICE_VXLAN_DST_PORT); + if (priv->props.proxy != props->proxy) g_object_notify (object, NM_DEVICE_VXLAN_PROXY); - if (priv->props.rsc != props.rsc) + if (priv->props.rsc != props->rsc) g_object_notify (object, NM_DEVICE_VXLAN_RSC); - if (priv->props.l2miss != props.l2miss) + if (priv->props.l2miss != props->l2miss) g_object_notify (object, NM_DEVICE_VXLAN_L2MISS); - if (priv->props.l3miss != props.l3miss) + if (priv->props.l3miss != props->l3miss) g_object_notify (object, NM_DEVICE_VXLAN_L3MISS); - memcpy (&priv->props, &props, sizeof (NMPlatformVxlanProperties)); + priv->props = *props; g_object_thaw_notify (object); } @@ -132,19 +144,424 @@ link_changed (NMDevice *device, NMPlatformLink *info) update_properties (device); } -/**************************************************************/ +static void +realize_start_notify (NMDevice *device, const NMPlatformLink *plink) +{ + g_assert (plink->type == NM_LINK_TYPE_VXLAN); + + NM_DEVICE_CLASS (nm_device_vxlan_parent_class)->realize_start_notify (device, plink); + + update_properties (device); +} static void -nm_device_vxlan_init (NMDeviceVxlan *self) +unrealize_notify (NMDevice *device) +{ + NMDeviceVxlan *self = NM_DEVICE_VXLAN (device); + NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (self); + GParamSpec **properties; + guint n_properties, i; + + NM_DEVICE_CLASS (nm_device_vxlan_parent_class)->unrealize_notify (device); + + memset (&priv->props, 0, sizeof (NMPlatformLnkVxlan)); + + properties = g_object_class_list_properties (G_OBJECT_GET_CLASS (self), &n_properties); + for (i = 0; i < n_properties; i++) + g_object_notify_by_pspec (G_OBJECT (self), properties[i]); + g_free (properties); +} + +static gboolean +create_and_realize (NMDevice *device, + NMConnection *connection, + NMDevice *parent, + const NMPlatformLink **out_plink, + GError **error) +{ + const char *iface = nm_device_get_iface (device); + NMPlatformError plerr; + NMPlatformLnkVxlan props = { }; + NMSettingVxlan *s_vxlan; + const char *str; + int ret; + + s_vxlan = nm_connection_get_setting_vxlan (connection); + g_assert (s_vxlan); + + if (parent) + props.parent_ifindex = nm_device_get_ifindex (parent); + + props.id = nm_setting_vxlan_get_id (s_vxlan); + + str = nm_setting_vxlan_get_local (s_vxlan); + if (str) { + ret = inet_pton (AF_INET, str, &props.local); + if (ret != 1) + ret = inet_pton (AF_INET6, str, &props.local6); + if (ret != 1) + return FALSE; + } + + str = nm_setting_vxlan_get_remote (s_vxlan); + ret = inet_pton (AF_INET, str, &props.group); + if (ret != 1) + ret = inet_pton (AF_INET6, str, &props.group6); + if (ret != 1) + return FALSE; + + props.tos = nm_setting_vxlan_get_tos (s_vxlan); + props.ttl = nm_setting_vxlan_get_ttl (s_vxlan); + props.learning = nm_setting_vxlan_get_learning (s_vxlan); + props.ageing = nm_setting_vxlan_get_ageing (s_vxlan); + props.limit = nm_setting_vxlan_get_limit (s_vxlan); + props.src_port_min = nm_setting_vxlan_get_source_port_min (s_vxlan); + props.src_port_max = nm_setting_vxlan_get_source_port_max (s_vxlan); + props.dst_port = nm_setting_vxlan_get_destination_port (s_vxlan); + props.proxy = nm_setting_vxlan_get_proxy (s_vxlan); + props.rsc = nm_setting_vxlan_get_rsc (s_vxlan); + props.l2miss = nm_setting_vxlan_get_l2_miss (s_vxlan); + props.l3miss = nm_setting_vxlan_get_l3_miss (s_vxlan); + + plerr = nm_platform_link_vxlan_add (NM_PLATFORM_GET, iface, &props, out_plink); + if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, + "Failed to create VXLAN interface '%s' for '%s': %s", + iface, + nm_connection_get_id (connection), + nm_platform_error_to_string (plerr)); + return FALSE; + } + + return TRUE; +} + +static gboolean +match_parent (NMDeviceVxlan *self, const char *parent) +{ + NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (self); + + g_return_val_if_fail (parent != NULL, FALSE); + + if (!priv->parent) + return FALSE; + + if (nm_utils_is_uuid (parent)) { + NMActRequest *parent_req; + NMConnection *parent_connection; + + /* If the parent is a UUID, the connection matches if our parent + * device has that connection activated. + */ + parent_req = nm_device_get_act_request (priv->parent); + if (!parent_req) + return FALSE; + + parent_connection = nm_active_connection_get_applied_connection (NM_ACTIVE_CONNECTION (parent_req)); + if (!parent_connection) + return FALSE; + + if (g_strcmp0 (parent, nm_connection_get_uuid (parent_connection)) != 0) + return FALSE; + } else { + /* interface name */ + if (g_strcmp0 (parent, nm_device_get_ip_iface (priv->parent)) != 0) + return FALSE; + } + + return TRUE; +} + +static gboolean +address_matches (const char *str, in_addr_t addr4, struct in6_addr *addr6) +{ + in_addr_t new_addr4 = 0; + struct in6_addr new_addr6 = { }; + + if (!str) { + return addr4 == 0 + && !memcmp (addr6, &in6addr_any, sizeof (in6addr_any)); + } + + if (inet_pton (AF_INET, str, &new_addr4) == 1) + return new_addr4 == addr4; + else if (inet_pton (AF_INET6, str, &new_addr6) == 1) + return !memcmp (&new_addr6, addr6, sizeof (new_addr6)); + else + return FALSE; +} + +static gboolean +check_connection_compatible (NMDevice *device, NMConnection *connection) +{ + NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (device); + NMSettingVxlan *s_vxlan; + const char *iface, *parent; + + if (!NM_DEVICE_CLASS (nm_device_vxlan_parent_class)->check_connection_compatible (device, connection)) + return FALSE; + + s_vxlan = nm_connection_get_setting_vxlan (connection); + if (!s_vxlan) + return FALSE; + + iface = nm_connection_get_interface_name (connection); + if (iface) { + if (g_strcmp0 (nm_device_get_ip_iface (device), iface) != 0) + return FALSE; + } + + if (nm_device_is_real (device)) { + parent = nm_setting_vxlan_get_parent (s_vxlan); + if ( parent + && !match_parent (NM_DEVICE_VXLAN (device), parent)) + return FALSE; + + if (priv->props.id != nm_setting_vxlan_get_id (s_vxlan)) + return FALSE; + + if (!address_matches (nm_setting_vxlan_get_local (s_vxlan), priv->props.local, &priv->props.local6)) + return FALSE; + + if (!address_matches (nm_setting_vxlan_get_remote (s_vxlan), priv->props.group, &priv->props.group6)) + return FALSE; + + if (priv->props.src_port_min != nm_setting_vxlan_get_source_port_min (s_vxlan)) + return FALSE; + + if (priv->props.src_port_max != nm_setting_vxlan_get_source_port_max (s_vxlan)) + return FALSE; + + if (priv->props.dst_port != nm_setting_vxlan_get_destination_port (s_vxlan)) + return FALSE; + + if (priv->props.tos != nm_setting_vxlan_get_tos (s_vxlan)) + return FALSE; + + if (priv->props.ttl != nm_setting_vxlan_get_ttl (s_vxlan)) + return FALSE; + + if (priv->props.learning != nm_setting_vxlan_get_learning (s_vxlan)) + return FALSE; + + if (priv->props.ageing != nm_setting_vxlan_get_ageing (s_vxlan)) + return FALSE; + + if (priv->props.proxy != nm_setting_vxlan_get_proxy (s_vxlan)) + return FALSE; + + if (priv->props.rsc != nm_setting_vxlan_get_rsc (s_vxlan)) + return FALSE; + + if (priv->props.l2miss != nm_setting_vxlan_get_l2_miss (s_vxlan)) + return FALSE; + + if (priv->props.l3miss != nm_setting_vxlan_get_l3_miss (s_vxlan)) + return FALSE; + } + + return TRUE; +} + +static gboolean +complete_connection (NMDevice *device, + NMConnection *connection, + const char *specific_object, + const GSList *existing_connections, + GError **error) +{ + NMSettingVxlan *s_vxlan; + + nm_utils_complete_generic (connection, + NM_SETTING_VXLAN_SETTING_NAME, + existing_connections, + NULL, + _("VXLAN connection"), + NULL, + TRUE); + + s_vxlan = nm_connection_get_setting_vxlan (connection); + if (!s_vxlan) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INVALID_CONNECTION, + "A 'vxlan' setting is required."); + return FALSE; + } + + return TRUE; +} + +static void +update_connection (NMDevice *device, NMConnection *connection) +{ + NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (device); + NMSettingVxlan *s_vxlan = nm_connection_get_setting_vxlan (connection); + NMDevice *parent = NULL; + const char *setting_parent, *new_parent; + + if (!s_vxlan) { + s_vxlan = (NMSettingVxlan *) nm_setting_vxlan_new (); + nm_connection_add_setting (connection, (NMSetting *) s_vxlan); + } + + if (priv->props.id != nm_setting_vxlan_get_id (s_vxlan)) + g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_ID, priv->props.id, NULL); + + if (priv->props.parent_ifindex != NM_PLATFORM_LINK_OTHER_NETNS) + parent = nm_manager_get_device_by_ifindex (nm_manager_get (), priv->props.parent_ifindex); + + /* Update parent in the connection; default to parent's interface name */ + if (parent) { + new_parent = nm_device_get_iface (parent); + setting_parent = nm_setting_vxlan_get_parent (s_vxlan); + if (setting_parent && nm_utils_is_uuid (setting_parent)) { + NMConnection *parent_connection; + + /* Don't change a parent specified by UUID if it's still valid */ + parent_connection = nm_connection_provider_get_connection_by_uuid (nm_connection_provider_get (), + setting_parent); + if (parent_connection && nm_device_check_connection_compatible (parent, parent_connection)) + new_parent = NULL; + } + if (new_parent) + g_object_set (s_vxlan, NM_SETTING_VXLAN_PARENT, new_parent, NULL); + } else + g_object_set (s_vxlan, NM_SETTING_VXLAN_PARENT, NULL, NULL); + + if (!address_matches (nm_setting_vxlan_get_remote (s_vxlan), priv->props.group, &priv->props.group6)) { + if (priv->props.group) { + g_object_set (s_vxlan, NM_SETTING_VXLAN_REMOTE, + nm_utils_inet4_ntop (priv->props.group, NULL), + NULL); + } else { + g_object_set (s_vxlan, NM_SETTING_VXLAN_REMOTE, + nm_utils_inet6_ntop (&priv->props.group6, NULL), + NULL); + } + } + + if (!address_matches (nm_setting_vxlan_get_local (s_vxlan), priv->props.local, &priv->props.local6)) { + if (priv->props.local) { + g_object_set (s_vxlan, NM_SETTING_VXLAN_LOCAL, + nm_utils_inet4_ntop (priv->props.local, NULL), + NULL); + } else if (memcmp (&priv->props.local6, &in6addr_any, sizeof (in6addr_any))) { + g_object_set (s_vxlan, NM_SETTING_VXLAN_LOCAL, + nm_utils_inet6_ntop (&priv->props.local6, NULL), + NULL); + } + } + + if (priv->props.src_port_min != nm_setting_vxlan_get_source_port_min (s_vxlan)) { + g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_SOURCE_PORT_MIN, + priv->props.src_port_min, NULL); + } + + if (priv->props.src_port_max != nm_setting_vxlan_get_source_port_max (s_vxlan)) { + g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_SOURCE_PORT_MAX, + priv->props.src_port_max, NULL); + } + + if (priv->props.dst_port != nm_setting_vxlan_get_destination_port (s_vxlan)) { + g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_DESTINATION_PORT, + priv->props.dst_port, NULL); + } + + if (priv->props.tos != nm_setting_vxlan_get_tos (s_vxlan)) { + g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_TOS, + priv->props.tos, NULL); + } + + if (priv->props.ttl != nm_setting_vxlan_get_ttl (s_vxlan)) { + g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_TTL, + priv->props.ttl, NULL); + } + + if (priv->props.learning != nm_setting_vxlan_get_learning (s_vxlan)) { + g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_LEARNING, + priv->props.learning, NULL); + } + + if (priv->props.ageing != nm_setting_vxlan_get_ageing (s_vxlan)) { + g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_AGEING, + priv->props.ageing, NULL); + } + + if (priv->props.proxy != nm_setting_vxlan_get_proxy (s_vxlan)) { + g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_PROXY, + priv->props.proxy, NULL); + } + + if (priv->props.rsc != nm_setting_vxlan_get_rsc (s_vxlan)) { + g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_RSC, + priv->props.rsc, NULL); + } + + if (priv->props.l2miss != nm_setting_vxlan_get_l2_miss (s_vxlan)) { + g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_L2_MISS, + priv->props.l2miss, NULL); + } + + if (priv->props.l3miss != nm_setting_vxlan_get_l3_miss (s_vxlan)) { + g_object_set (G_OBJECT (s_vxlan), NM_SETTING_VXLAN_L3_MISS, + priv->props.l3miss, NULL); + } +} + +static NMActStageReturn +act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) { + NMActRequest *req; + NMConnection *connection; + NMSettingWired *s_wired; + const char *cloned_mac; + NMActStageReturn ret; + + g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + ret = NM_DEVICE_CLASS (nm_device_vxlan_parent_class)->act_stage1_prepare (device, reason); + if (ret != NM_ACT_STAGE_RETURN_SUCCESS) + return ret; + + req = nm_device_get_act_request (device); + g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + connection = nm_act_request_get_applied_connection (req); + g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE); + + s_wired = nm_connection_get_setting_wired (connection); + if (s_wired) { + /* Set device MAC address if the connection wants to change it */ + cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); + if (cloned_mac) + nm_device_set_hw_addr (device, cloned_mac, "set", LOGD_DEVICE); + } + + return NM_ACT_STAGE_RETURN_SUCCESS; } static void -constructed (GObject *object) +ip4_config_pre_commit (NMDevice *device, NMIP4Config *config) { - update_properties (NM_DEVICE (object)); + NMConnection *connection; + NMSettingWired *s_wired; + guint32 mtu; + + connection = nm_device_get_applied_connection (device); + g_assert (connection); + + s_wired = nm_connection_get_setting_wired (connection); + if (s_wired) { + mtu = nm_setting_wired_get_mtu (s_wired); + if (mtu) + nm_ip4_config_set_mtu (config, mtu, NM_IP_CONFIG_SOURCE_USER); + } +} + +/**************************************************************/ - G_OBJECT_CLASS (nm_device_vxlan_parent_class)->constructed (object); +static void +nm_device_vxlan_init (NMDeviceVxlan *self) +{ } static void @@ -157,7 +574,7 @@ get_property (GObject *object, guint prop_id, switch (prop_id) { case PROP_PARENT: parent = nm_manager_get_device_by_ifindex (nm_manager_get (), priv->props.parent_ifindex); - g_value_set_boxed (value, parent ? nm_device_get_path (parent) : "/"); + nm_utils_g_value_set_object_path (value, parent); break; case PROP_ID: g_value_set_uint (value, priv->props.id); @@ -217,6 +634,15 @@ get_property (GObject *object, guint prop_id, } static void +dispose (GObject *object) +{ + NMDeviceVxlanPrivate *priv = NM_DEVICE_VXLAN_GET_PRIVATE (object); + + g_clear_object (&priv->parent); + G_OBJECT_CLASS (nm_device_vxlan_parent_class)->dispose (object); +} + +static void nm_device_vxlan_class_init (NMDeviceVxlanClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); @@ -224,18 +650,29 @@ nm_device_vxlan_class_init (NMDeviceVxlanClass *klass) g_type_class_add_private (klass, sizeof (NMDeviceVxlanPrivate)); - object_class->constructed = constructed; + NM_DEVICE_CLASS_DECLARE_TYPES (klass, NULL, NM_LINK_TYPE_VXLAN) + object_class->get_property = get_property; + object_class->dispose = dispose; device_class->link_changed = link_changed; + device_class->realize_start_notify = realize_start_notify; + device_class->unrealize_notify = unrealize_notify; + device_class->connection_type = NM_SETTING_VXLAN_SETTING_NAME; + device_class->create_and_realize = create_and_realize; + device_class->check_connection_compatible = check_connection_compatible; + device_class->complete_connection = complete_connection; + device_class->update_connection = update_connection; + device_class->act_stage1_prepare = act_stage1_prepare; + device_class->ip4_config_pre_commit = ip4_config_pre_commit; /* properties */ g_object_class_install_property (object_class, PROP_PARENT, - g_param_spec_boxed (NM_DEVICE_VXLAN_PARENT, "", "", - DBUS_TYPE_G_OBJECT_PATH, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + g_param_spec_string (NM_DEVICE_VXLAN_PARENT, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_ID, @@ -245,15 +682,15 @@ nm_device_vxlan_class_init (NMDeviceVxlanClass *klass) G_PARAM_STATIC_STRINGS)); g_object_class_install_property - (object_class, PROP_GROUP, - g_param_spec_string (NM_DEVICE_VXLAN_GROUP, "", "", + (object_class, PROP_LOCAL, + g_param_spec_string (NM_DEVICE_VXLAN_LOCAL, "", "", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property - (object_class, PROP_LOCAL, - g_param_spec_string (NM_DEVICE_VXLAN_LOCAL, "", "", + (object_class, PROP_GROUP, + g_param_spec_string (NM_DEVICE_VXLAN_GROUP, "", "", NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); @@ -294,22 +731,22 @@ nm_device_vxlan_class_init (NMDeviceVxlanClass *klass) G_PARAM_STATIC_STRINGS)); g_object_class_install_property - (object_class, PROP_DST_PORT, - g_param_spec_uint (NM_DEVICE_VXLAN_DST_PORT, "", "", + (object_class, PROP_SRC_PORT_MIN, + g_param_spec_uint (NM_DEVICE_VXLAN_SRC_PORT_MIN, "", "", 0, 65535, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property - (object_class, PROP_SRC_PORT_MIN, - g_param_spec_uint (NM_DEVICE_VXLAN_SRC_PORT_MIN, "", "", + (object_class, PROP_SRC_PORT_MAX, + g_param_spec_uint (NM_DEVICE_VXLAN_SRC_PORT_MAX, "", "", 0, 65535, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property - (object_class, PROP_SRC_PORT_MAX, - g_param_spec_uint (NM_DEVICE_VXLAN_SRC_PORT_MAX, "", "", + (object_class, PROP_DST_PORT, + g_param_spec_uint (NM_DEVICE_VXLAN_DST_PORT, "", "", 0, 65535, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); @@ -342,9 +779,9 @@ nm_device_vxlan_class_init (NMDeviceVxlanClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), - G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_vxlan_object_info); + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_VXLAN_SKELETON, + NULL); } /*************************************************************/ @@ -353,17 +790,58 @@ nm_device_vxlan_class_init (NMDeviceVxlanClass *klass) #define NM_VXLAN_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_VXLAN_FACTORY, NMVxlanFactory)) static NMDevice * -new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error) +create_device (NMDeviceFactory *factory, + const char *iface, + const NMPlatformLink *plink, + NMConnection *connection, + gboolean *out_ignore) { return (NMDevice *) g_object_new (NM_TYPE_DEVICE_VXLAN, - NM_DEVICE_PLATFORM_DEVICE, plink, + NM_DEVICE_IFACE, iface, NM_DEVICE_TYPE_DESC, "Vxlan", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_GENERIC, + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_VXLAN, + NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_VXLAN, NULL); } +static const char * +get_connection_parent (NMDeviceFactory *factory, NMConnection *connection) +{ + NMSettingVxlan *s_vxlan; + + g_return_val_if_fail (nm_connection_is_type (connection, NM_SETTING_VXLAN_SETTING_NAME), NULL); + + s_vxlan = nm_connection_get_setting_vxlan (connection); + g_assert (s_vxlan); + + return nm_setting_vxlan_get_parent (s_vxlan); +} + +static char * +get_virtual_iface_name (NMDeviceFactory *factory, + NMConnection *connection, + const char *parent_iface) +{ + const char *ifname; + NMSettingVxlan *s_vxlan; + + g_return_val_if_fail (nm_connection_is_type (connection, NM_SETTING_VXLAN_SETTING_NAME), NULL); + + s_vxlan = nm_connection_get_setting_vxlan (connection); + g_assert (s_vxlan); + + if (nm_setting_vxlan_get_parent (s_vxlan) && !parent_iface) + return NULL; + + ifname = nm_connection_get_interface_name (connection); + return g_strdup (ifname); +} + NM_DEVICE_FACTORY_DEFINE_INTERNAL (VXLAN, Vxlan, vxlan, - NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_VXLAN), - factory_iface->new_link = new_link; + NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_VXLAN) + NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_VXLAN_SETTING_NAME), + factory_iface->create_device = create_device; + factory_iface->get_connection_parent = get_connection_parent; + factory_iface->get_virtual_iface_name = get_virtual_iface_name; ) diff --git a/src/devices/nm-device-vxlan.h b/src/devices/nm-device-vxlan.h index cc6081e6..7de04a12 100644 --- a/src/devices/nm-device-vxlan.h +++ b/src/devices/nm-device-vxlan.h @@ -21,8 +21,6 @@ #ifndef __NETWORKMANAGER_DEVICE_VXLAN_H__ #define __NETWORKMANAGER_DEVICE_VXLAN_H__ -#include <glib-object.h> - #include "nm-device-generic.h" G_BEGIN_DECLS @@ -51,8 +49,8 @@ G_BEGIN_DECLS #define NM_DEVICE_VXLAN_L2MISS "l2miss" #define NM_DEVICE_VXLAN_L3MISS "l3miss" -typedef NMDeviceGeneric NMDeviceVxlan; -typedef NMDeviceGenericClass NMDeviceVxlanClass; +typedef NMDevice NMDeviceVxlan; +typedef NMDeviceClass NMDeviceVxlanClass; GType nm_device_vxlan_get_type (void); diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index bb39ca55..93782a45 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -21,9 +21,6 @@ #include "config.h" -#include <glib.h> -#include <glib/gi18n.h> -#include <dbus/dbus.h> #include <netinet/in.h> #include <string.h> #include <unistd.h> @@ -35,9 +32,9 @@ #include <arpa/inet.h> #include <fcntl.h> #include <netlink/route/addr.h> +#include <linux/if_addr.h> -#include "gsystem-local-alloc.h" -#include "nm-glib-compat.h" +#include "nm-default.h" #include "nm-device.h" #include "nm-device-private.h" #include "NetworkManagerUtils.h" @@ -46,8 +43,6 @@ #include "nm-rdisc.h" #include "nm-lndp-rdisc.h" #include "nm-dhcp-manager.h" -#include "nm-dbus-manager.h" -#include "nm-logging.h" #include "nm-activation-request.h" #include "nm-ip4-config.h" #include "nm-ip6-config.h" @@ -56,35 +51,35 @@ #include "nm-dhcp6-config.h" #include "nm-rfkill-manager.h" #include "nm-firewall-manager.h" -#include "nm-properties-changed-signal.h" #include "nm-enum-types.h" #include "nm-settings-connection.h" #include "nm-connection-provider.h" #include "nm-auth-utils.h" -#include "nm-dbus-glib-types.h" #include "nm-dispatcher.h" #include "nm-config.h" #include "nm-dns-manager.h" #include "nm-core-internal.h" #include "nm-default-route-manager.h" #include "nm-route-manager.h" +#include "nm-lldp-listener.h" +#include "sd-ipv4ll.h" +#include "nm-audit-manager.h" #include "nm-device-logging.h" _LOG_DECLARE_SELF (NMDevice); -static void impl_device_disconnect (NMDevice *self, DBusGMethodInvocation *context); -static void impl_device_delete (NMDevice *self, DBusGMethodInvocation *context); +#include "nmdbus-device.h" + static void ip_check_ping_watch_cb (GPid pid, gint status, gpointer user_data); static gboolean ip_config_valid (NMDeviceState state); -static void nm_device_update_metered (NMDevice *self); static NMActStageReturn dhcp4_start (NMDevice *self, NMConnection *connection, NMDeviceStateReason *reason); static gboolean dhcp6_start (NMDevice *self, gboolean wait_for_ll, NMDeviceStateReason *reason); +static void nm_device_start_ip_check (NMDevice *self); +static void realize_start_setup (NMDevice *self, const NMPlatformLink *plink); -#include "nm-device-glue.h" - -G_DEFINE_ABSTRACT_TYPE (NMDevice, nm_device, G_TYPE_OBJECT) +G_DEFINE_ABSTRACT_TYPE (NMDevice, nm_device, NM_TYPE_EXPORTED_OBJECT) -#define NM_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE, NMDevicePrivate)) +#define NM_DEVICE_GET_PRIVATE(o) ((o)->priv) enum { STATE_CHANGED, @@ -95,14 +90,12 @@ enum { REMOVED, RECHECK_AUTO_ACTIVATE, RECHECK_ASSUME, - LINK_INITIALIZED, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL] = { 0 }; enum { PROP_0, - PROP_PLATFORM_DEVICE, PROP_UDI, PROP_IFACE, PROP_IP_IFACE, @@ -121,9 +114,11 @@ enum { PROP_STATE_REASON, PROP_ACTIVE_CONNECTION, PROP_DEVICE_TYPE, + PROP_LINK_TYPE, PROP_MANAGED, PROP_AUTOCONNECT, PROP_FIRMWARE_MISSING, + PROP_NM_PLUGIN_MISSING, PROP_TYPE_DESC, PROP_RFKILL_TYPE, PROP_IFINDEX, @@ -134,15 +129,27 @@ enum { PROP_HW_ADDRESS, PROP_HAS_PENDING_ACTION, PROP_METERED, + PROP_LLDP_NEIGHBORS, + PROP_REAL, + PROP_SLAVES, LAST_PROP }; +#define DEFAULT_AUTOCONNECT TRUE + /***********************************************************/ #define PENDING_ACTION_DHCP4 "dhcp4" #define PENDING_ACTION_DHCP6 "dhcp6" #define PENDING_ACTION_AUTOCONF6 "autoconf6" +typedef void (*ActivationHandleFunc) (NMDevice *self); + +typedef struct { + ActivationHandleFunc func; + guint id; +} ActivationHandleData; + typedef enum { CLEANUP_TYPE_DECONFIGURE, CLEANUP_TYPE_KEEP, @@ -165,13 +172,13 @@ typedef struct { typedef struct { NMDevice *slave; - gboolean enslaved; + gboolean slave_is_enslaved; gboolean configure; - guint watch_id; + gulong watch_id; } SlaveInfo; typedef struct { - guint log_domain; + NMLogDomain log_domain; guint timeout; guint watch; GPid pid; @@ -186,7 +193,7 @@ typedef struct { int ifindex; } DeleteOnDeactivateData; -typedef struct { +typedef struct _NMDevicePrivate { gboolean in_state_changed; gboolean initialized; gboolean platform_link_initialized; @@ -200,22 +207,25 @@ typedef struct { guint queued_ip4_config_id; guint queued_ip6_config_id; GSList *pending_actions; + GSList *dad6_failed_addrs; char * udi; - char * path; char * iface; /* may change, could be renamed by user */ int ifindex; + gboolean real; char * ip_iface; int ip_ifindex; NMDeviceType type; char * type_desc; char * type_description; + NMLinkType link_type; NMDeviceCapabilities capabilities; char * driver; char * driver_version; char * firmware_version; RfKillType rfkill_type; gboolean firmware_missing; + gboolean nm_plugin_missing; GHashTable * available_connections; char * hw_addr; guint hw_addr_len; @@ -224,6 +234,7 @@ typedef struct { char * physical_port_id; guint dev_id; + gboolean managed_touched_by_user; NMUnmanagedFlags unmanaged_flags; gboolean is_nm_owned; /* whether the device is a device owned and created by NM */ DeleteOnDeactivateData *delete_on_deactivate_data; /* data for scheduled cleanup when deleting link (g_idle_add) */ @@ -235,13 +246,11 @@ typedef struct { NMActRequest * queued_act_request; gboolean queued_act_request_is_waiting_for_carrier; NMActRequest * act_request; - guint act_source_id; - gpointer act_source_func; - guint act_source6_id; - gpointer act_source6_func; + ActivationHandleData act_handle4; /* for layer2 and IPv4. */ + ActivationHandleData act_handle6; guint recheck_assume_id; struct { - guint call_id; + guint call_id; NMDeviceStateReason available_reason; NMDeviceStateReason unavailable_reason; } recheck_available; @@ -272,6 +281,7 @@ typedef struct { NMIP4Config * dev_ip4_config; /* Config from DHCP, PPP, LLv4, etc */ NMIP4Config * ext_ip4_config; /* Stuff added outside NM */ NMIP4Config * wwan_ip4_config; /* WWAN configuration */ + GSList * vpn4_configs; /* VPNs which use this device */ struct { gboolean v4_has; gboolean v4_is_assumed; @@ -289,7 +299,6 @@ typedef struct { gulong dhcp4_state_sigid; NMDhcp4Config * dhcp4_config; guint dhcp4_restart_id; - NMIP4Config * vpn4_config; /* routes added by a VPN which uses this device */ guint arp_round2_id; PingInfo gw_ping; @@ -299,20 +308,20 @@ typedef struct { gulong dnsmasq_state_id; /* Firewall */ - NMFirewallPendingCall fw_call; + gboolean fw_ready; + NMFirewallManagerCallId fw_call; - /* avahi-autoipd stuff */ - GPid aipd_pid; - guint aipd_watch; - guint aipd_timeout; + /* IPv4LL stuff */ + sd_ipv4ll * ipv4ll; + guint ipv4ll_timeout; /* IP6 configuration info */ NMIP6Config * ip6_config; IpState ip6_state; NMIP6Config * con_ip6_config; /* config from the setting */ - NMIP6Config * vpn6_config; /* routes added by a VPN which uses this device */ NMIP6Config * wwan_ip6_config; NMIP6Config * ext_ip6_config; /* Stuff added outside NM */ + GSList * vpn6_configs; /* VPNs which use this device */ gboolean nm_ipv6ll; /* TRUE if NM handles the device's IPv6LL address */ guint32 ip6_mtu; @@ -324,6 +333,7 @@ typedef struct { NMIP6Config * ac_ip6_config; guint linklocal6_timeout_id; + guint8 linklocal6_dad_counter; GHashTable * ip6_saved_properties; @@ -342,9 +352,9 @@ typedef struct { /* master interface for bridge/bond/team slave */ NMDevice * master; - gboolean enslaved; + gboolean is_enslaved; gboolean master_ready_handled; - guint master_ready_id; + gulong master_ready_id; /* slave management */ gboolean is_master; @@ -353,6 +363,9 @@ typedef struct { NMMetered metered; NMConnectionProvider *con_provider; + NMLldpListener *lldp_listener; + + guint check_delete_unrealized_id; } NMDevicePrivate; static gboolean nm_device_set_ip4_config (NMDevice *self, @@ -372,7 +385,7 @@ static gboolean nm_device_set_ip6_config (NMDevice *self, gboolean routes_full_sync, NMDeviceStateReason *reason); -static gboolean nm_device_master_add_slave (NMDevice *self, NMDevice *slave, gboolean configure); +static void nm_device_master_add_slave (NMDevice *self, NMDevice *slave, gboolean configure); static void nm_device_slave_notify_enslave (NMDevice *self, gboolean success); static void nm_device_slave_notify_release (NMDevice *self, NMDeviceStateReason reason); @@ -384,12 +397,20 @@ static void _carrier_wait_check_queued_act_request (NMDevice *self); static gboolean nm_device_get_default_unmanaged (NMDevice *self); +static const char *_activation_func_to_string (ActivationHandleFunc func); +static void activation_source_handle_cb (NMDevice *self, int family); + static void _set_state_full (NMDevice *self, NMDeviceState state, NMDeviceStateReason reason, gboolean quitting); -static void nm_device_update_hw_address (NMDevice *self); +static gboolean queued_ip4_config_change (gpointer user_data); +static gboolean queued_ip6_config_change (gpointer user_data); + +static void _set_unmanaged_flags (NMDevice *self, + NMUnmanagedFlags flags, + gboolean unmanaged); /***********************************************************/ @@ -425,7 +446,7 @@ state_to_string (NMDeviceState state) return queued_state_to_string (state) + strlen (QUEUED_PREFIX); } -static const char *reason_table[] = { +NM_UTILS_STRING_LOOKUP_TABLE_DEFINE_STATIC (_reason_to_string, NMDeviceStateReason, NULL, [NM_DEVICE_STATE_REASON_UNKNOWN] = "unknown", [NM_DEVICE_STATE_REASON_NONE] = "none", [NM_DEVICE_STATE_REASON_NOW_MANAGED] = "managed", @@ -489,15 +510,10 @@ static const char *reason_table[] = { [NM_DEVICE_STATE_REASON_NEW_ACTIVATION] = "new-activation", [NM_DEVICE_STATE_REASON_PARENT_CHANGED] = "parent-changed", [NM_DEVICE_STATE_REASON_PARENT_MANAGED_CHANGED] = "parent-managed-changed", -}; +); -static const char * -reason_to_string (NMDeviceStateReason reason) -{ - if ((gsize) reason < G_N_ELEMENTS (reason_table)) - return reason_table[reason]; - return reason_table[NM_DEVICE_STATE_REASON_UNKNOWN]; -} +#define reason_to_string(reason) \ + NM_UTILS_STRING_LOOKUP_TABLE (_reason_to_string, reason) /***********************************************************/ @@ -521,30 +537,6 @@ nm_device_has_capability (NMDevice *self, NMDeviceCapabilities caps) /***********************************************************/ -void -nm_device_dbus_export (NMDevice *self) -{ - static guint32 devcount = 0; - NMDevicePrivate *priv; - - g_return_if_fail (NM_IS_DEVICE (self)); - - priv = NM_DEVICE_GET_PRIVATE (self); - g_return_if_fail (priv->path == NULL); - - priv->path = g_strdup_printf ("/org/freedesktop/NetworkManager/Devices/%d", devcount++); - _LOGD (LOGD_DEVICE, "exported as %s", priv->path); - nm_dbus_manager_register_object (nm_dbus_manager_get (), priv->path, self); -} - -const char * -nm_device_get_path (NMDevice *self) -{ - g_return_val_if_fail (self != NULL, NULL); - - return NM_DEVICE_GET_PRIVATE (self)->path; -} - const char * nm_device_get_udi (NMDevice *self) { @@ -564,17 +556,40 @@ nm_device_get_iface (NMDevice *self) int nm_device_get_ifindex (NMDevice *self) { - g_return_val_if_fail (self != NULL, 0); + g_return_val_if_fail (NM_IS_DEVICE (self), 0); return NM_DEVICE_GET_PRIVATE (self)->ifindex; } +/** + * nm_device_is_software: + * @self: the #NMDevice + * + * Indicates if the device is a software-based virtual device without + * backing hardware, which can be added and removed programmatically. + * + * Returns: %TRUE if the device is a software-based device + */ gboolean nm_device_is_software (NMDevice *self) { return NM_FLAGS_HAS (NM_DEVICE_GET_PRIVATE (self)->capabilities, NM_DEVICE_CAP_IS_SOFTWARE); } +/** + * nm_device_is_real: + * @self: the #NMDevice + * + * Returns: %TRUE if the device exists, %FALSE if the device is a placeholder + */ +gboolean +nm_device_is_real (NMDevice *self) +{ + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + + return NM_DEVICE_GET_PRIVATE (self)->real; +} + const char * nm_device_get_ip_iface (NMDevice *self) { @@ -701,13 +716,21 @@ nm_device_get_device_type (NMDevice *self) return NM_DEVICE_GET_PRIVATE (self)->type; } +NMLinkType +nm_device_get_link_type (NMDevice *self) +{ + g_return_val_if_fail (NM_IS_DEVICE (self), NM_LINK_TYPE_UNKNOWN); + + return NM_DEVICE_GET_PRIVATE (self)->link_type; +} + /** * nm_device_get_metered: * @setting: the #NMDevice * * Returns: the #NMDevice:metered property of the device. * - * Since: 1.0.6 + * Since: 1.2 **/ NMMetered nm_device_get_metered (NMDevice *self) @@ -762,12 +785,20 @@ nm_device_get_priority (NMDevice *self) return 350; case NM_DEVICE_TYPE_VLAN: return 400; + case NM_DEVICE_TYPE_MACVLAN: + return 410; case NM_DEVICE_TYPE_BRIDGE: return 425; + case NM_DEVICE_TYPE_TUN: + return 450; + case NM_DEVICE_TYPE_VXLAN: + return 500; case NM_DEVICE_TYPE_WIFI: return 600; case NM_DEVICE_TYPE_OLPC_MESH: return 650; + case NM_DEVICE_TYPE_IP_TUNNEL: + return 675; case NM_DEVICE_TYPE_MODEM: return 700; case NM_DEVICE_TYPE_BT: @@ -795,7 +826,7 @@ _get_ipx_route_metric (NMDevice *self, g_return_val_if_fail (NM_IS_DEVICE (self), G_MAXUINT32); - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); if (connection) { s_ip = is_v4 ? nm_connection_get_setting_ip4_config (connection) @@ -923,12 +954,31 @@ nm_device_get_act_request (NMDevice *self) return NM_DEVICE_GET_PRIVATE (self)->act_request; } +NMSettingsConnection * +nm_device_get_settings_connection (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + return priv->act_request ? nm_act_request_get_settings_connection (priv->act_request) : NULL; +} + NMConnection * -nm_device_get_connection (NMDevice *self) +nm_device_get_applied_connection (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - return priv->act_request ? nm_act_request_get_connection (priv->act_request) : NULL; + return priv->act_request ? nm_act_request_get_applied_connection (priv->act_request) : NULL; +} + +gboolean +nm_device_has_unmodified_applied_connection (NMDevice *self, NMSettingCompareFlags compare_flags) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (!priv->act_request) + return FALSE; + + return nm_active_connection_has_unmodified_applied_connection ((NMActiveConnection *) priv->act_request, compare_flags); } RfKillType @@ -951,13 +1001,13 @@ static gboolean nm_device_uses_generated_assumed_connection (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMConnection *connection; + NMSettingsConnection *connection; if ( priv->act_request && nm_active_connection_get_assumed (NM_ACTIVE_CONNECTION (priv->act_request))) { - connection = nm_act_request_get_connection (priv->act_request); + connection = nm_act_request_get_settings_connection (priv->act_request); if ( connection - && nm_settings_connection_get_nm_generated_assumed (NM_SETTINGS_CONNECTION (connection))) + && nm_settings_connection_get_nm_generated_assumed (connection)) return TRUE; } return FALSE; @@ -989,17 +1039,8 @@ find_slave_info (NMDevice *self, NMDevice *slave) return NULL; } -static void -free_slave_info (SlaveInfo *info) -{ - g_signal_handler_disconnect (info->slave, info->watch_id); - g_clear_object (&info->slave); - memset (info, 0, sizeof (*info)); - g_free (info); -} - /** - * nm_device_enslave_slave: + * nm_device_master_enslave_slave: * @self: the master device * @slave: the slave device to enslave * @connection: (allow-none): the slave device's connection @@ -1011,7 +1052,7 @@ free_slave_info (SlaveInfo *info) * other devices. */ static gboolean -nm_device_enslave_slave (NMDevice *self, NMDevice *slave, NMConnection *connection) +nm_device_master_enslave_slave (NMDevice *self, NMDevice *slave, NMConnection *connection) { SlaveInfo *info; gboolean success = FALSE; @@ -1025,7 +1066,7 @@ nm_device_enslave_slave (NMDevice *self, NMDevice *slave, NMConnection *connecti if (!info) return FALSE; - if (info->enslaved) + if (info->slave_is_enslaved) success = TRUE; else { configure = (info->configure && connection != NULL); @@ -1033,7 +1074,7 @@ nm_device_enslave_slave (NMDevice *self, NMDevice *slave, NMConnection *connecti g_return_val_if_fail (nm_device_get_state (slave) >= NM_DEVICE_STATE_DISCONNECTED, FALSE); success = NM_DEVICE_GET_CLASS (self)->enslave_slave (self, slave, connection, configure); - info->enslaved = success; + info->slave_is_enslaved = success; } nm_device_slave_notify_enslave (info->slave, success); @@ -1059,7 +1100,7 @@ nm_device_enslave_slave (NMDevice *self, NMDevice *slave, NMConnection *connecti } /** - * nm_device_release_one_slave: + * nm_device_master_release_one_slave: * @self: the master device * @slave: the slave device to release * @configure: whether @self needs to actually release @slave @@ -1068,49 +1109,55 @@ nm_device_enslave_slave (NMDevice *self, NMDevice *slave, NMConnection *connecti * If @self is capable of enslaving other devices (ie it's a bridge, bond, team, * etc) then this function releases the previously enslaved @slave and/or * updates the state of @self and @slave to reflect its release. - * - * Returns: %TRUE on success, %FALSE on failure, if this device cannot enslave - * other devices, or if @slave was never enslaved. */ -static gboolean -nm_device_release_one_slave (NMDevice *self, NMDevice *slave, gboolean configure, NMDeviceStateReason reason) +static void +nm_device_master_release_one_slave (NMDevice *self, NMDevice *slave, gboolean configure, NMDeviceStateReason reason) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMDevicePrivate *priv; + NMDevicePrivate *slave_priv; SlaveInfo *info; - gboolean success = FALSE; + gs_unref_object NMDevice *self_free = NULL; - g_return_val_if_fail (slave != NULL, FALSE); - g_return_val_if_fail (NM_DEVICE_GET_CLASS (self)->release_slave != NULL, FALSE); + g_return_if_fail (NM_DEVICE (self)); + g_return_if_fail (NM_DEVICE (slave)); + g_return_if_fail (NM_DEVICE_GET_CLASS (self)->release_slave != NULL); info = find_slave_info (self, slave); + + _LOGt (LOGD_CORE, "master: release one slave %p/%s%s", slave, nm_device_get_iface (slave), + !info ? " (not registered)" : ""); + if (!info) - return FALSE; - priv->slaves = g_slist_remove (priv->slaves, info); + g_return_if_reached (); - if (info->enslaved) { - success = NM_DEVICE_GET_CLASS (self)->release_slave (self, slave, configure); - /* The release_slave() implementation logs success/failure (in the - * correct device-specific log domain), so we don't have to do anything. - */ - } + priv = NM_DEVICE_GET_PRIVATE (self); + slave_priv = NM_DEVICE_GET_PRIVATE (slave); - if (!configure) { - g_warn_if_fail (reason == NM_DEVICE_STATE_REASON_NONE || reason == NM_DEVICE_STATE_REASON_REMOVED); - reason = NM_DEVICE_STATE_REASON_NONE; - } else if (reason == NM_DEVICE_STATE_REASON_NONE) { - g_warn_if_reached (); - reason = NM_DEVICE_STATE_REASON_UNKNOWN; - } - nm_device_slave_notify_release (info->slave, reason); + g_return_if_fail (self == slave_priv->master); + nm_assert (slave == info->slave); + + /* first, let subclasses handle the release ... */ + if (info->slave_is_enslaved) + NM_DEVICE_GET_CLASS (self)->release_slave (self, slave, configure); + + /* raise notifications about the release, including clearing is_enslaved. */ + nm_device_slave_notify_release (slave, reason); + + /* keep both alive until the end of the function. + * Transfers ownership from slave_priv->master. */ + self_free = self; + + priv->slaves = g_slist_remove (priv->slaves, info); + slave_priv->master = NULL; - free_slave_info (info); + g_signal_handler_disconnect (slave, info->watch_id); + g_object_unref (slave); + g_slice_free (SlaveInfo, info); /* Ensure the device's hardware address is up-to-date; it often changes * when slaves change. */ nm_device_update_hw_address (self); - - return success; } /** @@ -1123,8 +1170,7 @@ nm_device_release_one_slave (NMDevice *self, NMDevice *slave, gboolean configure static gboolean can_unmanaged_external_down (NMDevice *self) { - return nm_device_is_software (self) - && !nm_device_get_is_nm_owned (self); + return nm_device_is_software (self) && !NM_DEVICE_GET_PRIVATE (self)->is_nm_owned; } /** @@ -1138,7 +1184,6 @@ void nm_device_finish_init (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - gboolean platform_unmanaged = FALSE; g_assert (priv->initialized == FALSE); @@ -1147,29 +1192,29 @@ nm_device_finish_init (NMDevice *self) && priv->ifindex > 0 && ( !priv->up || !priv->platform_link_initialized)) - nm_device_set_initial_unmanaged_flag (self, NM_UNMANAGED_EXTERNAL_DOWN, TRUE); + nm_device_set_unmanaged_flags_initial (self, NM_UNMANAGED_EXTERNAL_DOWN, TRUE); if (priv->master) - nm_device_enslave_slave (priv->master, self, NULL); + nm_device_master_enslave_slave (priv->master, self, NULL); if (priv->ifindex > 0) { if (priv->ifindex == 1) { - /* keep 'lo' as default-unmanaged. */ - - /* FIXME: either find a better way to unmange 'lo' that cannot be changed - * by user configuration (NM_UNMANGED_LOOPBACK?) or fix managing 'lo'. - * Currently it can happen that NM deletes 127.0.0.1 address. */ - nm_device_set_initial_unmanaged_flag (self, NM_UNMANAGED_DEFAULT, TRUE); + /* Unmanaged the loopback device with an explicit NM_UNMANAGED_LOOPBACK flag. + * Later we might want to manage 'lo' too. Currently that doesn't work because + * NetworkManager might down the interface or remove the 127.0.0.1 address. */ + nm_device_set_unmanaged_flags_initial (self, NM_UNMANAGED_LOOPBACK, TRUE); } else if (priv->platform_link_initialized || (priv->is_nm_owned && nm_device_is_software (self))) { + gboolean platform_unmanaged = FALSE; + if (nm_platform_link_get_unmanaged (NM_PLATFORM_GET, priv->ifindex, &platform_unmanaged)) - nm_device_set_initial_unmanaged_flag (self, NM_UNMANAGED_DEFAULT, platform_unmanaged); + nm_device_set_unmanaged_flags_initial (self, NM_UNMANAGED_DEFAULT, platform_unmanaged); } else { /* Hardware and externally-created software links stay unmanaged * until they are fully initialized by the platform. NM created * links must be available for activation immediately and thus * do not get the PLATFORM_INIT unmanaged flag set. */ - nm_device_set_initial_unmanaged_flag (self, NM_UNMANAGED_PLATFORM_INIT, TRUE); + nm_device_set_unmanaged_flags_initial (self, NM_UNMANAGED_PLATFORM_INIT, TRUE); } } @@ -1180,6 +1225,9 @@ static void update_dynamic_ip_setup (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + GError *error; + gconstpointer addr; + size_t addr_length; g_hash_table_remove_all (priv->ip6_saved_properties); @@ -1205,6 +1253,18 @@ update_dynamic_ip_setup (NMDevice *self) if (priv->dnsmasq_manager) { /* FIXME: todo */ } + + if (priv->lldp_listener && nm_lldp_listener_is_running (priv->lldp_listener)) { + nm_lldp_listener_stop (priv->lldp_listener); + addr = nm_platform_link_get_address (NM_PLATFORM_GET, priv->ifindex, &addr_length); + + if (!nm_lldp_listener_start (priv->lldp_listener, nm_device_get_ifindex (self), + nm_device_get_iface (self), addr, addr_length, &error)) { + _LOGD (LOGD_DEVICE, "LLDP listener %p could not be restarted: %s", + priv->lldp_listener, error->message); + g_clear_error (&error); + } + } } static void @@ -1342,23 +1402,40 @@ nm_device_set_carrier (NMDevice *self, gboolean carrier) } static void -device_set_master (NMDevice *self, int ifindex) +device_recheck_slave_status (NMDevice *self, const NMPlatformLink *plink) { - NMDevice *master; NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - master = nm_manager_get_device_by_ifindex (nm_manager_get (), ifindex); - if (master && NM_DEVICE_GET_CLASS (master)->enslave_slave) { - g_clear_object (&priv->master); - priv->master = g_object_ref (master); - nm_device_master_add_slave (master, self, FALSE); - } else if (master) { - _LOGI (LOGD_DEVICE, "enslaved to non-master-type device %s; ignoring", - nm_device_get_iface (master)); - } else { - _LOGW (LOGD_DEVICE, "enslaved to unknown device %d %s", - ifindex, - nm_platform_link_get_name (NM_PLATFORM_GET, ifindex)); + g_return_if_fail (plink); + + if (plink->master <= 0) + return; + + if (priv->master) { + if ( plink->master > 0 + && plink->master == nm_device_get_ifindex (priv->master)) { + /* call add-slave again. We expect @self already to be added to + * the master, but this also triggers a recheck-assume. */ + nm_device_master_add_slave (priv->master, self, FALSE); + return; + } + + nm_device_master_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); + } + if (plink->master > 0) { + NMDevice *master; + + master = nm_manager_get_device_by_ifindex (nm_manager_get (), plink->master); + if (master && NM_DEVICE_GET_CLASS (master)->enslave_slave) + nm_device_master_add_slave (master, self, FALSE); + else if (master) { + _LOGI (LOGD_DEVICE, "enslaved to non-master-type device %s; ignoring", + nm_device_get_iface (master)); + } else { + _LOGW (LOGD_DEVICE, "enslaved to unknown device %d %s", + plink->master, + nm_platform_link_get_name (NM_PLATFORM_GET, plink->master)); + } } } @@ -1369,12 +1446,11 @@ device_link_changed (NMDevice *self) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMUtilsIPv6IfaceId token_iid; gboolean ip_ifname_changed = FALSE; - gboolean platform_unmanaged = FALSE; const char *udi; NMPlatformLink info; const NMPlatformLink *pllink; int ifindex; - gboolean emit_link_initialized = FALSE; + gboolean just_initialized = FALSE; gboolean was_up; priv->device_link_changed_id = 0; @@ -1407,6 +1483,12 @@ device_link_changed (NMDevice *self) g_object_notify (G_OBJECT (self), NM_DEVICE_MTU); } + if (info.driver && g_strcmp0 (priv->driver, info.driver) != 0) { + g_free (priv->driver); + priv->driver = g_strdup (info.driver); + g_object_notify (G_OBJECT (self), NM_DEVICE_DRIVER); + } + if (info.name[0] && strcmp (priv->iface, info.name) != 0) { _LOGI (LOGD_DEVICE, "interface index %d renamed iface from '%s' to '%s'", priv->ifindex, priv->iface, info.name); @@ -1429,15 +1511,6 @@ device_link_changed (NMDevice *self) nm_device_emit_recheck_auto_activate (self); } - /* Update slave status for external changes */ - if (priv->enslaved && info.master != nm_device_get_ifindex (priv->master)) - nm_device_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_NONE); - if (info.master && !priv->enslaved) { - device_set_master (self, info.master); - if (priv->master) - nm_device_enslave_slave (priv->master, self, NULL); - } - if (priv->rdisc && nm_platform_link_get_ipv6_token (NM_PLATFORM_GET, priv->ifindex, &token_iid)) { _LOGD (LOGD_DEVICE, "IPv6 tokenized identifier present on device %s", priv->iface); if (nm_rdisc_set_iid (priv->rdisc, token_iid)) @@ -1452,33 +1525,36 @@ device_link_changed (NMDevice *self) update_dynamic_ip_setup (self); if (priv->ifindex > 0 && !priv->platform_link_initialized && info.initialized) { + gboolean platform_unmanaged = FALSE; + priv->platform_link_initialized = TRUE; if (nm_platform_link_get_unmanaged (NM_PLATFORM_GET, priv->ifindex, &platform_unmanaged)) { - nm_device_set_unmanaged (self, - NM_UNMANAGED_DEFAULT, - platform_unmanaged, - NM_DEVICE_STATE_REASON_USER_REQUESTED); + nm_device_set_unmanaged_flags (self, + NM_UNMANAGED_DEFAULT, + platform_unmanaged, + NM_DEVICE_STATE_REASON_USER_REQUESTED); } - nm_device_set_unmanaged (self, - NM_UNMANAGED_PLATFORM_INIT, - FALSE, - NM_DEVICE_STATE_REASON_NOW_MANAGED); + nm_device_set_unmanaged_flags (self, + NM_UNMANAGED_PLATFORM_INIT, + FALSE, + NM_DEVICE_STATE_REASON_NOW_MANAGED); - emit_link_initialized = TRUE; + just_initialized = TRUE; } was_up = priv->up; priv->up = NM_FLAGS_HAS (info.flags, IFF_UP); if ( priv->platform_link_initialized - && (emit_link_initialized || priv->up != was_up)) { + && ( just_initialized + || priv->up != was_up)) { /* Manage externally-created software interfaces only when they are IFF_UP */ g_assert (priv->ifindex > 0); if (NM_DEVICE_GET_CLASS (self)->can_unmanaged_external_down (self)) { - gboolean external_down = nm_device_get_unmanaged_flag (self, NM_UNMANAGED_EXTERNAL_DOWN); + gboolean external_down = !!nm_device_get_unmanaged_flags (self, NM_UNMANAGED_EXTERNAL_DOWN); if (external_down && NM_FLAGS_HAS (info.flags, IFF_UP)) { if (nm_device_get_state (self) < NM_DEVICE_STATE_DISCONNECTED) { @@ -1492,32 +1568,30 @@ device_link_changed (NMDevice *self) * the device before assumption occurs, pass * NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED as the reason. */ - nm_device_set_unmanaged (self, - NM_UNMANAGED_EXTERNAL_DOWN, - FALSE, - NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); + nm_device_set_unmanaged_flags (self, + NM_UNMANAGED_EXTERNAL_DOWN, + FALSE, + NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); } else { /* Don't trigger a state change; if the device is in a * state higher than UNAVAILABLE, it is already IFF_UP * or an explicit activation request was received. */ - priv->unmanaged_flags &= ~NM_UNMANAGED_EXTERNAL_DOWN; + _set_unmanaged_flags (self, NM_UNMANAGED_EXTERNAL_DOWN, FALSE); } } else if (!external_down && !NM_FLAGS_HAS (info.flags, IFF_UP) && nm_device_get_state (self) <= NM_DEVICE_STATE_DISCONNECTED) { /* If the device is already disconnected and is set !IFF_UP, * unmanage it. */ - nm_device_set_unmanaged (self, - NM_UNMANAGED_EXTERNAL_DOWN, - TRUE, - NM_DEVICE_STATE_REASON_USER_REQUESTED); + nm_device_set_unmanaged_flags (self, + NM_UNMANAGED_EXTERNAL_DOWN, + TRUE, + NM_DEVICE_STATE_REASON_USER_REQUESTED); } } } - if (emit_link_initialized) - g_signal_emit (self, signals[LINK_INITIALIZED], 0); - + device_recheck_slave_status (self, &info); return G_SOURCE_REMOVE; } @@ -1526,12 +1600,13 @@ device_ip_link_changed (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); const NMPlatformLink *pllink; - int ip_ifindex; priv->device_ip_link_changed_id = 0; - ip_ifindex = nm_device_get_ip_ifindex (self); - pllink = nm_platform_link_get (NM_PLATFORM_GET, ip_ifindex); + if (!priv->ip_ifindex) + return G_SOURCE_REMOVE; + + pllink = nm_platform_link_get (NM_PLATFORM_GET, priv->ip_ifindex); if (!pllink) return G_SOURCE_REMOVE; @@ -1554,7 +1629,6 @@ link_changed_cb (NMPlatform *platform, int ifindex, NMPlatformLink *info, NMPlatformSignalChangeType change_type, - NMPlatformReason reason, NMDevice *self) { NMDevicePrivate *priv; @@ -1564,12 +1638,6 @@ link_changed_cb (NMPlatform *platform, priv = NM_DEVICE_GET_PRIVATE (self); - /* We don't filter by 'reason' because we are interested in *all* link - * changes. For example a call to nm_platform_link_set_up() may result - * in an internal carrier change (i.e. we ask the kernel to set IFF_UP - * and it results in also setting IFF_LOWER_UP. - */ - if (ifindex == nm_device_get_ifindex (self)) { if (!priv->device_link_changed_id) { priv->device_link_changed_id = g_idle_add ((GSourceFunc) device_link_changed, self); @@ -1592,6 +1660,165 @@ link_changed (NMDevice *self, NMPlatformLink *info) nm_device_set_carrier (self, info->connected); } +static gboolean +link_type_compatible (NMDevice *self, + NMLinkType link_type, + gboolean *out_compatible, + GError **error) +{ + NMDeviceClass *klass; + NMLinkType device_type; + guint i = 0; + + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + + klass = NM_DEVICE_GET_CLASS (self); + + if (!klass->link_types) { + NM_SET_OUT (out_compatible, FALSE); + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "Device does not support platform links"); + return FALSE; + } + + device_type = self->priv->link_type; + if (device_type > NM_LINK_TYPE_UNKNOWN && device_type != link_type) { + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "Needed link type 0x%x does not match the platform link type 0x%X", + device_type, link_type); + return FALSE; + } + + for (i = 0; klass->link_types[i] > NM_LINK_TYPE_UNKNOWN; i++) { + if (klass->link_types[i] == link_type) + return TRUE; + if (klass->link_types[i] == NM_LINK_TYPE_ANY) + return TRUE; + } + + NM_SET_OUT (out_compatible, FALSE); + g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "Device does not support platform link type 0x%X", + link_type); + return FALSE; +} + +/** + * nm_device_realize_start(): + * @self: the #NMDevice + * @plink: an existing platform link or %NULL + * @out_compatible: %TRUE on return if @self is compatible with @plink + * @error: location to store error, or %NULL + * + * Initializes and sets up the device using existing backing resources. Before + * the device is ready for use nm_device_realize_finish() must be called. + * @out_compatible will only be set if @plink is not %NULL, and + * + * Important: if nm_device_realize_start() returns %TRUE, the caller MUST + * also call nm_device_realize_finish() to balance g_object_freeze_notify(). + * + * Returns: %TRUE on success, %FALSE on error + */ +gboolean +nm_device_realize_start (NMDevice *self, + const NMPlatformLink *plink, + gboolean *out_compatible, + GError **error) +{ + NM_SET_OUT (out_compatible, TRUE); + + if (plink) { + if (g_strcmp0 (nm_device_get_iface (self), plink->name) != 0) { + NM_SET_OUT (out_compatible, FALSE); + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "Device interface name does not match platform link"); + return FALSE; + } + + if (!link_type_compatible (self, plink->type, out_compatible, error)) + return FALSE; + } + + realize_start_setup (self, plink); + + return TRUE; +} + +/** + * nm_device_create_and_realize(): + * @self: the #NMDevice + * @connection: the #NMConnection being activated + * @parent: the parent #NMDevice if any + * @error: location to store error, or %NULL + * + * Creates any backing resources needed to realize the device to proceed + * with activating @connection. + * + * Returns: %TRUE on success, %FALSE on error + */ +gboolean +nm_device_create_and_realize (NMDevice *self, + NMConnection *connection, + NMDevice *parent, + GError **error) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMPlatformLink plink_copy; + const NMPlatformLink *plink = NULL; + + /* Must be set before device is realized */ + priv->is_nm_owned = !nm_platform_link_get_by_ifname (NM_PLATFORM_GET, priv->iface); + + _LOGD (LOGD_DEVICE, "create (is %snm-owned)", priv->is_nm_owned ? "" : "not "); + + /* Create any resources the device needs */ + if (NM_DEVICE_GET_CLASS (self)->create_and_realize) { + if (!NM_DEVICE_GET_CLASS (self)->create_and_realize (self, connection, parent, &plink, error)) + return FALSE; + plink_copy = *plink; + plink = &plink_copy; + } + + realize_start_setup (self, plink); + nm_device_realize_finish (self, plink); + + g_return_val_if_fail (nm_device_check_connection_compatible (self, connection), TRUE); + return TRUE; +} + +static void +update_device_from_platform_link (NMDevice *self, const NMPlatformLink *plink) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + const char *udi; + + g_return_if_fail (plink != NULL); + + udi = nm_platform_link_get_udi (NM_PLATFORM_GET, plink->ifindex); + if (udi && !g_strcmp0 (udi, priv->udi)) { + g_free (priv->udi); + priv->udi = g_strdup (udi); + g_object_notify (G_OBJECT (self), NM_DEVICE_UDI); + } + + if (!g_strcmp0 (plink->name, priv->iface)) { + g_free (priv->iface); + priv->iface = g_strdup (plink->name); + g_object_notify (G_OBJECT (self), NM_DEVICE_IFACE); + } + + priv->ifindex = plink->ifindex; + g_object_notify (G_OBJECT (self), NM_DEVICE_IFINDEX); + + priv->up = NM_FLAGS_HAS (plink->flags, IFF_UP); + if (plink->driver && g_strcmp0 (plink->driver, priv->driver) != 0) { + g_free (priv->driver); + priv->driver = g_strdup (plink->driver); + g_object_notify (G_OBJECT (self), NM_DEVICE_DRIVER); + } + priv->platform_link_initialized = plink->initialized; +} + static void config_changed_update_ignore_carrier (NMConfig *config, NMConfigData *config_data, @@ -1615,6 +1842,317 @@ check_carrier (NMDevice *self) nm_device_set_carrier (self, nm_platform_link_is_connected (NM_PLATFORM_GET, ifindex)); } +static void +realize_start_notify (NMDevice *self, const NMPlatformLink *plink) +{ + /* Stub implementation for realize_start_notify(). It does nothing, + * but allows derived classes to uniformly invoke the parent + * implementation. */ +} + +/** + * realize_start_setup(): + * @self: the #NMDevice + * @plink: the #NMPlatformLink if backed by a kernel netdevice + * + * Update the device from backing resource properties (like hardware + * addresses, carrier states, driver/firmware info, etc). This function + * should only change properties for this device, and should not perform + * any tasks that affect other interfaces (like master/slave or parent/child + * stuff). + */ +static void +realize_start_setup (NMDevice *self, const NMPlatformLink *plink) +{ + NMDevicePrivate *priv; + NMDeviceClass *klass; + static guint32 id = 0; + + g_return_if_fail (NM_IS_DEVICE (self)); + + priv = NM_DEVICE_GET_PRIVATE (self); + + /* The device should not be realized */ + g_return_if_fail (!priv->real); + g_return_if_fail (priv->ip_ifindex <= 0); + g_return_if_fail (priv->ip_iface == NULL); + + _LOGD (LOGD_DEVICE, "start setup of %s, kernel ifindex %d", G_OBJECT_TYPE_NAME (self), plink ? plink->ifindex : 0); + + klass = NM_DEVICE_GET_CLASS (self); + + /* Balanced by a thaw in nm_device_realize_finish() */ + g_object_freeze_notify (G_OBJECT (self)); + + if (plink) { + g_return_if_fail (link_type_compatible (self, plink->type, NULL, NULL)); + update_device_from_platform_link (self, plink); + } + + if (priv->ifindex > 0) { + priv->physical_port_id = nm_platform_link_get_physical_port_id (NM_PLATFORM_GET, priv->ifindex); + g_object_notify (G_OBJECT (self), NM_DEVICE_PHYSICAL_PORT_ID); + + priv->dev_id = nm_platform_link_get_dev_id (NM_PLATFORM_GET, priv->ifindex); + + if (nm_platform_link_is_software (NM_PLATFORM_GET, priv->ifindex)) + priv->capabilities |= NM_DEVICE_CAP_IS_SOFTWARE; + + priv->mtu = nm_platform_link_get_mtu (NM_PLATFORM_GET, priv->ifindex); + g_object_notify (G_OBJECT (self), NM_DEVICE_MTU); + + nm_platform_link_get_driver_info (NM_PLATFORM_GET, + priv->ifindex, + NULL, + &priv->driver_version, + &priv->firmware_version); + if (priv->driver_version) + g_object_notify (G_OBJECT (self), NM_DEVICE_DRIVER_VERSION); + if (priv->firmware_version) + g_object_notify (G_OBJECT (self), NM_DEVICE_FIRMWARE_VERSION); + + if (nm_platform_check_support_user_ipv6ll (NM_PLATFORM_GET)) + priv->nm_ipv6ll = nm_platform_link_get_user_ipv6ll_enabled (NM_PLATFORM_GET, priv->ifindex); + } + + if (klass->get_generic_capabilities) + priv->capabilities |= klass->get_generic_capabilities (self); + + if (!priv->udi) { + /* Use a placeholder UDI until we get a real one */ + priv->udi = g_strdup_printf ("/virtual/device/placeholder/%d", id++); + g_object_notify (G_OBJECT (self), NM_DEVICE_UDI); + } + + /* trigger initial ip config change to initialize ip-config */ + priv->queued_ip4_config_id = g_idle_add (queued_ip4_config_change, self); + priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self); + + nm_device_update_hw_address (self); + nm_device_update_initial_hw_address (self); + + /* Note: initial hardware address must be read before calling get_ignore_carrier() */ + if (nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) { + NMConfig *config = nm_config_get (); + + priv->ignore_carrier = nm_config_data_get_ignore_carrier (nm_config_get_data (config), self); + g_signal_connect (G_OBJECT (config), + NM_CONFIG_SIGNAL_CONFIG_CHANGED, + G_CALLBACK (config_changed_update_ignore_carrier), + self); + + check_carrier (self); + _LOGD (LOGD_HW, + "carrier is %s%s", + priv->carrier ? "ON" : "OFF", + priv->ignore_carrier ? " (but ignored)" : ""); + } else { + /* Fake online link when carrier detection is not available. */ + priv->carrier = TRUE; + } + + g_object_notify (G_OBJECT (self), NM_DEVICE_CAPABILITIES); + + klass->realize_start_notify (self, plink); +} + +/** + * nm_device_realize_finish(): + * @self: the #NMDevice + * @plink: the #NMPlatformLink if backed by a kernel netdevice + * + * Update the device's master/slave or parent/child relationships from + * backing resource properties. After this function finishes, the device + * is ready for network connectivity. + */ +void +nm_device_realize_finish (NMDevice *self, const NMPlatformLink *plink) +{ + NMDevicePrivate *priv; + + g_return_if_fail (NM_IS_DEVICE (self)); + g_return_if_fail (!plink || link_type_compatible (self, plink->type, NULL, NULL)); + + priv = NM_DEVICE_GET_PRIVATE (self); + + g_return_if_fail (!priv->real); + + if (plink) { + update_device_from_platform_link (self, plink); + device_recheck_slave_status (self, plink); + } + + priv->real = TRUE; + g_object_notify (G_OBJECT (self), NM_DEVICE_REAL); + + nm_device_recheck_available_connections (self); + + /* Balanced by a freeze in realize_start_setup() */ + g_object_thaw_notify (G_OBJECT (self)); +} + +static void +unrealize_notify (NMDevice *self) +{ + /* Stub implementation for unrealize_notify(). It does nothing, + * but allows derived classes to uniformly invoke the parent + * implementation. */ +} + +static gboolean +available_connection_check_delete_unrealized_on_idle (gpointer user_data) +{ + NMDevice *self = user_data; + NMDevicePrivate *priv; + + g_return_val_if_fail (NM_IS_DEVICE (self), G_SOURCE_REMOVE); + + priv = NM_DEVICE_GET_PRIVATE (self); + + priv->check_delete_unrealized_id = 0; + + if ( g_hash_table_size (priv->available_connections) == 0 + && !nm_device_is_real (self)) + g_signal_emit (self, signals[REMOVED], 0); + + return G_SOURCE_REMOVE; +} + +static void +available_connection_check_delete_unrealized (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + /* always rescheadule the remove signal. */ + nm_clear_g_source (&priv->check_delete_unrealized_id); + + if ( g_hash_table_size (priv->available_connections) == 0 + && !nm_device_is_real (self)) + priv->check_delete_unrealized_id = g_idle_add (available_connection_check_delete_unrealized_on_idle, self); +} + +/** + * nm_device_unrealize(): + * @self: the #NMDevice + * @remove_resources: if %TRUE, remove backing resources + * @error: location to store error, or %NULL + * + * Clears any properties that depend on backing resources (kernel devices, + * etc) and removes those resources if @remove_resources is %TRUE. + * + * Returns: %TRUE on success, %FALSE on error + */ +gboolean +nm_device_unrealize (NMDevice *self, gboolean remove_resources, GError **error) +{ + NMDevicePrivate *priv; + int ifindex; + + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + + if (!nm_device_is_software (self) || !nm_device_is_real (self)) { + g_set_error_literal (error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_NOT_SOFTWARE, + "This device is not a software device or is not realized"); + return FALSE; + } + + priv = NM_DEVICE_GET_PRIVATE (self); + + g_return_val_if_fail (priv->iface != NULL, FALSE); + g_return_val_if_fail (priv->real, FALSE); + + g_object_freeze_notify (G_OBJECT (self)); + + ifindex = nm_device_get_ifindex (self); + + _LOGD (LOGD_DEVICE, "unrealize (ifindex %d)", ifindex > 0 ? ifindex : 0); + + if (remove_resources) { + if (ifindex > 0) + nm_platform_link_delete (NM_PLATFORM_GET, ifindex); + } + + NM_DEVICE_GET_CLASS (self)->unrealize_notify (self); + + if (priv->ifindex > 0) { + priv->ifindex = 0; + g_object_notify (G_OBJECT (self), NM_DEVICE_IFINDEX); + } + priv->ip_ifindex = 0; + if (priv->ip_iface) { + g_clear_pointer (&priv->ip_iface, g_free); + g_object_notify (G_OBJECT (self), NM_DEVICE_IP_IFACE); + } + if (priv->driver_version) { + g_clear_pointer (&priv->driver_version, g_free); + g_object_notify (G_OBJECT (self), NM_DEVICE_DRIVER_VERSION); + } + if (priv->firmware_version) { + g_clear_pointer (&priv->firmware_version, g_free); + g_object_notify (G_OBJECT (self), NM_DEVICE_FIRMWARE_VERSION); + } + if (priv->udi) { + g_clear_pointer (&priv->udi, g_free); + g_object_notify (G_OBJECT (self), NM_DEVICE_UDI); + } + if (priv->hw_addr) { + g_clear_pointer (&priv->hw_addr, g_free); + g_object_notify (G_OBJECT (self), NM_DEVICE_HW_ADDRESS); + } + if (priv->physical_port_id) { + g_clear_pointer (&priv->physical_port_id, g_free); + g_object_notify (G_OBJECT (self), NM_DEVICE_PHYSICAL_PORT_ID); + } + + g_clear_pointer (&priv->perm_hw_addr, g_free); + g_clear_pointer (&priv->initial_hw_addr, g_free); + + priv->capabilities = NM_DEVICE_CAP_NM_SUPPORTED; + if (NM_DEVICE_GET_CLASS (self)->get_generic_capabilities) + priv->capabilities |= NM_DEVICE_GET_CLASS (self)->get_generic_capabilities (self); + g_object_notify (G_OBJECT (self), NM_DEVICE_CAPABILITIES); + + priv->real = FALSE; + g_object_notify (G_OBJECT (self), NM_DEVICE_REAL); + + nm_device_set_autoconnect (self, DEFAULT_AUTOCONNECT); + + g_object_thaw_notify (G_OBJECT (self)); + + nm_device_state_changed (self, + NM_DEVICE_STATE_UNMANAGED, + remove_resources ? + NM_DEVICE_STATE_REASON_USER_REQUESTED : NM_DEVICE_STATE_REASON_NOW_UNMANAGED); + + /* Garbage-collect unneeded unrealized devices. */ + nm_device_recheck_available_connections (self); + + return TRUE; +} + +/** + * nm_device_notify_new_device_added(): + * @self: the #NMDevice + * @device: the newly added device + * + * Called by the manager to notify the device that a new device has + * been found and added. + */ +void +nm_device_notify_new_device_added (NMDevice *self, NMDevice *device) +{ + NMDeviceClass *klass; + + g_return_if_fail (NM_IS_DEVICE (self)); + g_return_if_fail (NM_IS_DEVICE (device)); + + klass = NM_DEVICE_GET_CLASS (self); + if (klass->notify_new_device_added) + klass->notify_new_device_added (self, device); +} + /** * nm_device_notify_component_added(): * @self: the #NMDevice @@ -1630,8 +2168,14 @@ check_carrier (NMDevice *self) gboolean nm_device_notify_component_added (NMDevice *self, GObject *component) { - if (NM_DEVICE_GET_CLASS (self)->component_added) - return NM_DEVICE_GET_CLASS (self)->component_added (self, component); + NMDeviceClass *klass; + + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + g_return_val_if_fail (G_IS_OBJECT (component), FALSE); + + klass = NM_DEVICE_GET_CLASS (self); + if (klass->component_added) + return klass->component_added (self, component); return FALSE; } @@ -1687,7 +2231,7 @@ slave_state_changed (NMDevice *slave, return; if (slave_new_state == NM_DEVICE_STATE_IP_CONFIG) - nm_device_enslave_slave (self, slave, nm_device_get_connection (slave)); + nm_device_master_enslave_slave (self, slave, nm_device_get_applied_connection (slave)); else if (slave_new_state > NM_DEVICE_STATE_ACTIVATED) release = TRUE; else if ( slave_new_state <= NM_DEVICE_STATE_DISCONNECTED @@ -1697,7 +2241,7 @@ slave_state_changed (NMDevice *slave, } if (release) { - nm_device_release_one_slave (self, slave, TRUE, reason); + nm_device_master_release_one_slave (self, slave, TRUE, reason); /* Bridge/bond/team interfaces are left up until manually deactivated */ if (priv->slaves == NULL && priv->state == NM_DEVICE_STATE_ACTIVATED) _LOGD (LOGD_DEVICE, "last slave removed; remaining activated"); @@ -1713,33 +2257,53 @@ slave_state_changed (NMDevice *slave, * * If @self is capable of enslaving other devices (ie it's a bridge, bond, team, * etc) then this function adds @slave to the slave list for later enslavement. - * - * Returns: %TRUE on success, %FALSE on failure */ -static gboolean +static void nm_device_master_add_slave (NMDevice *self, NMDevice *slave, gboolean configure) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMDevicePrivate *priv; + NMDevicePrivate *slave_priv; SlaveInfo *info; - g_return_val_if_fail (self != NULL, FALSE); - g_return_val_if_fail (slave != NULL, FALSE); - g_return_val_if_fail (NM_DEVICE_GET_CLASS (self)->enslave_slave != NULL, FALSE); + g_return_if_fail (NM_IS_DEVICE (self)); + g_return_if_fail (NM_IS_DEVICE (slave)); + g_return_if_fail (NM_DEVICE_GET_CLASS (self)->enslave_slave != NULL); + + priv = NM_DEVICE_GET_PRIVATE (self); + slave_priv = NM_DEVICE_GET_PRIVATE (slave); + + info = find_slave_info (self, slave); + + _LOGt (LOGD_CORE, "master: add one slave %p/%s%s", slave, nm_device_get_iface (slave), + info ? " (already registered)" : ""); if (configure) - g_return_val_if_fail (nm_device_get_state (slave) >= NM_DEVICE_STATE_DISCONNECTED, FALSE); + g_return_if_fail (nm_device_get_state (slave) >= NM_DEVICE_STATE_DISCONNECTED); - if (!find_slave_info (self, slave)) { - info = g_malloc0 (sizeof (SlaveInfo)); + if (!info) { + g_return_if_fail (!slave_priv->master); + g_return_if_fail (!slave_priv->is_enslaved); + + info = g_slice_new0 (SlaveInfo); info->slave = g_object_ref (slave); info->configure = configure; - info->watch_id = g_signal_connect (slave, "state-changed", + info->watch_id = g_signal_connect (slave, + NM_DEVICE_STATE_CHANGED, G_CALLBACK (slave_state_changed), self); priv->slaves = g_slist_append (priv->slaves, info); - } - nm_device_queue_recheck_assume (self); + slave_priv->master = g_object_ref (self); - return TRUE; + /* no need to emit + * + * g_object_notify (G_OBJECT (slave), NM_DEVICE_MASTER); + * + * because slave_priv->is_enslaved is not true, thus the value + * didn't change yet. */ + } else + g_return_if_fail (slave_priv->master == self); + + nm_device_queue_recheck_assume (self); + nm_device_queue_recheck_assume (slave); } @@ -1749,7 +2313,7 @@ nm_device_master_add_slave (NMDevice *self, NMDevice *slave, gboolean configure) * * Returns: any slaves of which @self is the master. Caller owns returned list. */ -GSList * +static GSList * nm_device_master_get_slaves (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); @@ -1794,7 +2358,7 @@ nm_device_master_get_slave_by_ifindex (NMDevice *self, int ifindex) */ void nm_device_master_check_slave_physical_port (NMDevice *self, NMDevice *slave, - guint64 log_domain) + NMLogDomain log_domain) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); const char *slave_physical_port_id, *existing_physical_port_id; @@ -1831,6 +2395,7 @@ nm_device_master_release_slaves (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMDeviceStateReason reason; + gboolean configure = TRUE; /* Don't release the slaves if this connection doesn't belong to NM. */ if (nm_device_uses_generated_assumed_connection (self)) @@ -1840,14 +2405,29 @@ nm_device_master_release_slaves (NMDevice *self) if (priv->state == NM_DEVICE_STATE_FAILED) reason = NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED; + if (!nm_platform_link_get (NM_PLATFORM_GET, priv->ifindex)) + configure = FALSE; + while (priv->slaves) { SlaveInfo *info = priv->slaves->data; - nm_device_release_one_slave (self, info->slave, TRUE, reason); + nm_device_master_release_one_slave (self, info->slave, configure, reason); } } /** + * nm_device_is_master: + * @self: the device + * + * Returns: %TRUE if the device can have slaves + */ +gboolean +nm_device_is_master (NMDevice *self) +{ + return NM_DEVICE_GET_PRIVATE (self)->is_master; +} + +/** * nm_device_get_master: * @self: the device * @@ -1863,10 +2443,11 @@ nm_device_get_master (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - if (priv->enslaved) + if (priv->is_enslaved) { + g_return_val_if_fail (priv->master, NULL); return priv->master; - else - return NULL; + } + return NULL; } /** @@ -1881,12 +2462,12 @@ static void nm_device_slave_notify_enslave (NMDevice *self, gboolean success) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMConnection *connection = nm_device_get_connection (self); + NMConnection *connection = nm_device_get_applied_connection (self); gboolean activating = (priv->state == NM_DEVICE_STATE_IP_CONFIG); - g_assert (priv->master); + g_return_if_fail (priv->master); - if (!priv->enslaved) { + if (!priv->is_enslaved) { if (success) { if (activating) { _LOGI (LOGD_DEVICE, "Activation: connection '%s' enslaved, continuing activation", @@ -1894,8 +2475,9 @@ nm_device_slave_notify_enslave (NMDevice *self, gboolean success) } else _LOGI (LOGD_DEVICE, "enslaved to %s", nm_device_get_iface (priv->master)); - priv->enslaved = TRUE; + priv->is_enslaved = TRUE; g_object_notify (G_OBJECT (self), NM_DEVICE_MASTER); + g_object_notify (G_OBJECT (priv->master), NM_DEVICE_SLAVES); } else if (activating) { _LOGW (LOGD_DEVICE, "Activation: connection '%s' could not be enslaved", nm_connection_get_id (connection)); @@ -1924,12 +2506,13 @@ static void nm_device_slave_notify_release (NMDevice *self, NMDeviceStateReason reason) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMConnection *connection = nm_device_get_connection (self); + NMConnection *connection = nm_device_get_applied_connection (self); NMDeviceState new_state; const char *master_status; - if ( reason != NM_DEVICE_STATE_REASON_NONE - && priv->state > NM_DEVICE_STATE_DISCONNECTED + g_return_if_fail (priv->master); + + if ( priv->state > NM_DEVICE_STATE_DISCONNECTED && priv->state <= NM_DEVICE_STATE_ACTIVATED) { if (reason == NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED) { new_state = NM_DEVICE_STATE_FAILED; @@ -1947,14 +2530,13 @@ nm_device_slave_notify_release (NMDevice *self, NMDeviceStateReason reason) master_status); nm_device_queue_state (self, new_state, reason); - } else if (priv->master) - _LOGI (LOGD_DEVICE, "released from master %s", nm_device_get_iface (priv->master)); - else - _LOGD (LOGD_DEVICE, "released from master%s", priv->enslaved ? "" : " (was not enslaved)"); + } else + _LOGI (LOGD_DEVICE, "released from master device %s", nm_device_get_iface (priv->master)); - if (priv->enslaved) { - priv->enslaved = FALSE; + if (priv->is_enslaved) { + priv->is_enslaved = FALSE; g_object_notify (G_OBJECT (self), NM_DEVICE_MASTER); + g_object_notify (G_OBJECT (priv->master), NM_DEVICE_SLAVES); } } @@ -1968,7 +2550,7 @@ nm_device_slave_notify_release (NMDevice *self, NMDeviceStateReason reason) gboolean nm_device_get_enslaved (NMDevice *self) { - return NM_DEVICE_GET_PRIVATE (self)->enslaved; + return NM_DEVICE_GET_PRIVATE (self)->is_enslaved; } /** @@ -1981,12 +2563,17 @@ nm_device_get_enslaved (NMDevice *self) void nm_device_removed (NMDevice *self) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMDevicePrivate *priv; - if (priv->enslaved) - nm_device_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_REMOVED); -} + g_return_if_fail (NM_IS_DEVICE (self)); + priv = NM_DEVICE_GET_PRIVATE (self); + if (priv->master) { + /* this is called when something externally messes with the slave or during shut-down. + * Release the slave from master, but don't touch the device. */ + nm_device_master_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); + } +} static gboolean is_available (NMDevice *self, NMDeviceCheckDevAvailableFlags flags) @@ -1996,7 +2583,7 @@ is_available (NMDevice *self, NMDeviceCheckDevAvailableFlags flags) if (priv->carrier || priv->ignore_carrier) return TRUE; - if (NM_FLAGS_HAS (flags, NM_DEVICE_CHECK_DEV_AVAILABLE_IGNORE_CARRIER)) + if (NM_FLAGS_HAS (flags, _NM_DEVICE_CHECK_DEV_AVAILABLE_IGNORE_CARRIER)) return TRUE; return FALSE; @@ -2068,7 +2655,7 @@ nm_device_get_autoconnect (NMDevice *self) return NM_DEVICE_GET_PRIVATE (self)->autoconnect; } -static void +void nm_device_set_autoconnect (NMDevice *self, gboolean autoconnect) { NMDevicePrivate *priv; @@ -2116,7 +2703,11 @@ nm_device_autoconnect_allowed (NMDevice *self) GValue instance = G_VALUE_INIT; GValue retval = G_VALUE_INIT; - if (priv->state < NM_DEVICE_STATE_DISCONNECTED || !priv->autoconnect) + if (!priv->autoconnect) + return FALSE; + + /* Unrealized devices can always autoconnect. */ + if (nm_device_is_real (self) && priv->state < NM_DEVICE_STATE_DISCONNECTED) return FALSE; /* The 'autoconnect-allowed' signal is emitted on a device to allow @@ -2130,15 +2721,13 @@ nm_device_autoconnect_allowed (NMDevice *self) g_value_set_object (&instance, self); g_value_init (&retval, G_TYPE_BOOLEAN); - if (priv->autoconnect) - g_value_set_boolean (&retval, TRUE); - else - g_value_set_boolean (&retval, FALSE); + g_value_set_boolean (&retval, TRUE); /* Use g_signal_emitv() rather than g_signal_emit() to avoid the return * value being changed if no handlers are connected */ g_signal_emitv (&instance, signals[AUTOCONNECT_ALLOWED], 0, &retval); g_value_unset (&instance); + return g_value_get_boolean (&retval); } @@ -2199,7 +2788,7 @@ device_has_config (NMDevice *self) return TRUE; /* The existence of a software device is good enough. */ - if (nm_device_is_software (self)) + if (nm_device_is_software (self) && nm_device_is_real (self)) return TRUE; /* Slaves are also configured by definition */ @@ -2429,6 +3018,34 @@ nm_device_check_connection_compatible (NMDevice *self, NMConnection *connection) return NM_DEVICE_GET_CLASS (self)->check_connection_compatible (self, connection); } +gboolean +nm_device_check_slave_connection_compatible (NMDevice *self, NMConnection *slave) +{ + NMDevicePrivate *priv; + NMSettingConnection *s_con; + const char *connection_type, *slave_type; + + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + g_return_val_if_fail (NM_IS_CONNECTION (slave), FALSE); + + priv = NM_DEVICE_GET_PRIVATE (self); + + if (!priv->is_master) + return FALSE; + + /* All masters should have connection type set */ + connection_type = NM_DEVICE_GET_CLASS (self)->connection_type; + g_return_val_if_fail (connection_type, FALSE); + + s_con = nm_connection_get_setting_connection (slave); + g_assert (s_con); + slave_type = nm_setting_connection_get_slave_type (s_con); + if (!slave_type) + return FALSE; + + return strcmp (connection_type, slave_type) == 0; +} + /** * nm_device_can_assume_connections: * @self: #NMDevice instance @@ -2441,7 +3058,8 @@ nm_device_check_connection_compatible (NMDevice *self, NMConnection *connection) static gboolean nm_device_can_assume_connections (NMDevice *self) { - return !!NM_DEVICE_GET_CLASS (self)->update_connection; + return !!NM_DEVICE_GET_CLASS (self)->update_connection + && !NM_DEVICE_GET_PRIVATE (self)->is_nm_owned; } /** @@ -2481,7 +3099,7 @@ nm_device_can_assume_active_connection (NMDevice *self) if (!nm_device_can_assume_connections (self)) return FALSE; - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); if (!connection) return FALSE; @@ -2505,9 +3123,14 @@ nm_device_can_assume_active_connection (NMDevice *self) } static gboolean -nm_device_emit_recheck_assume (gpointer self) +nm_device_emit_recheck_assume (gpointer user_data) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMDevice *self = user_data; + NMDevicePrivate *priv; + + g_return_val_if_fail (NM_IS_DEVICE (self), G_SOURCE_REMOVE); + + priv = NM_DEVICE_GET_PRIVATE (self); priv->recheck_assume_id = 0; if (!nm_device_get_act_request (self)) { @@ -2522,7 +3145,8 @@ nm_device_queue_recheck_assume (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - if (nm_device_can_assume_connections (self) && !priv->recheck_assume_id) + if ( !priv->recheck_assume_id + && nm_device_can_assume_connections (self)) priv->recheck_assume_id = g_idle_add (nm_device_emit_recheck_assume, self); } @@ -2544,13 +3168,17 @@ recheck_available (gpointer user_data) new_state = NM_DEVICE_STATE_UNAVAILABLE; nm_device_queue_state (self, new_state, priv->recheck_available.unavailable_reason); } - _LOGD (LOGD_DEVICE, "device is %savailable, %s %s", - now_available ? "" : "not ", - new_state == NM_DEVICE_STATE_UNAVAILABLE ? "no change required for" : "will transition to", - state_to_string (new_state == NM_DEVICE_STATE_UNAVAILABLE ? state : new_state)); - priv->recheck_available.available_reason = NM_DEVICE_STATE_REASON_NONE; - priv->recheck_available.unavailable_reason = NM_DEVICE_STATE_REASON_NONE; + if (new_state > NM_DEVICE_STATE_UNKNOWN) { + _LOGD (LOGD_DEVICE, "device is %savailable, %s %s", + now_available ? "" : "not ", + new_state == NM_DEVICE_STATE_UNAVAILABLE ? "no change required for" : "will transition to", + state_to_string (new_state == NM_DEVICE_STATE_UNAVAILABLE ? state : new_state)); + + priv->recheck_available.available_reason = NM_DEVICE_STATE_REASON_NONE; + priv->recheck_available.unavailable_reason = NM_DEVICE_STATE_REASON_NONE; + } + return G_SOURCE_REMOVE; } @@ -2587,63 +3215,119 @@ dnsmasq_state_changed_cb (NMDnsMasqManager *manager, guint32 status, gpointer us } } -static void -activation_source_clear (NMDevice *self, gboolean remove_source, int family) +/*****************************************************************************/ + +static gboolean +activation_source_handle_cb4 (gpointer user_data) +{ + activation_source_handle_cb (user_data, AF_INET); + return G_SOURCE_REMOVE; +} + +static gboolean +activation_source_handle_cb6 (gpointer user_data) +{ + activation_source_handle_cb (user_data, AF_INET6); + return G_SOURCE_REMOVE; +} + +static ActivationHandleData * +activation_source_get_by_family (NMDevice *self, + int family, + GSourceFunc *out_idle_func) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - guint *act_source_id; - gpointer *act_source_func; if (family == AF_INET6) { - act_source_id = &priv->act_source6_id; - act_source_func = &priv->act_source6_func; + NM_SET_OUT (out_idle_func, activation_source_handle_cb6); + return &priv->act_handle6; } else { - act_source_id = &priv->act_source_id; - act_source_func = &priv->act_source_func; + NM_SET_OUT (out_idle_func, activation_source_handle_cb4); + g_return_val_if_fail (family == AF_INET, &priv->act_handle4); + return &priv->act_handle4; } +} - if (*act_source_id) { - if (remove_source) - g_source_remove (*act_source_id); - *act_source_id = 0; - *act_source_func = NULL; +static void +activation_source_clear (NMDevice *self, int family) +{ + ActivationHandleData *act_data; + + act_data = activation_source_get_by_family (self, family, NULL); + + if (act_data->id) { + _LOGD (LOGD_DEVICE, "activation-stage: clear %s,%d (id %u)", + _activation_func_to_string (act_data->func), family, act_data->id); + nm_clear_g_source (&act_data->id); + act_data->func = NULL; } } static void -activation_source_schedule (NMDevice *self, GSourceFunc func, int family) +activation_source_handle_cb (NMDevice *self, int family) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - guint *act_source_id; - gpointer *act_source_func; + ActivationHandleData *act_data, a; - if (family == AF_INET6) { - act_source_id = &priv->act_source6_id; - act_source_func = &priv->act_source6_func; - } else { - act_source_id = &priv->act_source_id; - act_source_func = &priv->act_source_func; + g_return_if_fail (NM_IS_DEVICE (self)); + + act_data = activation_source_get_by_family (self, family, NULL); + + g_return_if_fail (act_data->id); + g_return_if_fail (act_data->func); + + a = *act_data; + + act_data->func = NULL; + act_data->id = 0; + + _LOGD (LOGD_DEVICE, "activation-stage: invoke %s,%d (id %u)", + _activation_func_to_string (a.func), family, a.id); + + a.func (self); + + _LOGD (LOGD_DEVICE, "activation-stage: complete %s,%d (id %u)", + _activation_func_to_string (a.func), family, a.id); +} + +static void +activation_source_schedule (NMDevice *self, ActivationHandleFunc func, int family) +{ + ActivationHandleData *act_data; + GSourceFunc source_func; + guint new_id = 0; + + act_data = activation_source_get_by_family (self, family, &source_func); + + if (act_data->id && act_data->func != func) { + /* Don't bother rescheduling the same function that's about to + * run anyway. Fixes issues with crappy wireless drivers sending + * streams of associate events before NM has had a chance to process + * the first one. + */ + _LOGD (LOGD_DEVICE, "activation-stage: already scheduled %s,%d (id %u)", + _activation_func_to_string (func), family, act_data->id); + return; } - if (*act_source_id) { - if (*act_source_func == func) { - /* Don't bother rescheduling the same function that's about to - * run anyway. Fixes issues with crappy wireless drivers sending - * streams of associate events before NM has had a chance to process - * the first one. - */ - _LOGD (LOGD_DEVICE, "activation stage already scheduled"); - return; - } else { - _LOGW (LOGD_DEVICE, "a different activation stage already scheduled"); - activation_source_clear (self, TRUE, family); - } + new_id = g_idle_add (source_func, self); + + if (act_data->id) { + _LOGW (LOGD_DEVICE, "activation-stage: schedule %s,%d which replaces %s,%d (id %u -> %u)", + _activation_func_to_string (func), family, + _activation_func_to_string (act_data->func), family, + act_data->id, new_id); + nm_clear_g_source (&act_data->id); + } else { + _LOGD (LOGD_DEVICE, "activation-stage: schedule %s,%d (id %u)", + _activation_func_to_string (func), family, new_id); } - *act_source_id = g_idle_add (func, self); - *act_source_func = func; + act_data->func = func; + act_data->id = new_id; } +/*****************************************************************************/ + static gboolean get_ip_config_may_fail (NMDevice *self, int family) { @@ -2652,7 +3336,7 @@ get_ip_config_may_fail (NMDevice *self, int family) g_return_val_if_fail (self != NULL, TRUE); - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); g_assert (connection); /* Fail the connection if the failed IP method is required to complete */ @@ -2675,26 +3359,31 @@ master_ready (NMDevice *self, NMActiveConnection *active) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMActiveConnection *master; + NMActiveConnection *master_connection; + NMDevice *master; g_return_if_fail (priv->state == NM_DEVICE_STATE_PREPARE); g_return_if_fail (!priv->master_ready_handled); /* Notify a master device that it has a new slave */ g_return_if_fail (nm_active_connection_get_master_ready (active)); - master = nm_active_connection_get_master (active); + master_connection = nm_active_connection_get_master (active); priv->master_ready_handled = TRUE; nm_clear_g_signal_handler (active, &priv->master_ready_id); - priv->master = g_object_ref (nm_active_connection_get_device (master)); - nm_device_master_add_slave (priv->master, - self, - nm_active_connection_get_assumed (active) ? FALSE : TRUE); + master = nm_active_connection_get_device (master_connection); _LOGD (LOGD_DEVICE, "master connection ready; master device %s", - nm_device_get_iface (priv->master)); + nm_device_get_iface (master)); + + if (priv->master && priv->master != master) + nm_device_master_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); + /* If the master didn't change, add-slave only rechecks whether to assume a connection. */ + nm_device_master_add_slave (master, + self, + nm_active_connection_get_assumed (active) ? FALSE : TRUE); } static void @@ -2706,6 +3395,45 @@ master_ready_cb (NMActiveConnection *active, nm_device_activate_schedule_stage2_device_config (self); } +static void +lldp_neighbors_changed (NMLldpListener *lldp_listener, GParamSpec *pspec, + gpointer user_data) +{ + NMDevice *self = NM_DEVICE (user_data); + + g_object_notify (G_OBJECT (self), NM_DEVICE_LLDP_NEIGHBORS); +} + +static gboolean +lldp_rx_enabled (NMDevice *self) +{ + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingConnectionLldp lldp = NM_SETTING_CONNECTION_LLDP_DEFAULT; + + connection = nm_device_get_applied_connection (self); + g_return_val_if_fail (connection, FALSE); + + s_con = nm_connection_get_setting_connection (connection); + g_return_val_if_fail (s_con, FALSE); + + lldp = nm_setting_connection_get_lldp (s_con); + if (lldp == NM_SETTING_CONNECTION_LLDP_DEFAULT) { + gs_free char *value = NULL; + + value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, + "connection.lldp", + self); + lldp = _nm_utils_ascii_str_to_int64 (value, 10, + NM_SETTING_CONNECTION_LLDP_DEFAULT, + NM_SETTING_CONNECTION_LLDP_ENABLE_RX, + NM_SETTING_CONNECTION_LLDP_DEFAULT); + if (lldp == NM_SETTING_CONNECTION_LLDP_DEFAULT) + lldp = NM_SETTING_CONNECTION_LLDP_DISABLE; + } + return lldp == NM_SETTING_CONNECTION_LLDP_ENABLE_RX; +} + static NMActStageReturn act_stage1_prepare (NMDevice *self, NMDeviceStateReason *reason) { @@ -2713,48 +3441,39 @@ act_stage1_prepare (NMDevice *self, NMDeviceStateReason *reason) } /* - * nm_device_activate_stage1_device_prepare + * activate_stage1_device_prepare * * Prepare for device activation * */ -static gboolean -nm_device_activate_stage1_device_prepare (gpointer user_data) +static void +activate_stage1_device_prepare (NMDevice *self) { - NMDevice *self = NM_DEVICE (user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMActStageReturn ret = NM_ACT_STAGE_RETURN_SUCCESS; NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; NMActiveConnection *active = NM_ACTIVE_CONNECTION (priv->act_request); - /* Clear the activation source ID now that this stage has run */ - activation_source_clear (self, FALSE, 0); - priv->ip4_state = priv->ip6_state = IP_NONE; /* Notify the new ActiveConnection along with the state change */ g_object_notify (G_OBJECT (self), NM_DEVICE_ACTIVE_CONNECTION); - _LOGD (LOGD_DEVICE, "Activation: Stage 1 of 5 (Device Prepare) started..."); nm_device_state_changed (self, NM_DEVICE_STATE_PREPARE, NM_DEVICE_STATE_REASON_NONE); /* Assumed connections were already set up outside NetworkManager */ if (!nm_active_connection_get_assumed (active)) { ret = NM_DEVICE_GET_CLASS (self)->act_stage1_prepare (self, &reason); if (ret == NM_ACT_STAGE_RETURN_POSTPONE) { - goto out; + return; } else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); - goto out; + return; } g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); } nm_device_activate_schedule_stage2_device_config (self); - -out: - _LOGD (LOGD_DEVICE, "Activation: Stage 1 of 5 (Device Prepare) complete."); - return FALSE; } @@ -2774,9 +3493,7 @@ nm_device_activate_schedule_stage1_device_prepare (NMDevice *self) priv = NM_DEVICE_GET_PRIVATE (self); g_return_if_fail (priv->act_request); - activation_source_schedule (self, nm_device_activate_stage1_device_prepare, 0); - - _LOGD (LOGD_DEVICE, "Activation: Stage 1 of 5 (Device Prepare) scheduled..."); + activation_source_schedule (self, activate_stage1_device_prepare, AF_INET); } static NMActStageReturn @@ -2787,16 +3504,15 @@ act_stage2_config (NMDevice *self, NMDeviceStateReason *reason) } /* - * nm_device_activate_stage2_device_config + * activate_stage2_device_config * * Determine device parameters and set those on the device, ie * for wireless devices, set SSID, keys, etc. * */ -static gboolean -nm_device_activate_stage2_device_config (gpointer user_data) +static void +activate_stage2_device_config (NMDevice *self) { - NMDevice *self = NM_DEVICE (user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMActStageReturn ret; NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; @@ -2804,10 +3520,6 @@ nm_device_activate_stage2_device_config (gpointer user_data) NMActiveConnection *active = NM_ACTIVE_CONNECTION (priv->act_request); GSList *iter; - /* Clear the activation source ID now that this stage has run */ - activation_source_clear (self, FALSE, 0); - - _LOGD (LOGD_DEVICE, "Activation: Stage 2 of 5 (Device Configure) starting..."); nm_device_state_changed (self, NM_DEVICE_STATE_CONFIG, NM_DEVICE_STATE_REASON_NONE); /* Assumed connections were already set up outside NetworkManager */ @@ -2817,15 +3529,15 @@ nm_device_activate_stage2_device_config (gpointer user_data) nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_FIRMWARE_MISSING); else nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CONFIG_FAILED); - goto out; + return; } ret = NM_DEVICE_GET_CLASS (self)->act_stage2_config (self, &reason); if (ret == NM_ACT_STAGE_RETURN_POSTPONE) - goto out; + return; else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); - goto out; + return; } g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); } @@ -2836,19 +3548,39 @@ nm_device_activate_stage2_device_config (gpointer user_data) NMDeviceState slave_state = nm_device_get_state (info->slave); if (slave_state == NM_DEVICE_STATE_IP_CONFIG) - nm_device_enslave_slave (self, info->slave, nm_device_get_connection (info->slave)); + nm_device_master_enslave_slave (self, info->slave, nm_device_get_applied_connection (info->slave)); else if ( nm_device_uses_generated_assumed_connection (self) && slave_state <= NM_DEVICE_STATE_DISCONNECTED) nm_device_queue_recheck_assume (info->slave); } - _LOGD (LOGD_DEVICE, "Activation: Stage 2 of 5 (Device Configure) successful."); + if (lldp_rx_enabled (self)) { + gs_free_error GError *error = NULL; + gconstpointer addr; + size_t addr_length; - nm_device_activate_schedule_stage3_ip_config_start (self); + if (priv->lldp_listener) + nm_lldp_listener_stop (priv->lldp_listener); + else { + priv->lldp_listener = nm_lldp_listener_new (); + g_signal_connect (priv->lldp_listener, + "notify::" NM_LLDP_LISTENER_NEIGHBORS, + G_CALLBACK (lldp_neighbors_changed), + self); + } -out: - _LOGD (LOGD_DEVICE, "Activation: Stage 2 of 5 (Device Configure) complete."); - return FALSE; + addr = nm_platform_link_get_address (NM_PLATFORM_GET, priv->ifindex, &addr_length); + + if (nm_lldp_listener_start (priv->lldp_listener, nm_device_get_ifindex (self), + nm_device_get_iface (self), addr, addr_length, &error)) + _LOGD (LOGD_DEVICE, "LLDP listener %p started", priv->lldp_listener); + else { + _LOGD (LOGD_DEVICE, "LLDP listener %p could not be started: %s", + priv->lldp_listener, error->message); + } + } + + nm_device_activate_schedule_stage3_ip_config_start (self); } @@ -2893,56 +3625,74 @@ nm_device_activate_schedule_stage2_device_config (NMDevice *self) } } - activation_source_schedule (self, nm_device_activate_stage2_device_config, 0); - - _LOGD (LOGD_DEVICE, "Activation: Stage 2 of 5 (Device Configure) scheduled..."); + activation_source_schedule (self, activate_stage2_device_config, AF_INET); } -/*********************************************/ -/* avahi-autoipd stuff */ - +/* + * nm_device_check_ip_failed + * + * Progress the device to appropriate state if both IPv4 and IPv6 failed + */ static void -aipd_timeout_remove (NMDevice *self) +nm_device_check_ip_failed (NMDevice *self, gboolean may_fail) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMDeviceState state; - if (priv->aipd_timeout) { - g_source_remove (priv->aipd_timeout); - priv->aipd_timeout = 0; + if ( priv->ip4_state != IP_FAIL + || priv->ip6_state != IP_FAIL) + return; + + if (nm_device_uses_assumed_connection (self)) { + /* We have assumed configuration, but couldn't + * redo it. No problem, move to check state. */ + priv->ip4_state = priv->ip6_state = IP_DONE; + state = NM_DEVICE_STATE_IP_CHECK; + } else if ( may_fail + && get_ip_config_may_fail (self, AF_INET) + && get_ip_config_may_fail (self, AF_INET6)) { + /* Couldn't start either IPv6 and IPv4 autoconfiguration, + * but both are allowed to fail. */ + state = NM_DEVICE_STATE_SECONDARIES; + } else { + /* Autoconfiguration attempted without success. */ + state = NM_DEVICE_STATE_FAILED; } + + nm_device_state_changed (self, + state, + NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); } +/*********************************************/ +/* IPv4LL stuff */ + static void -aipd_cleanup (NMDevice *self) +ipv4ll_cleanup (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - if (priv->aipd_watch) { - g_source_remove (priv->aipd_watch); - priv->aipd_watch = 0; + if (priv->ipv4ll) { + sd_ipv4ll_set_callback (priv->ipv4ll, NULL, NULL); + sd_ipv4ll_stop (priv->ipv4ll); + priv->ipv4ll = sd_ipv4ll_unref (priv->ipv4ll); } - if (priv->aipd_pid > 0) { - nm_utils_kill_child_sync (priv->aipd_pid, SIGKILL, LOGD_AUTOIP4, "avahi-autoipd", NULL, 0, 0); - priv->aipd_pid = -1; - } - - aipd_timeout_remove (self); + nm_clear_g_source (&priv->ipv4ll_timeout); } static NMIP4Config * -aipd_get_ip4_config (NMDevice *self, guint32 lla) +ipv4ll_get_ip4_config (NMDevice *self, guint32 lla) { NMIP4Config *config = NULL; NMPlatformIP4Address address; NMPlatformIP4Route route; - config = nm_ip4_config_new (); + config = nm_ip4_config_new (nm_device_get_ip_ifindex (self)); g_assert (config); memset (&address, 0, sizeof (address)); - address.address = lla; - address.plen = 16; + nm_platform_ip4_address_set_addr (&address, lla, 16); address.source = NM_IP_CONFIG_SOURCE_IP4LL; nm_ip4_config_add_address (config, &address); @@ -2960,22 +3710,21 @@ aipd_get_ip4_config (NMDevice *self, guint32 lla) #define IPV4LL_NETWORK (htonl (0xA9FE0000L)) #define IPV4LL_NETMASK (htonl (0xFFFF0000L)) -void -nm_device_handle_autoip4_event (NMDevice *self, - const char *event, - const char *address) +static void +nm_device_handle_ipv4ll_event (sd_ipv4ll *ll, int event, void *data) { + NMDevice *self = data; NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *connection = NULL; const char *method; - NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - - g_return_if_fail (event != NULL); + struct in_addr address; + NMIP4Config *config; + int r; if (priv->act_request == NULL) return; - connection = nm_act_request_get_connection (priv->act_request); + connection = nm_act_request_get_applied_connection (priv->act_request); g_assert (connection); /* Ignore if the connection isn't an AutoIP connection */ @@ -2983,86 +3732,62 @@ nm_device_handle_autoip4_event (NMDevice *self, if (g_strcmp0 (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) != 0) return; - if (strcmp (event, "BIND") == 0) { - guint32 lla; - NMIP4Config *config; - - if (inet_pton (AF_INET, address, &lla) <= 0) { - _LOGE (LOGD_AUTOIP4, "invalid address %s received from avahi-autoipd.", address); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_AUTOIP_ERROR); + switch (event) { + case SD_IPV4LL_EVENT_BIND: + r = sd_ipv4ll_get_address (ll, &address); + if (r < 0) { + _LOGE (LOGD_AUTOIP4, "invalid IPv4 link-local address received, error %d.", r); + priv->ip4_state = IP_FAIL; + nm_device_check_ip_failed (self, FALSE); return; } - if ((lla & IPV4LL_NETMASK) != IPV4LL_NETWORK) { - _LOGE (LOGD_AUTOIP4, "invalid address %s received from avahi-autoipd (not link-local).", address); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_AUTOIP_ERROR); + if ((address.s_addr & IPV4LL_NETMASK) != IPV4LL_NETWORK) { + _LOGE (LOGD_AUTOIP4, "invalid address %08x received (not link-local).", address.s_addr); + priv->ip4_state = IP_FAIL; + nm_device_check_ip_failed (self, FALSE); return; } - config = aipd_get_ip4_config (self, lla); + config = ipv4ll_get_ip4_config (self, address.s_addr); if (config == NULL) { - _LOGE (LOGD_AUTOIP4, "failed to get autoip config"); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); + _LOGE (LOGD_AUTOIP4, "failed to get IPv4LL config"); + priv->ip4_state = IP_FAIL; + nm_device_check_ip_failed (self, FALSE); return; } if (priv->ip4_state == IP_CONF) { - aipd_timeout_remove (self); + nm_clear_g_source (&priv->ipv4ll_timeout); nm_device_activate_schedule_ip4_config_result (self, config); } else if (priv->ip4_state == IP_DONE) { - if (!ip4_config_merge_and_apply (self, config, TRUE, &reason)) { + if (!ip4_config_merge_and_apply (self, config, TRUE, NULL)) { _LOGE (LOGD_AUTOIP4, "failed to update IP4 config for autoip change."); - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + priv->ip4_state = IP_FAIL; + nm_device_check_ip_failed (self, FALSE); } } else g_assert_not_reached (); g_object_unref (config); - } else { - _LOGW (LOGD_AUTOIP4, "autoip address %s no longer valid because '%s'.", address, event); - - /* The address is gone; terminate the connection or fail activation */ - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_IP_CONFIG_EXPIRED); + break; + default: + _LOGW (LOGD_AUTOIP4, "IPv4LL address no longer valid after event %d.", event); + priv->ip4_state = IP_FAIL; + nm_device_check_ip_failed (self, FALSE); } } -static void -aipd_watch_cb (GPid pid, gint status, gpointer user_data) -{ - NMDevice *self = NM_DEVICE (user_data); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMDeviceState state; - - if (!priv->aipd_watch) - return; - priv->aipd_watch = 0; - - if (WIFEXITED (status)) - _LOGD (LOGD_AUTOIP4, "avahi-autoipd exited with error code %d", WEXITSTATUS (status)); - else if (WIFSTOPPED (status)) - _LOGW (LOGD_AUTOIP4, "avahi-autoipd stopped unexpectedly with signal %d", WSTOPSIG (status)); - else if (WIFSIGNALED (status)) - _LOGW (LOGD_AUTOIP4, "avahi-autoipd died with signal %d", WTERMSIG (status)); - else - _LOGW (LOGD_AUTOIP4, "avahi-autoipd died from an unknown cause"); - - aipd_cleanup (self); - - state = nm_device_get_state (self); - if (nm_device_is_activating (self) || (state == NM_DEVICE_STATE_ACTIVATED)) - nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_AUTOIP_FAILED); -} - static gboolean -aipd_timeout_cb (gpointer user_data) +ipv4ll_timeout_cb (gpointer user_data) { NMDevice *self = NM_DEVICE (user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - if (priv->aipd_timeout) { - _LOGI (LOGD_AUTOIP4, "avahi-autoipd timed out."); - priv->aipd_timeout = 0; - aipd_cleanup (self); + if (priv->ipv4ll_timeout) { + _LOGI (LOGD_AUTOIP4, "IPv4LL configuration timed out."); + priv->ipv4ll_timeout = 0; + ipv4ll_cleanup (self); if (priv->ip4_state == IP_CONF) nm_device_activate_schedule_ip4_config_timeout (self); @@ -3071,66 +3796,68 @@ aipd_timeout_cb (gpointer user_data) return FALSE; } -/* default to installed helper, but can be modified for testing */ -const char *nm_device_autoipd_helper_path = LIBEXECDIR "/nm-avahi-autoipd.action"; - static NMActStageReturn -aipd_start (NMDevice *self, NMDeviceStateReason *reason) +ipv4ll_start (NMDevice *self, NMDeviceStateReason *reason) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - const char *argv[6]; - char *cmdline; - const char *aipd_binary; - int i = 0; - GError *error = NULL; + const struct ether_addr *addr; + int ifindex, r; + size_t addr_len; - aipd_cleanup (self); + ipv4ll_cleanup (self); - /* Find avahi-autoipd */ - aipd_binary = nm_utils_find_helper ("avahi-autoipd", NULL, NULL); - if (!aipd_binary) { - _LOGW (LOGD_DEVICE | LOGD_AUTOIP4, - "Activation: Stage 3 of 5 (IP Configure Start) failed" - " to start avahi-autoipd: not found"); - *reason = NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED; - return NM_ACT_STAGE_RETURN_FAILURE; + r = sd_ipv4ll_new (&priv->ipv4ll); + if (r < 0) { + _LOGE (LOGD_AUTOIP4, "IPv4LL: new() failed with error %d", r); + goto fail; } - argv[i++] = aipd_binary; - argv[i++] = "--script"; - argv[i++] = nm_device_autoipd_helper_path; + r = sd_ipv4ll_attach_event (priv->ipv4ll, NULL, 0); + if (r < 0) { + _LOGE (LOGD_AUTOIP4, "IPv4LL: attach_event() failed with error %d", r); + goto fail; + } - if (nm_logging_enabled (LOGL_DEBUG, LOGD_AUTOIP4)) - argv[i++] = "--debug"; - argv[i++] = nm_device_get_ip_iface (self); - argv[i++] = NULL; + ifindex = nm_device_get_ip_ifindex (self); + addr = nm_platform_link_get_address (NM_PLATFORM_GET, ifindex, &addr_len); + if (!addr || addr_len != ETH_ALEN) { + _LOGE (LOGD_AUTOIP4, "IPv4LL: can't retrieve hardware address"); + goto fail; + } - cmdline = g_strjoinv (" ", (char **) argv); - _LOGD (LOGD_AUTOIP4, "running: %s", cmdline); - g_free (cmdline); + r = sd_ipv4ll_set_mac (priv->ipv4ll, addr); + if (r < 0) { + _LOGE (LOGD_AUTOIP4, "IPv4LL: set_mac() failed with error %d", r); + goto fail; + } - if (!g_spawn_async ("/", (char **) argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, - nm_utils_setpgid, NULL, &(priv->aipd_pid), &error)) { - _LOGW (LOGD_DEVICE | LOGD_AUTOIP4, - "Activation: Stage 3 of 5 (IP Configure Start) failed" - " to start avahi-autoipd: %s", - error && error->message ? error->message : "(unknown)"); - g_clear_error (&error); - aipd_cleanup (self); - return NM_ACT_STAGE_RETURN_FAILURE; + r = sd_ipv4ll_set_index (priv->ipv4ll, ifindex); + if (r < 0) { + _LOGE (LOGD_AUTOIP4, "IPv4LL: set_index() failed with error %d", r); + goto fail; } - _LOGD (LOGD_DEVICE | LOGD_AUTOIP4, - "Activation: Stage 3 of 5 (IP Configure Start) started" - " avahi-autoipd..."); + r = sd_ipv4ll_set_callback (priv->ipv4ll, nm_device_handle_ipv4ll_event, self); + if (r < 0) { + _LOGE (LOGD_AUTOIP4, "IPv4LL: set_callback() failed with error %d", r); + goto fail; + } + + r = sd_ipv4ll_start (priv->ipv4ll); + if (r < 0) { + _LOGE (LOGD_AUTOIP4, "IPv4LL: start() failed with error %d", r); + goto fail; + } - /* Monitor the child process so we know when it dies */ - priv->aipd_watch = g_child_watch_add (priv->aipd_pid, aipd_watch_cb, self); + _LOGI (LOGD_DEVICE | LOGD_AUTOIP4, "IPv4LL: started"); /* Start a timeout to bound the address attempt */ - priv->aipd_timeout = g_timeout_add_seconds (20, aipd_timeout_cb, self); + priv->ipv4ll_timeout = g_timeout_add_seconds (20, ipv4ll_timeout_cb, self); return NM_ACT_STAGE_RETURN_POSTPONE; +fail: + *reason = NM_DEVICE_STATE_REASON_AUTOIP_START_FAILED; + return NM_ACT_STAGE_RETURN_FAILURE; } /*********************************************/ @@ -3185,16 +3912,17 @@ static void ensure_con_ip4_config (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + int ip_ifindex = nm_device_get_ip_ifindex (self); NMConnection *connection; if (priv->con_ip4_config) return; - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); if (!connection) return; - priv->con_ip4_config = nm_ip4_config_new (); + priv->con_ip4_config = nm_ip4_config_new (ip_ifindex); nm_ip4_config_merge_setting (priv->con_ip4_config, nm_connection_get_setting_ip4_config (connection), nm_device_get_ip4_route_metric (self)); @@ -3210,16 +3938,17 @@ static void ensure_con_ip6_config (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + int ip_ifindex = nm_device_get_ip_ifindex (self); NMConnection *connection; if (priv->con_ip6_config) return; - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); if (!connection) return; - priv->con_ip6_config = nm_ip6_config_new (); + priv->con_ip6_config = nm_ip6_config_new (ip_ifindex); nm_ip6_config_merge_setting (priv->con_ip6_config, nm_connection_get_setting_ip6_config (connection), nm_device_get_ip6_route_metric (self)); @@ -3243,10 +3972,7 @@ dhcp4_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) if (priv->dhcp4_client) { /* Stop any ongoing DHCP transaction on this device */ - if (priv->dhcp4_state_sigid) { - g_signal_handler_disconnect (priv->dhcp4_client, priv->dhcp4_state_sigid); - priv->dhcp4_state_sigid = 0; - } + nm_clear_g_signal_handler (priv->dhcp4_client, &priv->dhcp4_state_sigid); nm_device_remove_pending_action (self, PENDING_ACTION_DHCP4, FALSE); @@ -3258,11 +3984,20 @@ dhcp4_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) } if (priv->dhcp4_config) { - g_clear_object (&priv->dhcp4_config); + nm_exported_object_clear_and_unexport (&priv->dhcp4_config); g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP4_CONFIG); } } +static void +_ip4_config_merge_default (gpointer value, gpointer user_data) +{ + NMIP4Config *src = (NMIP4Config *) value; + NMIP4Config *dst = (NMIP4Config *) user_data; + + nm_ip4_config_merge (dst, src, NM_IP_CONFIG_MERGE_DEFAULT); +} + static gboolean ip4_config_merge_and_apply (NMDevice *self, NMIP4Config *config, @@ -3288,7 +4023,7 @@ ip4_config_merge_and_apply (NMDevice *self, } /* Apply ignore-auto-routes and ignore-auto-dns settings */ - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); if (connection) { NMSettingIPConfig *s_ip4 = nm_connection_get_setting_ip4_config (connection); @@ -3298,7 +4033,7 @@ ip4_config_merge_and_apply (NMDevice *self, } } - composite = nm_ip4_config_new (); + composite = nm_ip4_config_new (nm_device_get_ip_ifindex (self)); if (commit) ensure_con_ip4_config (self); @@ -3308,8 +4043,9 @@ ip4_config_merge_and_apply (NMDevice *self, (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0)); } - if (priv->vpn4_config) - nm_ip4_config_merge (composite, priv->vpn4_config, NM_IP_CONFIG_MERGE_DEFAULT); + + g_slist_foreach (priv->vpn4_configs, _ip4_config_merge_default, composite); + if (priv->ext_ip4_config) nm_ip4_config_merge (composite, priv->ext_ip4_config, NM_IP_CONFIG_MERGE_DEFAULT); @@ -3327,7 +4063,6 @@ ip4_config_merge_and_apply (NMDevice *self, if (priv->con_ip4_config) nm_ip4_config_merge (composite, priv->con_ip4_config, NM_IP_CONFIG_MERGE_DEFAULT); - /* Add the default route. * * We keep track of the default route of a device in a private field. @@ -3366,7 +4101,7 @@ ip4_config_merge_and_apply (NMDevice *self, if ( !priv->v4_commit_first_time && connection_is_never_default) { - /* If the connection is explicitly configured as never-default, we enforce the (absense of the) + /* If the connection is explicitly configured as never-default, we enforce the (absence of the) * default-route only once. That allows the user to configure a connection as never-default, * but he can add default routes externally (via a dispatcher script) and NM will not interfere. */ goto END_ADD_DEFAULT_ROUTE; @@ -3390,7 +4125,7 @@ ip4_config_merge_and_apply (NMDevice *self, goto END_ADD_DEFAULT_ROUTE; has_direct_route = ( gateway == 0 - || nm_ip4_config_get_subnet_for_host (composite, gateway) + || nm_ip4_config_destination_is_direct (composite, gateway, 32) || nm_ip4_config_get_direct_route_for_host (composite, gateway)); priv->default_route.v4_has = TRUE; @@ -3452,7 +4187,8 @@ dhcp4_lease_change (NMDevice *self, NMIP4Config *config) } else { /* Notify dispatcher scripts of new DHCP4 config */ nm_dispatcher_call (DISPATCHER_ACTION_DHCP4_CHANGE, - nm_device_get_connection (self), + nm_device_get_settings_connection (self), + nm_device_get_applied_connection (self), self, NULL, NULL, @@ -3472,7 +4208,7 @@ dhcp4_restart_cb (gpointer user_data) priv = NM_DEVICE_GET_PRIVATE (self); priv->dhcp4_restart_id = 0; - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); if (dhcp4_start (self, connection, &reason) == NM_ACT_STAGE_RETURN_FAILURE) priv->dhcp4_restart_id = g_timeout_add_seconds (120, dhcp4_restart_cb, self); @@ -3517,22 +4253,6 @@ dhcp4_fail (NMDevice *self, gboolean timeout) } static void -dhcp4_update_config (NMDevice *self, NMDhcp4Config *config, GHashTable *options) -{ - GHashTableIter iter; - const char *key, *value; - - /* Update the DHCP4 config object with new DHCP options */ - nm_dhcp4_config_reset (config); - - g_hash_table_iter_init (&iter, options); - while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value)) - nm_dhcp4_config_add_option (config, key, value); - - g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP4_CONFIG); -} - -static void dhcp4_state_changed (NMDhcpClient *client, NMDhcpState state, NMIP4Config *ip4_config, @@ -3558,7 +4278,8 @@ dhcp4_state_changed (NMDhcpClient *client, break; } - dhcp4_update_config (self, priv->dhcp4_config, options); + nm_dhcp4_config_set_options (priv->dhcp4_config, options); + g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP4_CONFIG); if (priv->ip4_state == IP_CONF) nm_device_activate_schedule_ip4_config_result (self, ip4_config); @@ -3584,6 +4305,28 @@ dhcp4_state_changed (NMDhcpClient *client, } } +static int +dhcp4_get_timeout (NMDevice *self, NMSettingIP4Config *s_ip4) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + gs_free char *value = NULL; + int timeout; + + timeout = nm_setting_ip4_config_get_dhcp_timeout (s_ip4); + if (timeout) + return timeout; + + value = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, + "ipv4.dhcp-timeout", + self); + timeout = _nm_utils_ascii_str_to_int64 (value, 10, + 0, G_MAXINT32, 0); + if (timeout) + return timeout; + + return priv->dhcp_timeout; +} + static NMActStageReturn dhcp4_start (NMDevice *self, NMConnection *connection, @@ -3598,8 +4341,7 @@ dhcp4_start (NMDevice *self, s_ip4 = nm_connection_get_setting_ip4_config (connection); /* Clear old exported DHCP options */ - if (priv->dhcp4_config) - g_object_unref (priv->dhcp4_config); + nm_exported_object_clear_and_unexport (&priv->dhcp4_config); priv->dhcp4_config = nm_dhcp4_config_new (); hw_addr = nm_platform_link_get_address (NM_PLATFORM_GET, nm_device_get_ip_ifindex (self), &hw_addr_len); @@ -3618,8 +4360,9 @@ dhcp4_start (NMDevice *self, nm_device_get_ip4_route_metric (self), nm_setting_ip_config_get_dhcp_send_hostname (s_ip4), nm_setting_ip_config_get_dhcp_hostname (s_ip4), + nm_setting_ip4_config_get_dhcp_fqdn (NM_SETTING_IP4_CONFIG (s_ip4)), nm_setting_ip4_config_get_dhcp_client_id (NM_SETTING_IP4_CONFIG (s_ip4)), - priv->dhcp_timeout, + dhcp4_get_timeout (self, NM_SETTING_IP4_CONFIG (s_ip4)), priv->dhcp_anycast_address, NULL); @@ -3657,7 +4400,7 @@ nm_device_dhcp4_renew (NMDevice *self, gboolean release) /* Terminate old DHCP instance and release the old lease */ dhcp4_cleanup (self, CLEANUP_TYPE_DECONFIGURE, release); - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); g_assert (connection); /* Start DHCP again on the interface */ @@ -3687,10 +4430,11 @@ reserve_shared_ip (NMDevice *self, NMSettingIPConfig *s_ip4, NMPlatformIP4Addres if (s_ip4 && nm_setting_ip_config_get_num_addresses (s_ip4)) { /* Use the first user-supplied address */ NMIPAddress *user = nm_setting_ip_config_get_address (s_ip4, 0); + in_addr_t a; g_assert (user); - nm_ip_address_get_address_binary (user, &address->address); - address->plen = nm_ip_address_get_prefix (user); + nm_ip_address_get_address_binary (user, &a); + nm_platform_ip4_address_set_addr (address, a, nm_ip_address_get_prefix (user)); } else { /* Find an unused address in the 10.42.x.x range */ guint32 start = (guint32) ntohl (0x0a2a0001); /* 10.42.0.1 */ @@ -3703,8 +4447,7 @@ reserve_shared_ip (NMDevice *self, NMSettingIPConfig *s_ip4, NMPlatformIP4Addres return FALSE; } } - address->address = start + count; - address->plen = 24; + nm_platform_ip4_address_set_addr (address, start + count, 24); g_hash_table_insert (shared_ips, GUINT_TO_POINTER (address->address), @@ -3727,7 +4470,7 @@ shared4_new_config (NMDevice *self, NMConnection *connection, NMDeviceStateReaso return NULL; } - config = nm_ip4_config_new (); + config = nm_ip4_config_new (nm_device_get_ip_ifindex (self)); address.source = NM_IP_CONFIG_SOURCE_SHARED; nm_ip4_config_add_address (config, &address); @@ -3852,7 +4595,7 @@ act_stage3_ip4_config_start (NMDevice *self, g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); g_assert (connection); if ( connection_ip4_method_requires_carrier (connection, NULL) @@ -3884,10 +4627,10 @@ act_stage3_ip4_config_start (NMDevice *self, if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0) ret = dhcp4_start (self, connection, reason); else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL) == 0) - ret = aipd_start (self, reason); + ret = ipv4ll_start (self, reason); else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0) { /* Use only IPv4 config from the connection data */ - *out_config = nm_ip4_config_new (); + *out_config = nm_ip4_config_new (nm_device_get_ip_ifindex (self)); g_assert (*out_config); ret = NM_ACT_STAGE_RETURN_SUCCESS; } else if (strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0) { @@ -3917,14 +4660,10 @@ dhcp6_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) priv->dhcp6_mode = NM_RDISC_DHCP_LEVEL_NONE; g_clear_object (&priv->dhcp6_ip6_config); g_clear_pointer (&priv->dhcp6_event_id, g_free); - nm_clear_g_source (&priv->dhcp6_restart_id); if (priv->dhcp6_client) { - if (priv->dhcp6_state_sigid) { - g_signal_handler_disconnect (priv->dhcp6_client, priv->dhcp6_state_sigid); - priv->dhcp6_state_sigid = 0; - } + nm_clear_g_signal_handler (priv->dhcp6_client, &priv->dhcp6_state_sigid); if ( cleanup_type == CLEANUP_TYPE_DECONFIGURE || cleanup_type == CLEANUP_TYPE_REMOVED) @@ -3936,11 +4675,20 @@ dhcp6_cleanup (NMDevice *self, CleanupType cleanup_type, gboolean release) nm_device_remove_pending_action (self, PENDING_ACTION_DHCP6, FALSE); if (priv->dhcp6_config) { - g_clear_object (&priv->dhcp6_config); + nm_exported_object_clear_and_unexport (&priv->dhcp6_config); g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP6_CONFIG); } } +static void +_ip6_config_merge_default (gpointer value, gpointer user_data) +{ + NMIP6Config *src = (NMIP6Config *) value; + NMIP6Config *dst = (NMIP6Config *) user_data; + + nm_ip6_config_merge (dst, src, NM_IP_CONFIG_MERGE_DEFAULT); +} + static gboolean ip6_config_merge_and_apply (NMDevice *self, gboolean commit, @@ -3958,7 +4706,7 @@ ip6_config_merge_and_apply (NMDevice *self, gboolean ignore_auto_dns = FALSE; /* Apply ignore-auto-routes and ignore-auto-dns settings */ - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); if (connection) { NMSettingIPConfig *s_ip6 = nm_connection_get_setting_ip6_config (connection); @@ -3969,10 +4717,11 @@ ip6_config_merge_and_apply (NMDevice *self, } /* If no config was passed in, create a new one */ - composite = nm_ip6_config_new (); + composite = nm_ip6_config_new (nm_device_get_ip_ifindex (self)); if (commit) ensure_con_ip6_config (self); + g_assert (composite); /* Merge all the IP configs into the composite config */ if (priv->ac_ip6_config) { @@ -3985,8 +4734,9 @@ ip6_config_merge_and_apply (NMDevice *self, (ignore_auto_routes ? NM_IP_CONFIG_MERGE_NO_ROUTES : 0) | (ignore_auto_dns ? NM_IP_CONFIG_MERGE_NO_DNS : 0)); } - if (priv->vpn6_config) - nm_ip6_config_merge (composite, priv->vpn6_config, NM_IP_CONFIG_MERGE_DEFAULT); + + g_slist_foreach (priv->vpn6_configs, _ip6_config_merge_default, composite); + if (priv->ext_ip6_config) nm_ip6_config_merge (composite, priv->ext_ip6_config, NM_IP_CONFIG_MERGE_DEFAULT); @@ -4121,7 +4871,7 @@ static void dhcp6_lease_change (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMConnection *connection; + NMSettingsConnection *settings_connection; NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; if (priv->dhcp6_ip6_config == NULL) { @@ -4132,8 +4882,8 @@ dhcp6_lease_change (NMDevice *self) g_assert (priv->dhcp6_client); /* sanity check */ - connection = nm_device_get_connection (self); - g_assert (connection); + settings_connection = nm_device_get_settings_connection (self); + g_assert (settings_connection); /* Apply the updated config */ if (ip6_config_merge_and_apply (self, TRUE, &reason) == FALSE) { @@ -4141,7 +4891,10 @@ dhcp6_lease_change (NMDevice *self) nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); } else { /* Notify dispatcher scripts of new DHCPv6 config */ - nm_dispatcher_call (DISPATCHER_ACTION_DHCP6_CHANGE, connection, self, NULL, NULL, NULL); + nm_dispatcher_call (DISPATCHER_ACTION_DHCP6_CHANGE, + settings_connection, + nm_device_get_applied_connection (self), + self, NULL, NULL, NULL); } } @@ -4221,22 +4974,6 @@ dhcp6_timeout (NMDevice *self, NMDhcpClient *client) } static void -dhcp6_update_config (NMDevice *self, NMDhcp6Config *config, GHashTable *options) -{ - GHashTableIter iter; - const char *key, *value; - - /* Update the DHCP6 config object with new DHCP options */ - nm_dhcp6_config_reset (config); - - g_hash_table_iter_init (&iter, options); - while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &value)) - nm_dhcp6_config_add_option (config, key, value); - - g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP6_CONFIG); -} - -static void dhcp6_state_changed (NMDhcpClient *client, NMDhcpState state, NMIP6Config *ip6_config, @@ -4273,7 +5010,7 @@ dhcp6_state_changed (NMDhcpClient *client, if (ip6_config) { priv->dhcp6_ip6_config = g_object_ref (ip6_config); priv->dhcp6_event_id = g_strdup (event_id); - dhcp6_update_config (self, priv->dhcp6_config, options); + nm_dhcp6_config_set_options (priv->dhcp6_config, options); g_object_notify (G_OBJECT (self), NM_DEVICE_DHCP6_CONFIG); } } @@ -4320,6 +5057,9 @@ dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection) GByteArray *tmp = NULL; const guint8 *hw_addr; size_t hw_addr_len = 0; + const struct in6_addr *ll_addr = NULL; + NMIP6Config *ip6_config; + int i; g_assert (connection); s_ip6 = nm_connection_get_setting_ip6_config (connection); @@ -4331,10 +5071,22 @@ dhcp6_start_with_link_ready (NMDevice *self, NMConnection *connection) g_byte_array_append (tmp, hw_addr, hw_addr_len); } + ip6_config = priv->ext_ip6_config; + for (i = 0; ip6_config && i < nm_ip6_config_get_num_addresses (ip6_config); i++) { + const NMPlatformIP6Address *addr = nm_ip6_config_get_address (ip6_config, i); + + if (IN6_IS_ADDR_LINKLOCAL (&addr->address)) { + ll_addr = &addr->address; + break; + } + } + g_return_val_if_fail (ll_addr, FALSE); + priv->dhcp6_client = nm_dhcp_manager_start_ip6 (nm_dhcp_manager_get (), nm_device_get_ip_iface (self), nm_device_get_ip_ifindex (self), tmp, + ll_addr, nm_connection_get_uuid (connection), nm_device_get_ip6_route_metric (self), nm_setting_ip_config_get_dhcp_send_hostname (s_ip6), @@ -4363,14 +5115,14 @@ dhcp6_start (NMDevice *self, gboolean wait_for_ll, NMDeviceStateReason *reason) NMConnection *connection; NMSettingIPConfig *s_ip6; - g_clear_object (&priv->dhcp6_config); + nm_exported_object_clear_and_unexport (&priv->dhcp6_config); priv->dhcp6_config = nm_dhcp6_config_new (); g_warn_if_fail (priv->dhcp6_ip6_config == NULL); g_clear_object (&priv->dhcp6_ip6_config); g_clear_pointer (&priv->dhcp6_event_id, g_free); - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); g_assert (connection); s_ip6 = nm_connection_get_setting_ip6_config (connection); if (!nm_setting_ip_config_get_may_fail (s_ip6) || @@ -4443,10 +5195,14 @@ linklocal6_cleanup (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - if (priv->linklocal6_timeout_id) { - g_source_remove (priv->linklocal6_timeout_id); - priv->linklocal6_timeout_id = 0; - } + nm_clear_g_source (&priv->linklocal6_timeout_id); +} + +static void +linklocal6_failed (NMDevice *self) +{ + linklocal6_cleanup (self); + nm_device_activate_schedule_ip6_config_timeout (self); } static gboolean @@ -4454,11 +5210,8 @@ linklocal6_timeout_cb (gpointer user_data) { NMDevice *self = user_data; - linklocal6_cleanup (self); - _LOGD (LOGD_DEVICE, "linklocal6: waiting for link-local addresses failed due to timeout"); - - nm_device_activate_schedule_ip6_config_timeout (self); + linklocal6_failed (self); return G_SOURCE_REMOVE; } @@ -4474,7 +5227,7 @@ linklocal6_complete (NMDevice *self) linklocal6_cleanup (self); - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); g_assert (connection); method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG); @@ -4502,9 +5255,11 @@ check_and_add_ipv6ll_addr (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); int ip_ifindex = nm_device_get_ip_ifindex (self); - NMUtilsIPv6IfaceId iid; struct in6_addr lladdr; guint i, n; + NMConnection *connection; + NMSettingIP6Config *s_ip6 = NULL; + GError *error = NULL; if (priv->nm_ipv6ll == FALSE) return; @@ -4515,27 +5270,59 @@ check_and_add_ipv6ll_addr (NMDevice *self) const NMPlatformIP6Address *addr; addr = nm_ip6_config_get_address (priv->ip6_config, i); - if (IN6_IS_ADDR_LINKLOCAL (&addr->address)) { + if ( IN6_IS_ADDR_LINKLOCAL (&addr->address) + && !(addr->flags & IFA_F_DADFAILED)) { /* Already have an LL address, nothing to do */ return; } } } - if (!nm_device_get_ip_iface_identifier (self, &iid)) { - _LOGW (LOGD_IP6, "failed to get interface identifier; IPv6 may be broken"); - return; - } - memset (&lladdr, 0, sizeof (lladdr)); lladdr.s6_addr16[0] = htons (0xfe80); - nm_utils_ipv6_addr_set_interface_identfier (&lladdr, iid); - _LOGD (LOGD_IP6, "adding IPv6LL address %s", nm_utils_inet6_ntop (&lladdr, NULL)); + + connection = nm_device_get_applied_connection (self); + if (connection) + s_ip6 = NM_SETTING_IP6_CONFIG (nm_connection_get_setting_ip6_config (connection)); + + if (s_ip6 && nm_setting_ip6_config_get_addr_gen_mode (s_ip6) == NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_STABLE_PRIVACY) { + if (!nm_utils_ipv6_addr_set_stable_privacy (&lladdr, + nm_device_get_iface (self), + nm_connection_get_uuid (connection), + priv->linklocal6_dad_counter++, + &error)) { + _LOGW (LOGD_IP6, "linklocal6: failed to generate an address: %s", error->message); + g_clear_error (&error); + linklocal6_failed (self); + return; + } + _LOGD (LOGD_IP6, "linklocal6: using IPv6 stable-privacy addressing"); + } else { + NMUtilsIPv6IfaceId iid; + + if (priv->linklocal6_timeout_id) { + /* We already started and attempt to add a LL address. For the EUI-64 + * mode we can't pick a new one, we'll just fail. */ + _LOGW (LOGD_IP6, "linklocal6: DAD failed for an EUI-64 address"); + linklocal6_failed (self); + return; + } + + if (!nm_device_get_ip_iface_identifier (self, &iid)) { + _LOGW (LOGD_IP6, "linklocal6: failed to get interface identifier; IPv6 cannot continue"); + return; + } + _LOGD (LOGD_IP6, "linklocal6: using EUI-64 identifier to generate IPv6LL address"); + + nm_utils_ipv6_addr_set_interface_identfier (&lladdr, iid); + } + + _LOGD (LOGD_IP6, "linklocal6: adding IPv6LL address %s", nm_utils_inet6_ntop (&lladdr, NULL)); if (!nm_platform_ip6_address_add (NM_PLATFORM_GET, ip_ifindex, lladdr, - in6addr_any, 64, + in6addr_any, NM_PLATFORM_LIFETIME_PERMANENT, NM_PLATFORM_LIFETIME_PERMANENT, 0)) { @@ -4556,7 +5343,7 @@ linklocal6_start (NMDevice *self) if (have_ip6_address (priv->ip6_config, TRUE)) return NM_ACT_STAGE_RETURN_FINISH; - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); g_assert (connection); method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG); @@ -4576,53 +5363,6 @@ linklocal6_start (NMDevice *self) /******************************************/ -static void -print_support_extended_ifa_flags (NMSettingIP6ConfigPrivacy use_tempaddr) -{ - static gint8 warn = 0; - static gint8 s_libnl = -1, s_kernel; - - if (warn >= 2) - return; - - if (s_libnl == -1) { - s_libnl = !!nm_platform_check_support_libnl_extended_ifa_flags (); - s_kernel = !!nm_platform_check_support_kernel_extended_ifa_flags (NM_PLATFORM_GET); - - if (s_libnl && s_kernel) { - nm_log_dbg (LOGD_IP6, "kernel and libnl support extended IFA_FLAGS (needed by NM for IPv6 private addresses)"); - warn = 2; - return; - } - } - - if ( use_tempaddr != NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR - && use_tempaddr != NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR) { - if (warn == 0) { - nm_log_dbg (LOGD_IP6, "%s%s%s %s not support extended IFA_FLAGS (needed by NM for IPv6 private addresses)", - !s_kernel ? "kernel" : "", - !s_kernel && !s_libnl ? " and " : "", - !s_libnl ? "libnl" : "", - !s_kernel && !s_libnl ? "do" : "does"); - warn = 1; - } - return; - } - - if (!s_libnl && !s_kernel) { - nm_log_warn (LOGD_IP6, "libnl and the kernel do not support extended IFA_FLAGS needed by NM for " - "IPv6 private addresses. This feature is not available"); - } else if (!s_libnl) { - nm_log_warn (LOGD_IP6, "libnl does not support extended IFA_FLAGS needed by NM for " - "IPv6 private addresses. This feature is not available"); - } else if (!s_kernel) { - nm_log_warn (LOGD_IP6, "The kernel does not support extended IFA_FLAGS needed by NM for " - "IPv6 private addresses. This feature is not available"); - } - - warn = 2; -} - static void nm_device_ipv6_set_mtu (NMDevice *self, guint32 mtu); static void @@ -4680,24 +5420,20 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); int i; - static int system_support = -1; + int system_support; guint ifa_flags = 0x00; - if (system_support == -1) { - /* - * Check, if both libnl and the kernel are recent enough, - * to help user space handling RA. If it's not supported, - * we have no ipv6-privacy and must add autoconf addresses - * as /128. The reason for the /128 is to prevent the kernel - * from adding a prefix route for this address. - **/ - system_support = nm_platform_check_support_libnl_extended_ifa_flags () && - nm_platform_check_support_kernel_extended_ifa_flags (NM_PLATFORM_GET); - } + /* + * Check, whether kernel is recent enough to help user space handling RA. + * If it's not supported, we have no ipv6-privacy and must add autoconf + * addresses as /128. The reason for the /128 is to prevent the kernel + * from adding a prefix route for this address. + **/ + system_support = nm_platform_check_support_kernel_extended_ifa_flags (NM_PLATFORM_GET); if (system_support) ifa_flags = IFA_F_NOPREFIXROUTE; - if (priv->rdisc_use_tempaddr == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR + if ( priv->rdisc_use_tempaddr == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR || priv->rdisc_use_tempaddr == NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR) { /* without system_support, this flag will be ignored. Still set it, doesn't seem to do any harm. */ @@ -4707,7 +5443,7 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *self) g_return_if_fail (priv->act_request); if (!priv->ac_ip6_config) - priv->ac_ip6_config = nm_ip6_config_new (); + priv->ac_ip6_config = nm_ip6_config_new (nm_device_get_ip_ifindex (self)); if (changed & NM_RDISC_CONFIG_GATEWAYS) { /* Use the first gateway as ordered in router discovery cache. */ @@ -4805,10 +5541,11 @@ rdisc_config_changed (NMRDisc *rdisc, NMRDiscConfigMap changed, NMDevice *self) "Activation: Stage 3 of 5 (IP Configure Start) starting DHCPv6" " as requested by IPv6 router..."); if (!dhcp6_start (self, FALSE, &reason)) { - if (priv->dhcp6_mode == NM_RDISC_DHCP_LEVEL_MANAGED) + if (priv->dhcp6_mode == NM_RDISC_DHCP_LEVEL_MANAGED) { nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); + return; + } } - return; } } @@ -4854,10 +5591,15 @@ addrconf6_start_with_link_ready (NMDevice *self) g_assert (priv->rdisc); if (nm_platform_link_get_ipv6_token (NM_PLATFORM_GET, priv->ifindex, &iid)) { - _LOGD (LOGD_DEVICE, "IPv6 tokenized identifier present on device %s", priv->iface); - } else if (!nm_device_get_ip_iface_identifier (self, &iid)) { - _LOGW (LOGD_IP6, "failed to get interface identifier; IPv6 cannot continue"); - return FALSE; + _LOGD (LOGD_IP6, "addrconf6: IPv6 tokenized identifier present"); + nm_rdisc_set_iid (priv->rdisc, iid); + } else if (nm_device_get_ip_iface_identifier (self, &iid)) { + _LOGD (LOGD_IP6, "addrconf6: using the device EUI-64 identifier"); + nm_rdisc_set_iid (priv->rdisc, iid); + } else { + /* Don't abort the addrconf at this point -- if rdisc needs the iid + * it will notice this itself. */ + _LOGI (LOGD_IP6, "addrconf6: no interface identifier; IPv6 adddress creation may fail"); } /* Apply any manual configuration before starting RA */ @@ -4878,7 +5620,6 @@ addrconf6_start_with_link_ready (NMDevice *self) G_CALLBACK (rdisc_ra_timeout), self); - nm_rdisc_set_iid (priv->rdisc, iid); nm_rdisc_start (priv->rdisc); return TRUE; } @@ -4889,9 +5630,10 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *connection; NMActStageReturn ret; - const char *ip_iface = nm_device_get_ip_iface (self); + NMSettingIP6Config *s_ip6 = NULL; + GError *error = NULL; - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); g_assert (connection); g_warn_if_fail (priv->ac_ip6_config == NULL); @@ -4900,14 +5642,27 @@ addrconf6_start (NMDevice *self, NMSettingIP6ConfigPrivacy use_tempaddr) priv->ac_ip6_config = NULL; } - priv->rdisc = nm_lndp_rdisc_new (nm_device_get_ip_ifindex (self), ip_iface); + s_ip6 = NM_SETTING_IP6_CONFIG (nm_connection_get_setting_ip6_config (connection)); + g_assert (s_ip6); + + priv->rdisc = nm_lndp_rdisc_new (nm_device_get_ip_ifindex (self), + nm_device_get_ip_iface (self), + nm_connection_get_uuid (connection), + nm_setting_ip6_config_get_addr_gen_mode (s_ip6), + &error); if (!priv->rdisc) { - _LOGE (LOGD_IP6, "failed to start router discovery (%s)", ip_iface); + _LOGE (LOGD_IP6, "addrconf6: failed to start router discovery: %s", error->message); + g_error_free (error); return FALSE; } priv->rdisc_use_tempaddr = use_tempaddr; - print_support_extended_ifa_flags (use_tempaddr); + + if ( NM_IN_SET (use_tempaddr, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR) + && !nm_platform_check_support_kernel_extended_ifa_flags (NM_PLATFORM_GET)) { + _LOGW (LOGD_IP6, "The kernel does not support extended IFA_FLAGS needed by NM for " + "IPv6 private addresses. This feature is not available"); + } if (!nm_setting_ip_config_get_may_fail (nm_connection_get_setting_ip6_config (connection))) nm_device_add_pending_action (self, PENDING_ACTION_AUTOCONF6, TRUE); @@ -4929,15 +5684,8 @@ addrconf6_cleanup (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - if (priv->rdisc_changed_id) { - g_signal_handler_disconnect (priv->rdisc, priv->rdisc_changed_id); - priv->rdisc_changed_id = 0; - } - - if (priv->rdisc_timeout_id) { - g_signal_handler_disconnect (priv->rdisc, priv->rdisc_timeout_id); - priv->rdisc_timeout_id = 0; - } + nm_clear_g_signal_handler (priv->rdisc, &priv->rdisc_changed_id); + nm_clear_g_signal_handler (priv->rdisc, &priv->rdisc_timeout_id); nm_device_remove_pending_action (self, PENDING_ACTION_AUTOCONF6, FALSE); @@ -5060,7 +5808,7 @@ _ip6_privacy_get (NMDevice *self) /* 1.) First look at the per-connection setting. If it is not -1 (unknown), * use it. */ - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); if (connection) { NMSettingIPConfig *s_ip6 = nm_connection_get_setting_ip6_config (connection); @@ -5126,7 +5874,7 @@ act_stage3_ip6_config_start (NMDevice *self, g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); g_assert (connection); if ( connection_ip6_method_requires_carrier (connection, NULL) @@ -5208,7 +5956,7 @@ act_stage3_ip6_config_start (NMDevice *self, ret = NM_ACT_STAGE_RETURN_POSTPONE; } else if (strcmp (method, NM_SETTING_IP6_CONFIG_METHOD_MANUAL) == 0) { /* New blank config */ - *out_config = nm_ip6_config_new (); + *out_config = nm_ip6_config_new (nm_device_get_ip_ifindex (self)); g_assert (*out_config); ret = NM_ACT_STAGE_RETURN_SUCCESS; @@ -5318,61 +6066,20 @@ nm_device_activate_stage3_ip6_start (NMDevice *self) } /* - * nm_device_check_ip_failed - * - * Progress the device to appropriate state if both IPv4 and IPv6 failed - */ -static void -nm_device_check_ip_failed (NMDevice *self, gboolean may_fail) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMDeviceState state; - - if ( priv->ip4_state != IP_FAIL - || priv->ip6_state != IP_FAIL) - return; - - if (nm_device_uses_assumed_connection (self)) { - /* We have assumed configuration, but couldn't - * redo it. No problem, move to check state. */ - priv->ip4_state = priv->ip6_state = IP_DONE; - state = NM_DEVICE_STATE_IP_CHECK; - } else if ( may_fail - && get_ip_config_may_fail (self, AF_INET) - && get_ip_config_may_fail (self, AF_INET6)) { - /* Couldn't start either IPv6 and IPv4 autoconfiguration, - * but both are allowed to fail. */ - state = NM_DEVICE_STATE_SECONDARIES; - } else { - /* Autoconfiguration attempted without success. */ - state = NM_DEVICE_STATE_FAILED; - } - - nm_device_state_changed (self, - state, - NM_DEVICE_STATE_REASON_IP_CONFIG_UNAVAILABLE); -} - -/* - * nm_device_activate_stage3_ip_config_start + * activate_stage3_ip_config_start * * Begin automatic/manual IP configuration * */ -static gboolean -nm_device_activate_stage3_ip_config_start (gpointer user_data) +static void +activate_stage3_ip_config_start (NMDevice *self) { - NMDevice *self = NM_DEVICE (user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMActiveConnection *master; NMDevice *master_device; - /* Clear the activation source ID now that this stage has run */ - activation_source_clear (self, FALSE, 0); - priv->ip4_state = priv->ip6_state = IP_WAIT; - _LOGD (LOGD_DEVICE, "Activation: Stage 3 of 5 (IP Configure Start) started..."); nm_device_state_changed (self, NM_DEVICE_STATE_IP_CONFIG, NM_DEVICE_STATE_REASON_NONE); /* Device should be up before we can do anything with it */ @@ -5393,50 +6100,75 @@ nm_device_activate_stage3_ip_config_start (gpointer user_data) master_device = nm_active_connection_get_device (master); if (priv->ip4_state == IP_WAIT && priv->ip6_state == IP_WAIT) { _LOGI (LOGD_DEVICE, "Activation: connection '%s' waiting on master '%s'", - nm_connection_get_id (nm_device_get_connection (self)), + nm_connection_get_id (nm_device_get_applied_connection (self)), master_device ? nm_device_get_iface (master_device) : "(unknown)"); } - goto out; + return; } /* IPv4 */ if ( nm_device_activate_ip4_state_in_wait (self) && !nm_device_activate_stage3_ip4_start (self)) - goto out; + return; /* IPv6 */ if ( nm_device_activate_ip6_state_in_wait (self) && !nm_device_activate_stage3_ip6_start (self)) - goto out; + return; nm_device_check_ip_failed (self, TRUE); - -out: - _LOGD (LOGD_DEVICE, "Activation: Stage 3 of 5 (IP Configure Start) complete."); - return FALSE; } +static gboolean +fw_change_zone_handle (NMDevice *self, + NMFirewallManagerCallId call_id, + GError *error) +{ + NMDevicePrivate *priv; + + g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); + + priv = NM_DEVICE_GET_PRIVATE (self); + + g_return_val_if_fail (priv->fw_call == call_id, FALSE); + priv->fw_call = NULL; + + return !nm_utils_error_is_cancelled (error, FALSE); +} static void -fw_change_zone_cb (GError *error, gpointer user_data) +fw_change_zone_cb_stage2 (NMFirewallManager *firewall_manager, + NMFirewallManagerCallId call_id, + GError *error, + gpointer user_data) { - NMDevice *self; + NMDevice *self = user_data; NMDevicePrivate *priv; - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + if (!fw_change_zone_handle (self, call_id, error)) return; - self = NM_DEVICE (user_data); + /* FIXME: fail the device on error? */ + priv = NM_DEVICE_GET_PRIVATE (self); + priv->fw_ready = TRUE; - priv->fw_call = NULL; + nm_device_activate_schedule_stage3_ip_config_start (self); +} - if (error) { - /* FIXME: fail the device activation? */ - } +static void +fw_change_zone_cb_ip_check (NMFirewallManager *firewall_manager, + NMFirewallManagerCallId call_id, + GError *error, + gpointer user_data) +{ + NMDevice *self = user_data; - activation_source_schedule (self, nm_device_activate_stage3_ip_config_start, 0); - _LOGD (LOGD_DEVICE, "Activation: Stage 3 of 5 (IP Configure Start) scheduled."); + if (!fw_change_zone_handle (self, call_id, error)) + return; + + /* FIXME: fail the device on error? */ + nm_device_start_ip_check (self); } /* @@ -5457,29 +6189,31 @@ nm_device_activate_schedule_stage3_ip_config_start (NMDevice *self) priv = NM_DEVICE_GET_PRIVATE (self); g_return_if_fail (priv->act_request); - g_return_if_fail (!priv->fw_call); - /* Add the interface to the specified firewall zone */ - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); g_assert (connection); s_con = nm_connection_get_setting_connection (connection); - zone = nm_setting_connection_get_zone (s_con); - - if (nm_device_uses_assumed_connection (self)) { - _LOGD (LOGD_DEVICE, "Activation: skip setting firewall zone '%s' for assumed device", zone ? zone : "default"); - activation_source_schedule (self, nm_device_activate_stage3_ip_config_start, 0); - _LOGD (LOGD_DEVICE, "Activation: Stage 3 of 5 (IP Configure Start) scheduled."); - return; + if (!priv->fw_ready) { + if (nm_device_uses_assumed_connection (self)) + priv->fw_ready = TRUE; + else { + if (!priv->fw_call) { + zone = nm_setting_connection_get_zone (s_con); + + _LOGD (LOGD_DEVICE, "Activation: setting firewall zone '%s'", zone ? zone : "default"); + priv->fw_call = nm_firewall_manager_add_or_change_zone (nm_firewall_manager_get (), + nm_device_get_ip_iface (self), + zone, + FALSE, + fw_change_zone_cb_stage2, + self); + } + return; + } } - _LOGD (LOGD_DEVICE, "Activation: setting firewall zone '%s'", zone ? zone : "default"); - priv->fw_call = nm_firewall_manager_add_or_change_zone (nm_firewall_manager_get (), - nm_device_get_ip_iface (self), - zone, - FALSE, - fw_change_zone_cb, - self); + activation_source_schedule (self, activate_stage3_ip_config_start, AF_INET); } static NMActStageReturn @@ -5499,35 +6233,25 @@ act_stage4_ip4_config_timeout (NMDevice *self, NMDeviceStateReason *reason) * Time out on retrieving the IPv4 config. * */ -static gboolean -nm_device_activate_ip4_config_timeout (gpointer user_data) +static void +activate_stage4_ip4_config_timeout (NMDevice *self) { - NMDevice *self = NM_DEVICE (user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - /* Clear the activation source ID now that this stage has run */ - activation_source_clear (self, FALSE, AF_INET); - - _LOGD (LOGD_DEVICE | LOGD_IP4, "Activation: Stage 4 of 5 (IPv4 Configure Timeout) started..."); - ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip4_config_timeout (self, &reason); if (ret == NM_ACT_STAGE_RETURN_POSTPONE) - goto out; + return; else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); - goto out; + return; } - g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); + g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); priv->ip4_state = IP_FAIL; nm_device_check_ip_failed (self, FALSE); - -out: - _LOGD (LOGD_DEVICE | LOGD_IP4, "Activation: Stage 4 of 5 (IPv4 Configure Timeout) complete."); - return FALSE; } @@ -5547,9 +6271,7 @@ nm_device_activate_schedule_ip4_config_timeout (NMDevice *self) priv = NM_DEVICE_GET_PRIVATE (self); g_return_if_fail (priv->act_request); - activation_source_schedule (self, nm_device_activate_ip4_config_timeout, AF_INET); - - _LOGD (LOGD_DEVICE | LOGD_IP4, "Activation: Stage 4 of 5 (IPv4 Configure Timeout) scheduled..."); + activation_source_schedule (self, activate_stage4_ip4_config_timeout, AF_INET); } @@ -5566,40 +6288,30 @@ act_stage4_ip6_config_timeout (NMDevice *self, NMDeviceStateReason *reason) /* - * nm_device_activate_ip6_config_timeout + * activate_stage4_ip6_config_timeout * * Time out on retrieving the IPv6 config. * */ -static gboolean -nm_device_activate_ip6_config_timeout (gpointer user_data) +static void +activate_stage4_ip6_config_timeout (NMDevice *self) { - NMDevice *self = NM_DEVICE (user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; - /* Clear the activation source ID now that this stage has run */ - activation_source_clear (self, FALSE, AF_INET6); - - _LOGD (LOGD_DEVICE | LOGD_IP6, "Activation: Stage 4 of 5 (IPv6 Configure Timeout) started..."); - ret = NM_DEVICE_GET_CLASS (self)->act_stage4_ip6_config_timeout (self, &reason); if (ret == NM_ACT_STAGE_RETURN_POSTPONE) - goto out; - else if (ret == NM_ACT_STAGE_RETURN_FAILURE) { + return; + if (ret == NM_ACT_STAGE_RETURN_FAILURE) { nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); - goto out; + return; } g_assert (ret == NM_ACT_STAGE_RETURN_SUCCESS); priv->ip6_state = IP_FAIL; nm_device_check_ip_failed (self, FALSE); - -out: - _LOGD (LOGD_DEVICE | LOGD_IP6, "Activation: Stage 4 of 5 (IPv6 Configure Timeout) complete."); - return FALSE; } @@ -5619,9 +6331,7 @@ nm_device_activate_schedule_ip6_config_timeout (NMDevice *self) priv = NM_DEVICE_GET_PRIVATE (self); g_return_if_fail (priv->act_request); - activation_source_schedule (self, nm_device_activate_ip6_config_timeout, AF_INET6); - - _LOGD (LOGD_DEVICE | LOGD_IP6, "Activation: Stage 4 of 5 (IPv6 Configure Timeout) scheduled..."); + activation_source_schedule (self, activate_stage4_ip6_config_timeout, AF_INET6); } static gboolean @@ -5721,7 +6431,7 @@ start_sharing (NMDevice *self, NMIP4Config *config) return FALSE; } - priv->dnsmasq_state_id = g_signal_connect (priv->dnsmasq_manager, "state-changed", + priv->dnsmasq_state_id = g_signal_connect (priv->dnsmasq_manager, NM_DNS_MASQ_MANAGER_STATE_CHANGED, G_CALLBACK (dnsmasq_state_changed_cb), self); return TRUE; @@ -5738,7 +6448,7 @@ send_arps (NMDevice *self, const char *mode_arg) NMIPAddress *addr; GError *error = NULL; - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); if (!connection) return; s_ip4 = nm_connection_get_setting_ip4_config (connection); @@ -5776,10 +6486,14 @@ send_arps (NMDevice *self, const char *mode_arg) } static gboolean -arp_announce_round2 (gpointer self) +arp_announce_round2 (gpointer user_data) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMDevice *self = user_data; + NMDevicePrivate *priv; + g_return_val_if_fail (NM_IS_DEVICE (self), G_SOURCE_REMOVE); + + priv = NM_DEVICE_GET_PRIVATE (self); priv->arp_round2_id = 0; if ( priv->state >= NM_DEVICE_STATE_IP_CONFIG @@ -5794,10 +6508,7 @@ arp_cleanup (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - if (priv->arp_round2_id) { - g_source_remove (priv->arp_round2_id); - priv->arp_round2_id = 0; - } + nm_clear_g_source (&priv->arp_round2_id); } static void @@ -5813,7 +6524,7 @@ arp_announce (NMDevice *self) /* We only care about manually-configured addresses; DHCP- and autoip-configured * ones should already have been seen on the network at this point. */ - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); if (!connection) return; s_ip4 = nm_connection_get_setting_ip4_config (connection); @@ -5827,10 +6538,9 @@ arp_announce (NMDevice *self) priv->arp_round2_id = g_timeout_add_seconds (2, arp_announce_round2, self); } -static gboolean -nm_device_activate_ip4_config_commit (gpointer user_data) +static void +activate_stage5_ip4_config_commit (NMDevice *self) { - NMDevice *self = NM_DEVICE (user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMActRequest *req; const char *method; @@ -5838,14 +6548,9 @@ nm_device_activate_ip4_config_commit (gpointer user_data) NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; int ip_ifindex; - /* Clear the activation source ID now that this stage has run */ - activation_source_clear (self, FALSE, AF_INET); - - _LOGD (LOGD_DEVICE, "Activation: Stage 5 of 5 (IPv4 Commit) started..."); - req = nm_device_get_act_request (self); g_assert (req); - connection = nm_act_request_get_connection (req); + connection = nm_act_request_get_applied_connection (req); g_assert (connection); /* Interface must be IFF_UP before IP config can be applied */ @@ -5860,7 +6565,7 @@ nm_device_activate_ip4_config_commit (gpointer user_data) if (!ip4_config_merge_and_apply (self, NULL, TRUE, &reason)) { _LOGD (LOGD_DEVICE | LOGD_IP4, "Activation: Stage 5 of 5 (IPv4 Commit) failed"); nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); - goto out; + return; } /* Start IPv4 sharing if we need it */ @@ -5870,7 +6575,7 @@ nm_device_activate_ip4_config_commit (gpointer user_data) if (!start_sharing (self, priv->ip4_config)) { _LOGW (LOGD_SHARING, "Activation: Stage 5 of 5 (IPv4 Commit) start sharing failed."); nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SHARED_START_FAILED); - goto out; + return; } } @@ -5882,7 +6587,8 @@ nm_device_activate_ip4_config_commit (gpointer user_data) && (nm_device_get_state (self) > NM_DEVICE_STATE_IP_CONFIG)) { /* Notify dispatcher scripts of new DHCP4 config */ nm_dispatcher_call (DISPATCHER_ACTION_DHCP4_CHANGE, - nm_device_get_connection (self), + nm_device_get_settings_connection (self), + nm_device_get_applied_connection (self), self, NULL, NULL, @@ -5898,15 +6604,10 @@ nm_device_activate_ip4_config_commit (gpointer user_data) if (nm_device_get_state (self) == NM_DEVICE_STATE_IP_CONFIG) nm_device_state_changed (self, NM_DEVICE_STATE_IP_CHECK, NM_DEVICE_STATE_REASON_NONE); - -out: - _LOGD (LOGD_DEVICE, "Activation: Stage 5 of 5 (IPv4 Commit) complete."); - - return FALSE; } static void -nm_device_queued_ip_config_change_clear (NMDevice *self) +queued_ip4_config_change_clear (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); @@ -5915,6 +6616,13 @@ nm_device_queued_ip_config_change_clear (NMDevice *self) g_source_remove (priv->queued_ip4_config_id); priv->queued_ip4_config_id = 0; } +} + +static void +queued_ip6_config_change_clear (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + if (priv->queued_ip6_config_id) { _LOGD (LOGD_DEVICE, "clearing queued IP6 config change"); g_source_remove (priv->queued_ip6_config_id); @@ -5934,10 +6642,8 @@ nm_device_activate_schedule_ip4_config_result (NMDevice *self, NMIP4Config *conf if (config) priv->dev_ip4_config = g_object_ref (config); - nm_device_queued_ip_config_change_clear (self); - activation_source_schedule (self, nm_device_activate_ip4_config_commit, AF_INET); - - _LOGD (LOGD_DEVICE | LOGD_IP4, "Activation: Stage 5 of 5 (IPv4 Configure Commit) scheduled..."); + queued_ip4_config_change_clear (self); + activation_source_schedule (self, activate_stage5_ip4_config_commit, AF_INET); } gboolean @@ -5954,24 +6660,18 @@ nm_device_activate_ip4_state_in_wait (NMDevice *self) return NM_DEVICE_GET_PRIVATE (self)->ip4_state == IP_WAIT; } -static gboolean -nm_device_activate_ip6_config_commit (gpointer user_data) +static void +activate_stage5_ip6_config_commit (NMDevice *self) { - NMDevice *self = NM_DEVICE (user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMActRequest *req; NMConnection *connection; NMDeviceStateReason reason = NM_DEVICE_STATE_REASON_NONE; int ip_ifindex; - /* Clear the activation source ID now that this stage has run */ - activation_source_clear (self, FALSE, AF_INET6); - - _LOGD (LOGD_DEVICE, "Activation: Stage 5 of 5 (IPv6 Commit) started..."); - req = nm_device_get_act_request (self); g_assert (req); - connection = nm_act_request_get_connection (req); + connection = nm_act_request_get_applied_connection (req); g_assert (connection); /* Interface must be IFF_UP before IP config can be applied */ @@ -5983,19 +6683,23 @@ nm_device_activate_ip6_config_commit (gpointer user_data) } if (ip6_config_merge_and_apply (self, TRUE, &reason)) { - /* If IPv6 wasn't the first IP to complete, and DHCP was used, - * then ensure dispatcher scripts get the DHCP lease information. - */ - if ( priv->dhcp6_client - && nm_device_activate_ip6_state_in_conf (self) - && (nm_device_get_state (self) > NM_DEVICE_STATE_IP_CONFIG)) { - /* Notify dispatcher scripts of new DHCP6 config */ - nm_dispatcher_call (DISPATCHER_ACTION_DHCP6_CHANGE, - nm_device_get_connection (self), - self, - NULL, - NULL, - NULL); + if ( priv->dhcp6_mode != NM_RDISC_DHCP_LEVEL_NONE + && priv->ip6_state == IP_CONF) { + if (priv->dhcp6_ip6_config) { + /* If IPv6 wasn't the first IP to complete, and DHCP was used, + * then ensure dispatcher scripts get the DHCP lease information. + */ + nm_dispatcher_call (DISPATCHER_ACTION_DHCP6_CHANGE, + nm_device_get_settings_connection (self), + nm_device_get_applied_connection (self), + self, + NULL, + NULL, + NULL); + } else { + /* still waiting for first dhcp6 lease. */ + return; + } } /* Enter the IP_CHECK state if this is the first method to complete */ @@ -6010,10 +6714,6 @@ nm_device_activate_ip6_config_commit (gpointer user_data) _LOGW (LOGD_DEVICE | LOGD_IP6, "Activation: Stage 5 of 5 (IPv6 Commit) failed"); nm_device_state_changed (self, NM_DEVICE_STATE_FAILED, reason); } - - _LOGD (LOGD_DEVICE, "Activation: Stage 5 of 5 (IPv6 Commit) complete."); - - return FALSE; } void @@ -6029,9 +6729,7 @@ nm_device_activate_schedule_ip6_config_result (NMDevice *self) if (priv->ip6_state == IP_FAIL) priv->ip6_state = IP_CONF; - activation_source_schedule (self, nm_device_activate_ip6_config_commit, AF_INET6); - - _LOGD (LOGD_DEVICE | LOGD_IP6, "Activation: Stage 5 of 5 (IPv6 Commit) scheduled..."); + activation_source_schedule (self, activate_stage5_ip6_config_commit, AF_INET6); } gboolean @@ -6073,10 +6771,7 @@ dnsmasq_cleanup (NMDevice *self) if (!priv->dnsmasq_manager) return; - if (priv->dnsmasq_state_id) { - g_signal_handler_disconnect (priv->dnsmasq_manager, priv->dnsmasq_state_id); - priv->dnsmasq_state_id = 0; - } + nm_clear_g_signal_handler (priv->dnsmasq_manager, &priv->dnsmasq_state_id); nm_dnsmasq_manager_stop (priv->dnsmasq_manager); g_object_unref (priv->dnsmasq_manager); @@ -6108,14 +6803,6 @@ nm_device_get_is_nm_owned (NMDevice *self) return NM_DEVICE_GET_PRIVATE (self)->is_nm_owned; } -void -nm_device_set_nm_owned (NMDevice *self) -{ - g_return_if_fail (NM_IS_DEVICE (self)); - - NM_DEVICE_GET_PRIVATE (self)->is_nm_owned = TRUE; -} - /* * delete_on_deactivate_link_delete * @@ -6129,16 +6816,21 @@ delete_on_deactivate_link_delete (gpointer user_data) DeleteOnDeactivateData *data = user_data; NMDevice *self = data->device; + _LOGD (LOGD_DEVICE, "delete_on_deactivate: cleanup and delete virtual link #%d (id=%u)", + data->ifindex, data->idle_add_id); + if (data->device) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (data->device); + gs_free_error GError *error = NULL; g_object_remove_weak_pointer (G_OBJECT (data->device), (void **) &data->device); priv->delete_on_deactivate_data = NULL; - } - _LOGD (LOGD_DEVICE, "delete_on_deactivate: cleanup and delete virtual link #%d (id=%u)", - data->ifindex, data->idle_add_id); - nm_platform_link_delete (NM_PLATFORM_GET, data->ifindex); + if (!nm_device_unrealize (data->device, TRUE, &error)) + _LOGD (LOGD_DEVICE, "delete_on_deactivate: unrealizing %d failed (%s)", data->ifindex, error->message); + } else + nm_platform_link_delete (NM_PLATFORM_GET, data->ifindex); + g_free (data); return FALSE; } @@ -6173,7 +6865,7 @@ delete_on_deactivate_check_and_schedule (NMDevice *self, int ifindex) return; if (priv->queued_act_request) return; - if (!nm_device_is_software (self)) + if (!nm_device_is_software (self) || !nm_device_is_real (self)) return; if (nm_device_get_state (self) == NM_DEVICE_STATE_UNMANAGED) return; @@ -6193,8 +6885,330 @@ delete_on_deactivate_check_and_schedule (NMDevice *self, int ifindex) } static void +_cleanup_ip4_pre (NMDevice *self, CleanupType cleanup_type) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + priv->ip4_state = IP_NONE; + queued_ip4_config_change_clear (self); + + dhcp4_cleanup (self, cleanup_type, FALSE); + arp_cleanup (self); + dnsmasq_cleanup (self); + ipv4ll_cleanup (self); +} + +static void +_cleanup_ip6_pre (NMDevice *self, CleanupType cleanup_type) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + priv->ip6_state = IP_NONE; + queued_ip6_config_change_clear (self); + + dhcp6_cleanup (self, cleanup_type, FALSE); + linklocal6_cleanup (self); + addrconf6_cleanup (self); +} + +G_GNUC_NULL_TERMINATED +static gboolean +_hash_check_invalid_keys (GHashTable *hash, const char *setting_name, GError **error, ...) +{ + va_list ap; + const char *key; + guint found_keys = 0; + +#if NM_MORE_ASSERTS > 10 + /* Assert that the keys are unique. */ + { + gs_unref_hashtable GHashTable *check_dups = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL); + + va_start (ap, error); + while ((key = va_arg (ap, const char *))) { + if (!g_hash_table_add (check_dups, (char *) key)) + nm_assert (FALSE); + } + va_end (ap); + nm_assert (g_hash_table_size (check_dups) > 0); + } +#endif + + if (!hash || g_hash_table_size (hash) == 0) + return TRUE; + + va_start (ap, error); + while ((key = va_arg (ap, const char *))) { + if (g_hash_table_contains (hash, key)) + found_keys++; + } + va_end (ap); + + if (found_keys != g_hash_table_size (hash)) { + GHashTableIter iter; + const char *k = NULL; + const char *first_invalid_key = NULL; + + if (!error) + return FALSE; + + g_hash_table_iter_init (&iter, hash); + while (g_hash_table_iter_next (&iter, (gpointer *) &k, NULL)) { + va_start (ap, error); + while ((key = va_arg (ap, const char *))) { + if (!strcmp (key, k)) { + first_invalid_key = k; + break; + } + } + va_end (ap); + if (first_invalid_key) + break; + } + g_set_error (error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, + "Can't reapply changes to '%s%s%s' setting", + setting_name ? : "", + setting_name ? "." : "", + first_invalid_key ? : "<UNKNOWN>"); + g_return_val_if_fail (first_invalid_key, FALSE); + return FALSE; + } + + return TRUE; +} + +void +nm_device_reactivate_ip4_config (NMDevice *self, + NMSettingIPConfig *s_ip4_old, + NMSettingIPConfig *s_ip4_new) +{ + NMDevicePrivate *priv; + + g_return_if_fail (NM_IS_DEVICE (self)); + priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->ip4_state != IP_NONE) { + g_clear_object (&priv->con_ip4_config); + priv->con_ip4_config = nm_ip4_config_new (nm_device_get_ip_ifindex (self)); + nm_ip4_config_merge_setting (priv->con_ip4_config, + s_ip4_new, + nm_device_get_ip4_route_metric (self)); + + if (strcmp (nm_setting_ip_config_get_method (s_ip4_new), + nm_setting_ip_config_get_method (s_ip4_old))) { + _cleanup_ip4_pre (self, CLEANUP_TYPE_DECONFIGURE); + priv->ip4_state = IP_WAIT; + if (!nm_device_activate_stage3_ip4_start (self)) + _LOGW (LOGD_IP4, "Failed to apply IPv4 configuration"); + } else + ip4_config_merge_and_apply (self, NULL, TRUE, NULL); + } +} + +void +nm_device_reactivate_ip6_config (NMDevice *self, + NMSettingIPConfig *s_ip6_old, + NMSettingIPConfig *s_ip6_new) +{ + NMDevicePrivate *priv; + + g_return_if_fail (NM_IS_DEVICE (self)); + priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->ip6_state != IP_NONE) { + g_clear_object (&priv->con_ip6_config); + priv->con_ip6_config = nm_ip6_config_new (nm_device_get_ip_ifindex (self)); + nm_ip6_config_merge_setting (priv->con_ip6_config, + s_ip6_new, + nm_device_get_ip6_route_metric (self)); + + if (strcmp (nm_setting_ip_config_get_method (s_ip6_new), + nm_setting_ip_config_get_method (s_ip6_old))) { + _cleanup_ip6_pre (self, CLEANUP_TYPE_DECONFIGURE); + priv->ip6_state = IP_WAIT; + if (!nm_device_activate_stage3_ip6_start (self)) + _LOGW (LOGD_IP6, "Failed to apply IPv6 configuration"); + } else + ip6_config_merge_and_apply (self, TRUE, NULL); + } +} + + +/* reapply_connection: + * @connection: the new connection settings to be applied or %NULL to reapply + * the current settings connection + * @error: the error if %FALSE is returned + * + * Change configuration of an already configured device if possible. + * Updates the device's applied connection upon success. + * + * Return: %FALSE if the new configuration can not be reapplied. + */ +static gboolean +reapply_connection (NMDevice *self, + NMConnection *connection, + GError **error) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMConnection *applied = nm_device_get_applied_connection (self); + gs_unref_object NMConnection *applied_clone = NULL; + gs_unref_hashtable GHashTable *diffs = NULL; + NMConnection *con_old, *con_new; + NMSettingIPConfig *s_ip4_old, *s_ip4_new; + NMSettingIPConfig *s_ip6_old, *s_ip6_new; + + if (priv->state != NM_DEVICE_STATE_ACTIVATED) { + g_set_error_literal (error, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_NOT_ACTIVE, + "Device is not activated"); + return FALSE; + } + + nm_connection_diff (connection, + applied, + NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP | + NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS, + &diffs); + + /************************************************************************** + * check for unsupported changes and reject to reapply + *************************************************************************/ + if (!_hash_check_invalid_keys (diffs, NULL, error, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_CONNECTION_SETTING_NAME, + NULL)) + return FALSE; + + if (!_hash_check_invalid_keys (diffs ? g_hash_table_lookup (diffs, NM_SETTING_CONNECTION_SETTING_NAME) : NULL, + NM_SETTING_CONNECTION_SETTING_NAME, + error, + NM_SETTING_CONNECTION_ZONE, + NM_SETTING_CONNECTION_METERED, + NULL)) + return FALSE; + + _LOGD (LOGD_DEVICE, "reapply"); + + /************************************************************************** + * Update applied connection + *************************************************************************/ + + if (diffs) { + con_old = applied_clone = nm_simple_connection_new_clone (applied); + con_new = applied; + nm_connection_replace_settings_from_connection (applied, connection); + } else + con_old = con_new = applied; + + s_ip4_new = nm_connection_get_setting_ip4_config (con_new); + s_ip4_old = nm_connection_get_setting_ip4_config (con_old); + s_ip6_new = nm_connection_get_setting_ip6_config (con_new); + s_ip6_old = nm_connection_get_setting_ip6_config (con_old); + + /************************************************************************** + * Reapply changes + *************************************************************************/ + + nm_device_update_firewall_zone (self); + nm_device_update_metered (self); + + nm_device_reactivate_ip4_config (self, s_ip4_old, s_ip4_new); + nm_device_reactivate_ip6_config (self, s_ip6_old, s_ip6_new); + + return TRUE; +} + +static void +reapply_cb (NMDevice *self, + GDBusMethodInvocation *context, + NMAuthSubject *subject, + GError *error, + gpointer user_data) +{ + gs_unref_object NMConnection *connection = NM_CONNECTION (user_data); + GError *local = NULL; + + if (error) { + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, subject, error->message); + g_dbus_method_invocation_return_gerror (context, error); + return; + } + + if (!reapply_connection (self, + connection ? : (NMConnection *) nm_device_get_settings_connection (self), + &local)) { + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, subject, local->message); + g_dbus_method_invocation_take_error (context, local); + local = NULL; + } else { + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, TRUE, subject, NULL); + g_dbus_method_invocation_return_value (context, NULL); + } +} + +static void +impl_device_reapply (NMDevice *self, + GDBusMethodInvocation *context, + GVariant *settings, + guint flags) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMSettingsConnection *settings_connection; + NMConnection *connection = NULL; + GError *error = NULL; + + /* No flags supported as of now. */ + if (flags != 0) { + error = g_error_new_literal (NM_DEVICE_ERROR, + NM_DEVICE_ERROR_NOT_ACTIVE, + "Invalid flags specified"); + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, context, error->message); + g_dbus_method_invocation_take_error (context, error); + return; + } + + if (priv->state != NM_DEVICE_STATE_ACTIVATED) { + error = g_error_new_literal (NM_DEVICE_ERROR, + NM_DEVICE_ERROR_NOT_ACTIVE, + "Device is not activated"); + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, context, error->message); + g_dbus_method_invocation_take_error (context, error); + return; + } + + settings_connection = nm_device_get_settings_connection (self); + g_return_if_fail (settings_connection); + + if (settings && g_variant_n_children (settings)) { + /* New settings specified inline. */ + connection = nm_simple_connection_new_from_dbus (settings, &error); + if (!connection) { + g_prefix_error (&error, "The settings specified are invalid: "); + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, context, error->message); + g_dbus_method_invocation_take_error (context, error); + return; + } + nm_connection_clear_secrets (connection); + } + + /* Ask the manager to authenticate this request for us */ + g_signal_emit (self, signals[AUTH_REQUEST], 0, + context, + nm_device_get_applied_connection (self), + NM_AUTH_PERMISSION_NETWORK_CONTROL, + TRUE, + reapply_cb, + connection); +} + +static void disconnect_cb (NMDevice *self, - DBusGMethodInvocation *context, + GDBusMethodInvocation *context, + NMAuthSubject *subject, GError *error, gpointer user_data) { @@ -6202,7 +7216,8 @@ disconnect_cb (NMDevice *self, GError *local = NULL; if (error) { - dbus_g_method_return_error (context, error); + g_dbus_method_invocation_return_gerror (context, error); + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DISCONNECT, self, FALSE, subject, error->message); return; } @@ -6211,15 +7226,16 @@ disconnect_cb (NMDevice *self, local = g_error_new_literal (NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_ACTIVE, "Device is not active"); - dbus_g_method_return_error (context, local); - g_error_free (local); + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DISCONNECT, self, FALSE, subject, local->message); + g_dbus_method_invocation_take_error (context, local); } else { nm_device_set_autoconnect (self, FALSE); nm_device_state_changed (self, NM_DEVICE_STATE_DEACTIVATING, NM_DEVICE_STATE_REASON_USER_REQUESTED); - dbus_g_method_return (context); + g_dbus_method_invocation_return_value (context, NULL); + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DISCONNECT, self, TRUE, subject, NULL); } } @@ -6233,7 +7249,7 @@ _clear_queued_act_request (NMDevicePrivate *priv) } static void -impl_device_disconnect (NMDevice *self, DBusGMethodInvocation *context) +impl_device_disconnect (NMDevice *self, GDBusMethodInvocation *context) { NMConnection *connection; GError *error = NULL; @@ -6242,12 +7258,11 @@ impl_device_disconnect (NMDevice *self, DBusGMethodInvocation *context) error = g_error_new_literal (NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_ACTIVE, "This device is not active"); - dbus_g_method_return_error (context, error); - g_error_free (error); + g_dbus_method_invocation_take_error (context, error); return; } - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); g_assert (connection); /* Ask the manager to authenticate this request for us */ @@ -6262,31 +7277,37 @@ impl_device_disconnect (NMDevice *self, DBusGMethodInvocation *context) static void delete_cb (NMDevice *self, - DBusGMethodInvocation *context, + GDBusMethodInvocation *context, + NMAuthSubject *subject, GError *error, gpointer user_data) { + GError *local = NULL; + if (error) { - dbus_g_method_return_error (context, error); + g_dbus_method_invocation_return_gerror (context, error); + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DELETE, self, FALSE, subject, error->message); return; } /* Authorized */ - nm_platform_link_delete (NM_PLATFORM_GET, nm_device_get_ifindex (self)); - dbus_g_method_return (context); + nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_DELETE, self, TRUE, subject, NULL); + if (nm_device_unrealize (self, TRUE, &local)) + g_dbus_method_invocation_return_value (context, NULL); + else + g_dbus_method_invocation_take_error (context, local); } static void -impl_device_delete (NMDevice *self, DBusGMethodInvocation *context) +impl_device_delete (NMDevice *self, GDBusMethodInvocation *context) { GError *error = NULL; - if (!nm_device_is_software (self)) { + if (!nm_device_is_software (self) || !nm_device_is_real (self)) { error = g_error_new_literal (NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_SOFTWARE, - "This device is not a software device"); - dbus_g_method_return_error (context, error); - g_error_free (error); + "This device is not a software device or is not realized"); + g_dbus_method_invocation_take_error (context, error); return; } @@ -6317,7 +7338,7 @@ _device_activate (NMDevice *self, NMActRequest *req) priv = NM_DEVICE_GET_PRIVATE (self); - connection = nm_act_request_get_connection (req); + connection = nm_act_request_get_applied_connection (req); g_assert (connection); _LOGI (LOGD_DEVICE, "Activation: starting connection '%s' (%s)", @@ -6378,7 +7399,7 @@ _carrier_wait_check_act_request_must_queue (NMDevice *self, NMActRequest *req) if (priv->carrier_wait_id == 0) return FALSE; - connection = nm_act_request_get_connection (req); + connection = nm_act_request_get_applied_connection (req); if (!connection_requires_carrier (connection)) return FALSE; @@ -6408,19 +7429,19 @@ _carrier_wait_check_act_request_must_queue (NMDevice *self, NMActRequest *req) } void -nm_device_steal_connection (NMDevice *self, NMConnection *connection) +nm_device_steal_connection (NMDevice *self, NMSettingsConnection *connection) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); _LOGW (LOGD_DEVICE, "disconnecting connection '%s' for new activation request.", - nm_connection_get_id (connection)); + nm_settings_connection_get_id (connection)); if ( priv->queued_act_request - && connection == nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (priv->queued_act_request))) + && connection == nm_active_connection_get_settings_connection (NM_ACTIVE_CONNECTION (priv->queued_act_request))) _clear_queued_act_request (priv); if ( priv->act_request - && connection == nm_active_connection_get_connection (NM_ACTIVE_CONNECTION (priv->act_request)) + && connection == nm_active_connection_get_settings_connection (NM_ACTIVE_CONNECTION (priv->act_request)) && priv->state < NM_DEVICE_STATE_DEACTIVATING) nm_device_state_changed (self, NM_DEVICE_STATE_DEACTIVATING, @@ -6481,7 +7502,7 @@ nm_device_is_activating (NMDevice *self) * handler is actually run. If there's an activation handler scheduled * we're activating anyway. */ - return priv->act_source_id ? TRUE : FALSE; + return priv->act_handle4.id ? TRUE : FALSE; } /* IP Configuration stuff */ @@ -6516,13 +7537,19 @@ nm_device_set_ip4_config (NMDevice *self, gboolean has_changes = FALSE; gboolean success = TRUE; NMDeviceStateReason reason_local = NM_DEVICE_STATE_REASON_NONE; - int ip_ifindex; + int ip_ifindex, config_ifindex; g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); priv = NM_DEVICE_GET_PRIVATE (self); ip_ifindex = nm_device_get_ip_ifindex (self); + if (new_config) { + config_ifindex = nm_ip4_config_get_ifindex (new_config); + if (config_ifindex > 0) + g_return_val_if_fail (ip_ifindex == config_ifindex, FALSE); + } + old_config = priv->ip4_config; /* Always commit to nm-platform to update lifetimes */ @@ -6548,25 +7575,23 @@ nm_device_set_ip4_config (NMDevice *self, nm_ip4_config_replace (old_config, new_config, &has_changes); if (has_changes) { _LOGD (LOGD_IP4, "update IP4Config instance (%s)", - nm_ip4_config_get_dbus_path (old_config)); + nm_exported_object_get_path (NM_EXPORTED_OBJECT (old_config))); } } else { has_changes = TRUE; priv->ip4_config = g_object_ref (new_config); - if (success && !nm_ip4_config_get_dbus_path (new_config)) { - /* Export over D-Bus */ - nm_ip4_config_export (new_config); - } + if (success && !nm_exported_object_is_exported (NM_EXPORTED_OBJECT (new_config))) + nm_exported_object_export (NM_EXPORTED_OBJECT (new_config)); _LOGD (LOGD_IP4, "set IP4Config instance (%s)", - nm_ip4_config_get_dbus_path (new_config)); + nm_exported_object_get_path (NM_EXPORTED_OBJECT (new_config))); } } else if (old_config) { has_changes = TRUE; priv->ip4_config = NULL; _LOGD (LOGD_IP4, "clear IP4Config instance (%s)", - nm_ip4_config_get_dbus_path (old_config)); + nm_exported_object_get_path (NM_EXPORTED_OBJECT (old_config))); /* Device config is invalid if combined config is invalid */ g_clear_object (&priv->dev_ip4_config); } @@ -6580,17 +7605,26 @@ nm_device_set_ip4_config (NMDevice *self, g_object_notify (G_OBJECT (self), NM_DEVICE_IP4_CONFIG); g_signal_emit (self, signals[IP4_CONFIG_CHANGED], 0, priv->ip4_config, old_config); - if (old_config != priv->ip4_config && old_config) - g_object_unref (old_config); + if (old_config != priv->ip4_config) + nm_exported_object_clear_and_unexport (&old_config); if (nm_device_uses_generated_assumed_connection (self)) { - NMConnection *connection = nm_device_get_connection (self); + NMConnection *connection = nm_device_get_applied_connection (self); + NMConnection *settings_connection = NM_CONNECTION (nm_device_get_settings_connection (self)); NMSetting *s_ip4; g_object_freeze_notify (G_OBJECT (connection)); + g_object_freeze_notify (G_OBJECT (settings_connection)); + + nm_connection_remove_setting (settings_connection, NM_TYPE_SETTING_IP4_CONFIG); + s_ip4 = nm_ip4_config_create_setting (priv->ip4_config); + nm_connection_add_setting (settings_connection, s_ip4); + nm_connection_remove_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); s_ip4 = nm_ip4_config_create_setting (priv->ip4_config); nm_connection_add_setting (connection, s_ip4); + + g_object_thaw_notify (G_OBJECT (settings_connection)); g_object_thaw_notify (G_OBJECT (connection)); } @@ -6603,18 +7637,49 @@ nm_device_set_ip4_config (NMDevice *self, return success; } +static gboolean +_replace_vpn_config_in_list (GSList **plist, GObject *old, GObject *new) +{ + GSList *old_link; + + /* Below, assert that we have an @old instance to replace and that + * @new is not yet tracked. But still, behave correctly in any + * case. */ + + if ( old + && (old_link = g_slist_find (*plist, old))) { + if (old != new) { + if (new) + old_link->data = g_object_ref (new); + else + *plist = g_slist_remove_link (*plist, old_link); + g_object_unref (old); + } + return TRUE; + } + + if (new) { + if (!g_slist_find (*plist, new)) + *plist = g_slist_append (*plist, g_object_ref (new)); + else + g_return_val_if_reached (TRUE); + g_return_val_if_fail (!old, TRUE); + return TRUE; + } + + /* return FALSE if both @old and @new are unset. */ + g_return_val_if_fail (!old, FALSE); + return FALSE; +} + void -nm_device_set_vpn4_config (NMDevice *self, NMIP4Config *config) +nm_device_replace_vpn4_config (NMDevice *self, NMIP4Config *old, NMIP4Config *config) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - if (priv->vpn4_config == config) + if (!_replace_vpn_config_in_list (&priv->vpn4_configs, (GObject *) old, (GObject *) config)) return; - g_clear_object (&priv->vpn4_config); - if (config) - priv->vpn4_config = g_object_ref (config); - /* NULL to use existing configs */ if (!ip4_config_merge_and_apply (self, NULL, TRUE, NULL)) _LOGW (LOGD_IP4, "failed to set VPN routes for device"); @@ -6649,13 +7714,19 @@ nm_device_set_ip6_config (NMDevice *self, gboolean has_changes = FALSE; gboolean success = TRUE; NMDeviceStateReason reason_local = NM_DEVICE_STATE_REASON_NONE; - int ip_ifindex; + int ip_ifindex, config_ifindex; g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); priv = NM_DEVICE_GET_PRIVATE (self); ip_ifindex = nm_device_get_ip_ifindex (self); + if (new_config) { + config_ifindex = nm_ip6_config_get_ifindex (new_config); + if (config_ifindex > 0) + g_return_val_if_fail (ip_ifindex == config_ifindex, FALSE); + } + old_config = priv->ip6_config; /* Always commit to nm-platform to update lifetimes */ @@ -6675,25 +7746,23 @@ nm_device_set_ip6_config (NMDevice *self, nm_ip6_config_replace (old_config, new_config, &has_changes); if (has_changes) { _LOGD (LOGD_IP6, "update IP6Config instance (%s)", - nm_ip6_config_get_dbus_path (old_config)); + nm_exported_object_get_path (NM_EXPORTED_OBJECT (old_config))); } } else { has_changes = TRUE; priv->ip6_config = g_object_ref (new_config); - if (success && !nm_ip6_config_get_dbus_path (new_config)) { - /* Export over D-Bus */ - nm_ip6_config_export (new_config); - } + if (success && !nm_exported_object_is_exported (NM_EXPORTED_OBJECT (new_config))) + nm_exported_object_export (NM_EXPORTED_OBJECT (new_config)); _LOGD (LOGD_IP6, "set IP6Config instance (%s)", - nm_ip6_config_get_dbus_path (new_config)); + nm_exported_object_get_path (NM_EXPORTED_OBJECT (new_config))); } } else if (old_config) { has_changes = TRUE; priv->ip6_config = NULL; _LOGD (LOGD_IP6, "clear IP6Config instance (%s)", - nm_ip6_config_get_dbus_path (old_config)); + nm_exported_object_get_path (NM_EXPORTED_OBJECT (old_config))); } nm_default_route_manager_ip6_update_default_route (nm_default_route_manager_get (), self); @@ -6703,17 +7772,26 @@ nm_device_set_ip6_config (NMDevice *self, g_object_notify (G_OBJECT (self), NM_DEVICE_IP6_CONFIG); g_signal_emit (self, signals[IP6_CONFIG_CHANGED], 0, priv->ip6_config, old_config); - if (old_config != priv->ip6_config && old_config) - g_object_unref (old_config); + if (old_config != priv->ip6_config) + nm_exported_object_clear_and_unexport (&old_config); if (nm_device_uses_generated_assumed_connection (self)) { - NMConnection *connection = nm_device_get_connection (self); + NMConnection *connection = nm_device_get_applied_connection (self); + NMConnection *settings_connection = NM_CONNECTION (nm_device_get_settings_connection (self)); NMSetting *s_ip6; g_object_freeze_notify (G_OBJECT (connection)); + g_object_freeze_notify (G_OBJECT (settings_connection)); + + nm_connection_remove_setting (settings_connection, NM_TYPE_SETTING_IP6_CONFIG); + s_ip6 = nm_ip6_config_create_setting (priv->ip6_config); + nm_connection_add_setting (settings_connection, s_ip6); + nm_connection_remove_setting (connection, NM_TYPE_SETTING_IP6_CONFIG); s_ip6 = nm_ip6_config_create_setting (priv->ip6_config); nm_connection_add_setting (connection, s_ip6); + + g_object_thaw_notify (G_OBJECT (settings_connection)); g_object_thaw_notify (G_OBJECT (connection)); } @@ -6727,17 +7805,13 @@ nm_device_set_ip6_config (NMDevice *self, } void -nm_device_set_vpn6_config (NMDevice *self, NMIP6Config *config) +nm_device_replace_vpn6_config (NMDevice *self, NMIP6Config *old, NMIP6Config *config) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - if (priv->vpn6_config == config) + if (!_replace_vpn_config_in_list (&priv->vpn6_configs, (GObject *) old, (GObject *) config)) return; - g_clear_object (&priv->vpn6_config); - if (config) - priv->vpn6_config = g_object_ref (config); - /* NULL to use existing configs */ if (!ip6_config_merge_and_apply (self, TRUE, NULL)) _LOGW (LOGD_IP6, "failed to set VPN routes for device"); @@ -6821,7 +7895,8 @@ ip_check_pre_up (NMDevice *self) priv->dispatcher.post_state = NM_DEVICE_STATE_SECONDARIES; priv->dispatcher.post_state_reason = NM_DEVICE_STATE_REASON_NONE; if (!nm_dispatcher_call (DISPATCHER_ACTION_PRE_UP, - nm_device_get_connection (self), + nm_device_get_settings_connection (self), + nm_device_get_applied_connection (self), self, dispatcher_complete_proceed_state, self, @@ -6904,7 +7979,7 @@ ip_check_ping_watch_cb (GPid pid, gint status, gpointer user_data) { NMDevice *self = NM_DEVICE (user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - guint log_domain = priv->gw_ping.log_domain; + NMLogDomain log_domain = priv->gw_ping.log_domain; gboolean success = FALSE; if (!priv->gw_ping.watch) @@ -6951,7 +8026,7 @@ ip_check_ping_timeout_cb (gpointer user_data) static gboolean start_ping (NMDevice *self, - guint log_domain, + NMLogDomain log_domain, const char *binary, const char *address, guint timeout) @@ -6985,7 +8060,7 @@ nm_device_start_ip_check (NMDevice *self) guint timeout = 0; const char *ping_binary = NULL; char buf[INET6_ADDRSTRLEN] = { 0 }; - guint log_domain = LOGD_IP4; + NMLogDomain log_domain = LOGD_IP4; /* Shouldn't be any active ping here, since IP_CHECK happens after the * first IP method completes. Any subsequently completing IP method doesn't @@ -6996,7 +8071,7 @@ nm_device_start_ip_check (NMDevice *self) g_assert (!priv->gw_ping.pid); g_assert (priv->ip4_state == IP_DONE || priv->ip6_state == IP_DONE); - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); g_assert (connection); s_con = nm_connection_get_setting_connection (connection); @@ -7210,12 +8285,33 @@ nm_device_get_firmware_missing (NMDevice *self) return NM_DEVICE_GET_PRIVATE (self)->firmware_missing; } +void +nm_device_set_nm_plugin_missing (NMDevice *self, gboolean new_missing) +{ + NMDevicePrivate *priv; + + g_return_if_fail (NM_IS_DEVICE (self)); + + priv = NM_DEVICE_GET_PRIVATE (self); + if (priv->nm_plugin_missing != new_missing) { + priv->nm_plugin_missing = new_missing; + g_object_notify (G_OBJECT (self), NM_DEVICE_NM_PLUGIN_MISSING); + } +} + +gboolean +nm_device_get_nm_plugin_missing (NMDevice *self) +{ + return NM_DEVICE_GET_PRIVATE (self)->nm_plugin_missing; +} + static NMIP4Config * find_ip4_lease_config (NMDevice *self, NMConnection *connection, NMIP4Config *ext_ip4_config) { const char *ip_iface = nm_device_get_ip_iface (self); + int ip_ifindex = nm_device_get_ip_ifindex (self); GSList *leases, *liter; NMIP4Config *found = NULL; @@ -7224,6 +8320,7 @@ find_ip4_lease_config (NMDevice *self, leases = nm_dhcp_manager_get_lease_ip_configs (nm_dhcp_manager_get (), ip_iface, + ip_ifindex, nm_connection_get_uuid (connection), FALSE, nm_device_get_ip4_route_metric (self)); @@ -7310,6 +8407,24 @@ capture_lease_config (NMDevice *self, } static void +_ip4_config_intersect (gpointer value, gpointer user_data) +{ + NMIP4Config *dst = (NMIP4Config *) value; + NMIP4Config *src = (NMIP4Config *) user_data; + + nm_ip4_config_intersect (dst, src); +} + +static void +_ip4_config_subtract (gpointer value, gpointer user_data) +{ + NMIP4Config *dst = (NMIP4Config *) user_data; + NMIP4Config *src = (NMIP4Config *) value; + + nm_ip4_config_subtract (dst, src); +} + +static void update_ip4_config (NMDevice *self, gboolean initial) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); @@ -7339,15 +8454,16 @@ update_ip4_config (NMDevice *self, gboolean initial) * kernel routes. */ /* This function was called upon external changes. Remove the configuration - * (adresses,routes) that is no longer present externally from the interal - * config. This way, we don't readd addresses that were manually removed + * (addresses,routes) that is no longer present externally from the internal + * config. This way, we don't re-add addresses that were manually removed * by the user. */ if (priv->con_ip4_config) nm_ip4_config_intersect (priv->con_ip4_config, priv->ext_ip4_config); if (priv->dev_ip4_config) nm_ip4_config_intersect (priv->dev_ip4_config, priv->ext_ip4_config); - if (priv->vpn4_config) - nm_ip4_config_intersect (priv->vpn4_config, priv->ext_ip4_config); + + g_slist_foreach (priv->vpn4_configs, _ip4_config_intersect, priv->ext_ip4_config); + if (priv->wwan_ip4_config) nm_ip4_config_intersect (priv->wwan_ip4_config, priv->ext_ip4_config); @@ -7358,8 +8474,9 @@ update_ip4_config (NMDevice *self, gboolean initial) nm_ip4_config_subtract (priv->ext_ip4_config, priv->con_ip4_config); if (priv->dev_ip4_config) nm_ip4_config_subtract (priv->ext_ip4_config, priv->dev_ip4_config); - if (priv->vpn4_config) - nm_ip4_config_subtract (priv->ext_ip4_config, priv->vpn4_config); + + g_slist_foreach (priv->vpn4_configs, _ip4_config_subtract, priv->ext_ip4_config); + if (priv->wwan_ip4_config) nm_ip4_config_subtract (priv->ext_ip4_config, priv->wwan_ip4_config); @@ -7368,6 +8485,24 @@ update_ip4_config (NMDevice *self, gboolean initial) } static void +_ip6_config_intersect (gpointer value, gpointer user_data) +{ + NMIP6Config *dst = (NMIP6Config *) value; + NMIP6Config *src = (NMIP6Config *) user_data; + + nm_ip6_config_intersect (dst, src); +} + +static void +_ip6_config_subtract (gpointer value, gpointer user_data) +{ + NMIP6Config *dst = (NMIP6Config *) user_data; + NMIP6Config *src = (NMIP6Config *) value; + + nm_ip6_config_subtract (dst, src); +} + +static void update_ip6_config (NMDevice *self, gboolean initial) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); @@ -7393,8 +8528,8 @@ update_ip6_config (NMDevice *self, gboolean initial) have_ip6_address (priv->ext_ip6_config, TRUE); /* This function was called upon external changes. Remove the configuration - * (adresses,routes) that is no longer present externally from the interal - * config. This way, we don't readd addresses that were manually removed + * (addresses,routes) that is no longer present externally from the internal + * config. This way, we don't re-add addresses that were manually removed * by the user. */ if (priv->con_ip6_config) nm_ip6_config_intersect (priv->con_ip6_config, priv->ext_ip6_config); @@ -7404,8 +8539,7 @@ update_ip6_config (NMDevice *self, gboolean initial) nm_ip6_config_intersect (priv->dhcp6_ip6_config, priv->ext_ip6_config); if (priv->wwan_ip6_config) nm_ip6_config_intersect (priv->wwan_ip6_config, priv->ext_ip6_config); - if (priv->vpn6_config) - nm_ip6_config_intersect (priv->vpn6_config, priv->ext_ip6_config); + g_slist_foreach (priv->vpn6_configs, _ip6_config_intersect, priv->ext_ip6_config); /* Remove parts from ext_ip6_config to only contain the information that * was configured externally -- we already have the same configuration from @@ -7418,8 +8552,7 @@ update_ip6_config (NMDevice *self, gboolean initial) nm_ip6_config_subtract (priv->ext_ip6_config, priv->dhcp6_ip6_config); if (priv->wwan_ip6_config) nm_ip6_config_subtract (priv->ext_ip6_config, priv->wwan_ip6_config); - if (priv->vpn6_config) - nm_ip6_config_subtract (priv->ext_ip6_config, priv->vpn6_config); + g_slist_foreach (priv->vpn6_configs, _ip6_config_subtract, priv->ext_ip6_config); ip6_config_merge_and_apply (self, FALSE, NULL); } @@ -7462,6 +8595,8 @@ queued_ip6_config_change (gpointer user_data) { NMDevice *self = NM_DEVICE (user_data); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + GSList *iter; + gboolean need_ipv6ll = FALSE; /* Wait for any queued state changes */ if (priv->queued_state.id) @@ -7471,13 +8606,38 @@ queued_ip6_config_change (gpointer user_data) g_object_ref (self); update_ip6_config (self, FALSE); - /* If no IPv6 link-local address exists but other addresses do then we - * must add the LL address to remain conformant with RFC 3513 chapter 2.1 - * ("Addressing Model"): "All interfaces are required to have at least - * one link-local unicast address". - */ - if (priv->ip6_config && nm_ip6_config_get_num_addresses (priv->ip6_config)) - check_and_add_ipv6ll_addr (self); + if ( nm_platform_link_get (NM_PLATFORM_GET, priv->ifindex) + && priv->state < NM_DEVICE_STATE_DEACTIVATING) { + /* Handle DAD falures */ + for (iter = priv->dad6_failed_addrs; iter; iter = g_slist_next (iter)) { + NMPlatformIP6Address *addr = iter->data; + + if (addr->source >= NM_IP_CONFIG_SOURCE_USER) + continue; + + _LOGI (LOGD_IP6, "ipv6: duplicate address check failed for the %s address", + nm_platform_ip6_address_to_string (addr, NULL, 0)); + + if (IN6_IS_ADDR_LINKLOCAL (&addr->address)) + need_ipv6ll = TRUE; + else if (priv->rdisc) + nm_rdisc_dad_failed (priv->rdisc, &addr->address); + } + + /* If no IPv6 link-local address exists but other addresses do then we + * must add the LL address to remain conformant with RFC 3513 chapter 2.1 + * ("Addressing Model"): "All interfaces are required to have at least + * one link-local unicast address". + */ + if (priv->ip6_config && nm_ip6_config_get_num_addresses (priv->ip6_config)) + need_ipv6ll = TRUE; + + if (need_ipv6ll) + check_and_add_ipv6ll_addr (self); + } + + g_slist_free_full (priv->dad6_failed_addrs, g_free); + priv->dad6_failed_addrs = NULL; g_object_unref (self); @@ -7490,15 +8650,16 @@ device_ipx_changed (NMPlatform *platform, int ifindex, gpointer platform_object, NMPlatformSignalChangeType change_type, - NMPlatformReason reason, NMDevice *self) { NMDevicePrivate *priv; + NMPlatformIP6Address *addr; if (nm_device_get_ip_ifindex (self) != ifindex) return; priv = NM_DEVICE_GET_PRIVATE (self); + switch (obj_type) { case NMP_OBJECT_TYPE_IP4_ADDRESS: case NMP_OBJECT_TYPE_IP4_ROUTE: @@ -7508,6 +8669,16 @@ device_ipx_changed (NMPlatform *platform, } break; case NMP_OBJECT_TYPE_IP6_ADDRESS: + addr = platform_object; + + if ( priv->state > NM_DEVICE_STATE_DISCONNECTED + && priv->state < NM_DEVICE_STATE_DEACTIVATING + && ( (change_type == NM_PLATFORM_SIGNAL_CHANGED && addr->flags & IFA_F_DADFAILED) + || (change_type == NM_PLATFORM_SIGNAL_REMOVED && addr->flags & IFA_F_TENTATIVE))) { + priv->dad6_failed_addrs = g_slist_append (priv->dad6_failed_addrs, + g_memdup (addr, sizeof (NMPlatformIP6Address))); + } + /* fallthrough */ case NMP_OBJECT_TYPE_IP6_ROUTE: if (!priv->queued_ip6_config_id) { priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self); @@ -7540,23 +8711,24 @@ nm_device_get_managed (NMDevice *self) * default-unmanaged flag (eg, only NM_UNMANAGED_DEFAULT is set) then * the device is managed whenever it's not in the UNMANAGED state. */ - managed = !(priv->unmanaged_flags & ~NM_UNMANAGED_DEFAULT); - if (managed && (priv->unmanaged_flags & NM_UNMANAGED_DEFAULT)) + managed = !NM_FLAGS_ANY (priv->unmanaged_flags, ~NM_UNMANAGED_DEFAULT); + if (managed && NM_FLAGS_HAS (priv->unmanaged_flags, NM_UNMANAGED_DEFAULT)) managed = (priv->state > NM_DEVICE_STATE_UNMANAGED); return managed; } /** - * nm_device_get_unmanaged_flag(): + * nm_device_get_unmanaged_flags(): * @self: the #NMDevice + * @flag: return only the selected flags * - * Returns: %TRUE if the device is unmanaged for @flag. + * Returns: the unmanage flags of the device (filtered with @flag) */ -gboolean -nm_device_get_unmanaged_flag (NMDevice *self, NMUnmanagedFlags flag) +NMUnmanagedFlags +nm_device_get_unmanaged_flags (NMDevice *self, NMUnmanagedFlags flag) { - return NM_FLAGS_ANY (NM_DEVICE_GET_PRIVATE (self)->unmanaged_flags, flag); + return NM_DEVICE_GET_PRIVATE (self)->unmanaged_flags & flag; } /** @@ -7568,14 +8740,42 @@ nm_device_get_unmanaged_flag (NMDevice *self, NMUnmanagedFlags flag) static gboolean nm_device_get_default_unmanaged (NMDevice *self) { - return nm_device_get_unmanaged_flag (self, NM_UNMANAGED_DEFAULT); + return !!nm_device_get_unmanaged_flags (self, NM_UNMANAGED_DEFAULT); +} + +static void +_set_unmanaged_flags (NMDevice *self, + NMUnmanagedFlags flags, + gboolean unmanaged) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (unmanaged) { + if (!NM_FLAGS_ALL (priv->unmanaged_flags, flags)) { + _LOGD (LOGD_DEVICE, "unmanaged: flags set to 0x%0llx (was 0x%0llx, %s 0x%0llx)", + (long long unsigned) (priv->unmanaged_flags | flags), + (long long unsigned) priv->unmanaged_flags, + "set", + (long long unsigned) flags); + priv->unmanaged_flags |= flags; + } + } else { + if (NM_FLAGS_ANY (priv->unmanaged_flags, flags)) { + _LOGD (LOGD_DEVICE, "unmanaged: flags set to 0x%0llx (was 0x%0llx, %s 0x%0llx)", + (long long unsigned) (priv->unmanaged_flags & (~flags)), + (long long unsigned) priv->unmanaged_flags, + "clear", + (long long unsigned) flags); + priv->unmanaged_flags &= ~flags; + } + } } void -nm_device_set_unmanaged (NMDevice *self, - NMUnmanagedFlags flag, - gboolean unmanaged, - NMDeviceStateReason reason) +nm_device_set_unmanaged_flags (NMDevice *self, + NMUnmanagedFlags flag, + gboolean unmanaged, + NMDeviceStateReason reason) { NMDevicePrivate *priv; gboolean was_managed, now_managed; @@ -7586,10 +8786,7 @@ nm_device_set_unmanaged (NMDevice *self, priv = NM_DEVICE_GET_PRIVATE (self); was_managed = nm_device_get_managed (self); - if (unmanaged) - priv->unmanaged_flags |= flag; - else - priv->unmanaged_flags &= ~flag; + _set_unmanaged_flags (self, flag, unmanaged); now_managed = nm_device_get_managed (self); if (was_managed != now_managed) { @@ -7605,34 +8802,41 @@ nm_device_set_unmanaged (NMDevice *self, } void -nm_device_set_unmanaged_quitting (NMDevice *self) +nm_device_set_unmanaged_flags_by_device_spec (NMDevice *self, const GSList *unmanaged_specs) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMDevicePrivate *priv; + gboolean unmanaged; - /* It's OK to block here because we're quitting */ - if (nm_device_is_activating (self) || priv->state == NM_DEVICE_STATE_ACTIVATED) - _set_state_full (self, NM_DEVICE_STATE_DEACTIVATING, NM_DEVICE_STATE_REASON_NOW_UNMANAGED, TRUE); + g_return_if_fail (NM_IS_DEVICE (self)); + + priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->managed_touched_by_user) + return; - nm_device_set_unmanaged (self, - NM_UNMANAGED_INTERNAL, - TRUE, - NM_DEVICE_STATE_REASON_NOW_UNMANAGED); + unmanaged = nm_device_spec_match_list (self, unmanaged_specs); + nm_device_set_unmanaged_flags (self, + NM_UNMANAGED_USER, + unmanaged, + unmanaged + ? NM_DEVICE_STATE_REASON_NOW_UNMANAGED + : NM_DEVICE_STATE_REASON_NOW_MANAGED); } /** - * nm_device_set_initial_unmanaged_flag(): + * nm_device_set_unmanaged_flags_initial(): * @self: the #NMDevice * @flag: an #NMUnmanagedFlag * @unmanaged: %TRUE or %FALSE to set or clear @flag * - * Like nm_device_set_unmanaged(), but must be set before the device is + * Like nm_device_set_unmanaged_flags(), but must be set before the device is * initialized by nm_device_finish_init(), and does not trigger state changes. * Should only be used when initializing a device. */ void -nm_device_set_initial_unmanaged_flag (NMDevice *self, - NMUnmanagedFlags flag, - gboolean unmanaged) +nm_device_set_unmanaged_flags_initial (NMDevice *self, + NMUnmanagedFlags flag, + gboolean unmanaged) { NMDevicePrivate *priv; @@ -7642,13 +8846,30 @@ nm_device_set_initial_unmanaged_flag (NMDevice *self, priv = NM_DEVICE_GET_PRIVATE (self); g_return_if_fail (priv->initialized == FALSE); - if (unmanaged) - priv->unmanaged_flags |= flag; - else - priv->unmanaged_flags &= ~flag; + _set_unmanaged_flags (self, flag, unmanaged); } void +nm_device_set_unmanaged_quitting (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + gboolean need_deactivate = nm_device_is_activating (self) || + priv->state == NM_DEVICE_STATE_ACTIVATED; + + /* It's OK to block here because we're quitting */ + if (need_deactivate) + _set_state_full (self, NM_DEVICE_STATE_DEACTIVATING, NM_DEVICE_STATE_REASON_NOW_UNMANAGED, TRUE); + + nm_device_set_unmanaged_flags (self, + NM_UNMANAGED_INTERNAL, + TRUE, + need_deactivate ? NM_DEVICE_STATE_REASON_REMOVED + : NM_DEVICE_STATE_REASON_NOW_UNMANAGED); +} + +/*****************************************************************************/ + +void nm_device_set_dhcp_timeout (NMDevice *self, guint32 timeout) { g_return_if_fail (NM_IS_DEVICE (self)); @@ -7670,7 +8891,84 @@ nm_device_set_dhcp_anycast_address (NMDevice *self, const char *addr) priv->dhcp_anycast_address = g_strdup (addr); } -static void +void +nm_device_reapply_settings_immediately (NMDevice *self) +{ + NMConnection *applied_connection; + NMSettingsConnection *settings_connection; + NMDeviceState state; + NMSettingConnection *s_con_settings; + NMSettingConnection *s_con_applied; + const char *zone; + NMMetered metered; + + g_return_if_fail (NM_IS_DEVICE (self)); + + state = nm_device_get_state (self); + if ( state <= NM_DEVICE_STATE_DISCONNECTED + || state > NM_DEVICE_STATE_ACTIVATED) + return; + + applied_connection = nm_device_get_applied_connection (self); + settings_connection = nm_device_get_settings_connection (self); + + if (!nm_settings_connection_has_unmodified_applied_connection (settings_connection, + applied_connection, + NM_SETTING_COMPARE_FLAG_IGNORE_REAPPLY_IMMEDIATELY)) + return; + + s_con_settings = nm_connection_get_setting_connection ((NMConnection *) settings_connection); + s_con_applied = nm_connection_get_setting_connection (applied_connection); + + if (g_strcmp0 ((zone = nm_setting_connection_get_zone (s_con_settings)), + nm_setting_connection_get_zone (s_con_applied)) != 0) { + + _LOGD (LOGD_DEVICE, "reapply setting: zone = %s%s%s", NM_PRINT_FMT_QUOTE_STRING (zone)); + + g_object_set (G_OBJECT (s_con_applied), + NM_SETTING_CONNECTION_ZONE, zone, + NULL); + + nm_device_update_firewall_zone (self); + } + + if ((metered = nm_setting_connection_get_metered (s_con_settings)) != nm_setting_connection_get_metered (s_con_applied)) { + + _LOGD (LOGD_DEVICE, "reapply setting: metered = %d", (int) metered); + + g_object_set (G_OBJECT (s_con_applied), + NM_SETTING_CONNECTION_METERED, metered, + NULL); + + nm_device_update_metered (self); + } +} + +void +nm_device_update_firewall_zone (NMDevice *self) +{ + NMConnection *applied_connection; + NMSettingConnection *s_con; + + g_return_if_fail (NM_IS_DEVICE (self)); + + applied_connection = nm_device_get_applied_connection (self); + if (!applied_connection) + return; + + s_con = nm_connection_get_setting_connection (applied_connection); + if ( nm_device_get_state (self) == NM_DEVICE_STATE_ACTIVATED + && !nm_device_uses_assumed_connection (self)) { + nm_firewall_manager_add_or_change_zone (nm_firewall_manager_get (), + nm_device_get_ip_iface (self), + nm_setting_connection_get_zone (s_con), + FALSE, /* change zone */ + NULL, + NULL); + } +} + +void nm_device_update_metered (NMDevice *self) { #define NM_METERED_INVALID ((NMMetered) -1) @@ -7688,7 +8986,7 @@ nm_device_update_metered (NMDevice *self) value = NM_METERED_UNKNOWN; if (value == NM_METERED_INVALID) { - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); if (connection) { setting = nm_connection_get_setting_connection (connection); if (setting) { @@ -7723,6 +9021,34 @@ nm_device_update_metered (NMDevice *self) } } +static gboolean +_nm_device_check_connection_available (NMDevice *self, + NMConnection *connection, + NMDeviceCheckConAvailableFlags flags, + const char *specific_object) +{ + NMDeviceState state; + + state = nm_device_get_state (self); + if (state < NM_DEVICE_STATE_UNMANAGED) + return FALSE; + if ( state < NM_DEVICE_STATE_UNAVAILABLE + && nm_device_get_unmanaged_flags (self, NM_UNMANAGED_ALL & ~NM_UNMANAGED_DEFAULT)) + return FALSE; + if ( state < NM_DEVICE_STATE_DISCONNECTED + && !nm_device_is_software (self) + && ( ( !NM_FLAGS_ANY (flags, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST) + && !nm_device_is_available (self, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE)) + || ( NM_FLAGS_ANY (flags, NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST) + && !nm_device_is_available (self, NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST)))) + return FALSE; + + if (!nm_device_check_connection_compatible (self, connection)) + return FALSE; + + return NM_DEVICE_GET_CLASS (self)->check_connection_available (self, connection, flags, specific_object); +} + /** * nm_device_check_connection_available(): * @self: the #NMDevice @@ -7744,25 +9070,33 @@ nm_device_check_connection_available (NMDevice *self, NMDeviceCheckConAvailableFlags flags, const char *specific_object) { - NMDeviceState state; + gboolean available; - state = nm_device_get_state (self); - if (state < NM_DEVICE_STATE_UNMANAGED) - return FALSE; - if ( state < NM_DEVICE_STATE_UNAVAILABLE - && nm_device_get_unmanaged_flag (self, NM_UNMANAGED_ALL & ~NM_UNMANAGED_DEFAULT)) - return FALSE; - if ( state < NM_DEVICE_STATE_DISCONNECTED - && ( ( !NM_FLAGS_HAS (flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER) - && !nm_device_is_available (self, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE)) - || ( NM_FLAGS_HAS (flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER) - && !nm_device_is_available (self, NM_DEVICE_CHECK_DEV_AVAILABLE_IGNORE_CARRIER)))) - return FALSE; + available = _nm_device_check_connection_available (self, connection, flags, specific_object); - if (!nm_device_check_connection_compatible (self, connection)) - return FALSE; +#if NM_MORE_ASSERTS >= 2 + { + /* The meaning of the flags is so that *adding* a flag relaxes a condition, thus making + * the device *more* available. Assert against that requirement by testing all the flags. */ + NMDeviceCheckConAvailableFlags i, j, k; + gboolean available_all[NM_DEVICE_CHECK_CON_AVAILABLE_ALL + 1] = { FALSE }; + + for (i = 0; i <= NM_DEVICE_CHECK_CON_AVAILABLE_ALL; i++) + available_all[i] = _nm_device_check_connection_available (self, connection, i, specific_object); + + for (i = 0; i <= NM_DEVICE_CHECK_CON_AVAILABLE_ALL; i++) { + for (j = 1; j <= NM_DEVICE_CHECK_CON_AVAILABLE_ALL; j <<= 1) { + if (NM_FLAGS_HAS (i, j)) { + k = i & ~j; + nm_assert ( available_all[i] == available_all[k] + || available_all[i]); + } + } + } + } +#endif - return NM_DEVICE_GET_CLASS (self)->check_connection_available (self, connection, flags, specific_object); + return available; } static void @@ -7842,6 +9176,8 @@ nm_device_recheck_available_connections (NMDevice *self) _signal_available_connections_changed (self); } + + available_connection_check_delete_unrealized (self); } /** @@ -7883,29 +9219,44 @@ nm_device_get_available_connections (NMDevice *self, const char *specific_object static void cp_connection_added (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) { - if (_try_add_available_connection (NM_DEVICE (user_data), connection)) - _signal_available_connections_changed (NM_DEVICE (user_data)); + NMDevice *self = user_data; + + g_return_if_fail (NM_IS_DEVICE (self)); + + if (_try_add_available_connection (self, connection)) + _signal_available_connections_changed (self); } static void cp_connection_removed (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) { - if (_del_available_connection (NM_DEVICE (user_data), connection)) - _signal_available_connections_changed (NM_DEVICE (user_data)); + NMDevice *self = user_data; + + g_return_if_fail (NM_IS_DEVICE (self)); + + if (_del_available_connection (self, connection)) { + _signal_available_connections_changed (self); + available_connection_check_delete_unrealized (self); + } } static void cp_connection_updated (NMConnectionProvider *cp, NMConnection *connection, gpointer user_data) { + NMDevice *self = user_data; gboolean added, deleted; + g_return_if_fail (NM_IS_DEVICE (self)); + /* FIXME: don't remove it from the hash if it's just going to get re-added */ - deleted = _del_available_connection (NM_DEVICE (user_data), connection); - added = _try_add_available_connection (NM_DEVICE (user_data), connection); + deleted = _del_available_connection (self, connection); + added = _try_add_available_connection (self, connection); /* Only signal if the connection was removed OR added, but not both */ - if (added != deleted) - _signal_available_connections_changed (NM_DEVICE (user_data)); + if (added != deleted) { + _signal_available_connections_changed (self); + available_connection_check_delete_unrealized (self); + } } gboolean @@ -7979,12 +9330,13 @@ gboolean nm_device_remove_pending_action (NMDevice *self, const char *action, gboolean assert_is_pending) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - GSList *iter; + GSList *iter, *next; guint count = 0; g_return_val_if_fail (action, FALSE); - for (iter = priv->pending_actions; iter; iter = iter->next) { + for (iter = priv->pending_actions; iter; iter = next) { + next = iter->next; if (!strcmp (action, iter->data)) { _LOGD (LOGD_DEVICE, "remove_pending_action (%d): '%s'", count + g_slist_length (iter->next), /* length excluding 'iter' */ @@ -8018,38 +9370,23 @@ nm_device_has_pending_action (NMDevice *self) /***********************************************************/ static void -_cleanup_ip_pre (NMDevice *self, CleanupType cleanup_type) -{ - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - - priv->ip4_state = priv->ip6_state = IP_NONE; - nm_device_queued_ip_config_change_clear (self); - - dhcp4_cleanup (self, cleanup_type, FALSE); - arp_cleanup (self); - dhcp6_cleanup (self, cleanup_type, FALSE); - linklocal6_cleanup (self); - addrconf6_cleanup (self); - dnsmasq_cleanup (self); - aipd_cleanup (self); -} - -static void _cancel_activation (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); /* Clean up when device was deactivated during call to firewall */ if (priv->fw_call) { - nm_firewall_manager_cancel_call (nm_firewall_manager_get (), priv->fw_call); + nm_firewall_manager_cancel_call (priv->fw_call); + g_warn_if_fail (!priv->fw_call); priv->fw_call = NULL; } + priv->fw_ready = FALSE; ip_check_gw_ping_cleanup (self); /* Break the activation chain */ - activation_source_clear (self, TRUE, AF_INET); - activation_source_clear (self, TRUE, AF_INET6); + activation_source_clear (self, AF_INET); + activation_source_clear (self, AF_INET6); } static void @@ -8059,19 +9396,22 @@ _cleanup_generic_pre (NMDevice *self, CleanupType cleanup_type) _cancel_activation (self); - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); if ( cleanup_type == CLEANUP_TYPE_DECONFIGURE && connection && !nm_device_uses_assumed_connection (self)) { nm_firewall_manager_remove_from_zone (nm_firewall_manager_get (), nm_device_get_ip_iface (self), + NULL, + NULL, NULL); } /* Clear any queued transitions */ nm_device_queued_state_clear (self); - _cleanup_ip_pre (self, cleanup_type); + _cleanup_ip4_pre (self, cleanup_type); + _cleanup_ip6_pre (self, cleanup_type); } static void @@ -8098,6 +9438,8 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type) priv->v4_commit_first_time = TRUE; priv->v6_commit_first_time = TRUE; + priv->linklocal6_dad_counter = 0; + /* Clean up IP configs; this does not actually deconfigure the * interface; the caller must flush routes and addresses explicitly. */ @@ -8107,15 +9449,18 @@ _cleanup_generic_post (NMDevice *self, CleanupType cleanup_type) g_clear_object (&priv->dev_ip4_config); g_clear_object (&priv->ext_ip4_config); g_clear_object (&priv->wwan_ip4_config); - g_clear_object (&priv->vpn4_config); g_clear_object (&priv->ip4_config); g_clear_object (&priv->con_ip6_config); g_clear_object (&priv->ac_ip6_config); g_clear_object (&priv->ext_ip6_config); - g_clear_object (&priv->vpn6_config); g_clear_object (&priv->wwan_ip6_config); g_clear_object (&priv->ip6_config); + g_slist_free_full (priv->vpn4_configs, g_object_unref); + priv->vpn4_configs = NULL; + g_slist_free_full (priv->vpn6_configs, g_object_unref); + priv->vpn6_configs = NULL; + clear_act_request (self); /* Clear legacy IPv4 address property */ @@ -8177,11 +9522,9 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType clean nm_device_master_release_slaves (self); /* slave: mark no longer enslaved */ - if (nm_platform_link_get_master (NM_PLATFORM_GET, priv->ifindex) <= 0) { - g_clear_object (&priv->master); - priv->enslaved = FALSE; - g_object_notify (G_OBJECT (self), NM_DEVICE_MASTER); - } + if ( priv->master + && nm_platform_link_get_master (NM_PLATFORM_GET, priv->ifindex) <= 0) + nm_device_master_release_one_slave (priv->master, self, FALSE, NM_DEVICE_STATE_REASON_CONNECTION_ASSUMED); /* Take out any entries in the routing table and any IP address the device had. */ ifindex = nm_device_get_ip_ifindex (self); @@ -8190,6 +9533,9 @@ nm_device_cleanup (NMDevice *self, NMDeviceStateReason reason, CleanupType clean nm_platform_address_flush (NM_PLATFORM_GET, ifindex); } + if (priv->lldp_listener) + nm_lldp_listener_stop (priv->lldp_listener); + nm_device_update_metered (self); _cleanup_generic_post (self, cleanup_type); } @@ -8241,13 +9587,14 @@ nm_device_spawn_iface_helper (NMDevice *self) const char *method; GPtrArray *argv; gs_free char *dhcp4_address = NULL; + char *logging_backend; if (priv->state != NM_DEVICE_STATE_ACTIVATED) return; if (!nm_device_can_assume_connections (self)) return; - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); g_assert (connection); argv = g_ptr_array_sized_new (10); @@ -8259,6 +9606,17 @@ nm_device_spawn_iface_helper (NMDevice *self) g_ptr_array_add (argv, g_strdup ("--uuid")); g_ptr_array_add (argv, g_strdup (nm_connection_get_uuid (connection))); + logging_backend = nm_config_get_is_debug (nm_config_get ()) + ? g_strdup ("debug") + : nm_config_data_get_value (NM_CONFIG_GET_DATA_ORIG, + NM_CONFIG_KEYFILE_GROUP_LOGGING, + NM_CONFIG_KEYFILE_KEY_LOGGING_BACKEND, + NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY); + if (logging_backend) { + g_ptr_array_add (argv, g_strdup ("--logging-backend")); + g_ptr_array_add (argv, logging_backend); + } + dhcp4_address = find_dhcp4_address (self); method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); @@ -8278,7 +9636,7 @@ nm_device_spawn_iface_helper (NMDevice *self) g_ptr_array_add (argv, g_strdup ("--dhcp4-required")); if (priv->dhcp4_client) { - const char *hostname; + const char *hostname, *fqdn; GBytes *client_id; client_id = nm_dhcp_client_get_client_id (priv->dhcp4_client); @@ -8294,6 +9652,12 @@ nm_device_spawn_iface_helper (NMDevice *self) g_ptr_array_add (argv, g_strdup ("--dhcp4-hostname")); g_ptr_array_add (argv, g_strdup (hostname)); } + + fqdn = nm_dhcp_client_get_fqdn (priv->dhcp4_client); + if (fqdn) { + g_ptr_array_add (argv, g_strdup ("--dhcp4-fqdn")); + g_ptr_array_add (argv, g_strdup (fqdn)); + } } configured = TRUE; @@ -8325,6 +9689,9 @@ nm_device_spawn_iface_helper (NMDevice *self) g_ptr_array_add (argv, hex_iid); } + g_ptr_array_add (argv, g_strdup ("--addr-gen-mode")); + g_ptr_array_add (argv, g_strdup_printf ("%d", nm_setting_ip6_config_get_addr_gen_mode (NM_SETTING_IP6_CONFIG (s_ip6)))); + configured = TRUE; } @@ -8398,15 +9765,14 @@ deactivate_async_ready (NMDevice *self, /* If operation cancelled, just return */ if ( g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) || (priv->deactivating_cancellable && g_cancellable_is_cancelled (priv->deactivating_cancellable))) { - nm_log_warn (LOGD_DEVICE, "Deactivation (%s) cancelled", - nm_device_get_iface (self)); + _LOGW (LOGD_DEVICE, "Deactivation cancelled"); } /* In every other case, transition to the DISCONNECTED state */ else { - if (error) - nm_log_warn (LOGD_DEVICE, "Deactivation (%s) failed: %s", - nm_device_get_iface (self), - error->message); + if (error) { + _LOGW (LOGD_DEVICE, "Deactivation failed: %s", + error->message); + } nm_device_queue_state (self, NM_DEVICE_STATE_DISCONNECTED, reason); } @@ -8453,17 +9819,21 @@ _set_state_full (NMDevice *self, NMDeviceStateReason reason, gboolean quitting) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMDevicePrivate *priv; NMDeviceState old_state; NMActRequest *req; gboolean no_firmware = FALSE; - NMConnection *connection; + NMSettingsConnection *connection; + NMConnection *applied_connection; + + g_return_if_fail (NM_IS_DEVICE (self)); + + priv = NM_DEVICE_GET_PRIVATE (self); /* Track re-entry */ g_warn_if_fail (priv->in_state_changed == FALSE); - priv->in_state_changed = TRUE; - g_return_if_fail (NM_IS_DEVICE (self)); + old_state = priv->state; /* Do nothing if state isn't changing, but as a special case allow * re-setting UNAVAILABLE if the device is missing firmware so that we @@ -8471,14 +9841,16 @@ _set_state_full (NMDevice *self, */ if ( (priv->state == state) && !(state == NM_DEVICE_STATE_UNAVAILABLE && priv->firmware_missing)) { - priv->in_state_changed = FALSE; + _LOGD (LOGD_DEVICE, "device state change: %s -> %s (reason '%s') [%d %d %d] (skip due to missing firmware)", + state_to_string (old_state), + state_to_string (state), + reason_to_string (reason), + old_state, + state, + reason); return; } - old_state = priv->state; - priv->state = state; - priv->state_reason = reason; - _LOGI (LOGD_DEVICE, "device state change: %s -> %s (reason '%s') [%d %d %d]", state_to_string (old_state), state_to_string (state), @@ -8487,6 +9859,11 @@ _set_state_full (NMDevice *self, state, reason); + priv->in_state_changed = TRUE; + + priv->state = state; + priv->state_reason = reason; + /* Clear any queued transitions */ nm_device_queued_state_clear (self); @@ -8573,7 +9950,8 @@ _set_state_full (NMDevice *self, /* Clean up any half-done IP operations if the device's layer2 * finds out it needs authentication during IP config. */ - _cleanup_ip_pre (self, CLEANUP_TYPE_DECONFIGURE); + _cleanup_ip4_pre (self, CLEANUP_TYPE_DECONFIGURE); + _cleanup_ip6_pre (self, CLEANUP_TYPE_DECONFIGURE); } break; default: @@ -8587,7 +9965,7 @@ _set_state_full (NMDevice *self, g_object_notify (G_OBJECT (self), NM_DEVICE_STATE); g_object_notify (G_OBJECT (self), NM_DEVICE_STATE_REASON); - g_signal_emit_by_name (self, "state-changed", state, old_state, reason); + g_signal_emit_by_name (self, NM_DEVICE_STATE_CHANGED, state, old_state, reason); /* Post-process the event after internal notification */ @@ -8622,13 +10000,15 @@ _set_state_full (NMDevice *self, if (quitting) { nm_dispatcher_call_sync (DISPATCHER_ACTION_PRE_DOWN, - nm_act_request_get_connection (req), + nm_act_request_get_settings_connection (req), + nm_act_request_get_applied_connection (req), self); } else { priv->dispatcher.post_state = NM_DEVICE_STATE_DISCONNECTED; priv->dispatcher.post_state_reason = reason; if (!nm_dispatcher_call (DISPATCHER_ACTION_PRE_DOWN, - nm_act_request_get_connection (req), + nm_act_request_get_settings_connection (req), + nm_act_request_get_applied_connection (req), self, deactivate_dispatcher_complete, self, @@ -8659,7 +10039,10 @@ _set_state_full (NMDevice *self, case NM_DEVICE_STATE_ACTIVATED: _LOGI (LOGD_DEVICE, "Activation: successful, device activated."); nm_device_update_metered (self); - nm_dispatcher_call (DISPATCHER_ACTION_UP, nm_act_request_get_connection (req), self, NULL, NULL, NULL); + nm_dispatcher_call (DISPATCHER_ACTION_UP, + nm_act_request_get_settings_connection (req), + nm_act_request_get_applied_connection (req), + self, NULL, NULL, NULL); break; case NM_DEVICE_STATE_FAILED: /* Usually upon failure the activation chain is interrupted in @@ -8678,10 +10061,10 @@ _set_state_full (NMDevice *self, break; } - connection = nm_device_get_connection (self); + connection = nm_device_get_settings_connection (self); _LOGW (LOGD_DEVICE | LOGD_WIFI, "Activation: failed for connection '%s'", - connection ? nm_connection_get_id (connection) : "<unknown>"); + connection ? nm_settings_connection_get_id (connection) : "<unknown>"); /* Notify any slaves of the unexpected failure */ nm_device_master_release_slaves (self); @@ -8691,11 +10074,8 @@ _set_state_full (NMDevice *self, * failed (zero timestamp), connections that succeeded (non-zero timestamp), * and those we haven't tried yet (no timestamp). */ - if (connection && !nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (connection), NULL)) { - nm_settings_connection_update_timestamp (NM_SETTINGS_CONNECTION (connection), - (guint64) 0, - TRUE); - } + if (connection && !nm_settings_connection_get_timestamp (connection, NULL)) + nm_settings_connection_update_timestamp (connection, (guint64) 0, TRUE); /* Schedule the transition to DISCONNECTED. The device can't transition * immediately because we can't change states again from the state @@ -8704,7 +10084,28 @@ _set_state_full (NMDevice *self, nm_device_queue_state (self, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_NONE); break; case NM_DEVICE_STATE_IP_CHECK: - nm_device_start_ip_check (self); + /* Now that IP config has completed, check if the firewall + * zone must be set again for the IP interface. + */ + applied_connection = nm_device_get_applied_connection (self); + + if ( applied_connection + && priv->ifindex != priv->ip_ifindex + && !nm_device_uses_assumed_connection (self)) { + NMSettingConnection *s_con; + const char *zone; + + s_con = nm_connection_get_setting_connection (applied_connection); + zone = nm_setting_connection_get_zone (s_con); + g_assert (!priv->fw_call); + priv->fw_call = nm_firewall_manager_add_or_change_zone (nm_firewall_manager_get (), + nm_device_get_ip_iface (self), + zone, + FALSE, + fw_change_zone_cb_ip_check, + self); + } else + nm_device_start_ip_check (self); /* IP-related properties are only valid when the device has IP configuration; * now that it does, ensure their change notifications are emitted. @@ -8724,10 +10125,17 @@ _set_state_full (NMDevice *self, if ( (old_state == NM_DEVICE_STATE_ACTIVATED || old_state == NM_DEVICE_STATE_DEACTIVATING) && (state != NM_DEVICE_STATE_DEACTIVATING)) { - if (quitting) - nm_dispatcher_call_sync (DISPATCHER_ACTION_DOWN, nm_act_request_get_connection (req), self); - else - nm_dispatcher_call (DISPATCHER_ACTION_DOWN, nm_act_request_get_connection (req), self, NULL, NULL, NULL); + if (quitting) { + nm_dispatcher_call_sync (DISPATCHER_ACTION_DOWN, + nm_act_request_get_settings_connection (req), + nm_act_request_get_applied_connection (req), + self); + } else { + nm_dispatcher_call (DISPATCHER_ACTION_DOWN, + nm_act_request_get_settings_connection (req), + nm_act_request_get_applied_connection (req), + self, NULL, NULL, NULL); + } } /* IP-related properties are only valid when the device has IP configuration. @@ -8836,7 +10244,7 @@ nm_device_queued_state_clear (NMDevice *self) if (priv->queued_state.id) { _LOGD (LOGD_DEVICE, "clearing queued state transition (id %d)", priv->queued_state.id); - g_source_remove (priv->queued_state.id); + nm_clear_g_source (&priv->queued_state.id); nm_device_remove_pending_action (self, queued_state_to_string (priv->queued_state.state), TRUE); } memset (&priv->queued_state, 0, sizeof (priv->queued_state)); @@ -8864,20 +10272,26 @@ nm_device_get_hw_address (NMDevice *self) return priv->hw_addr_len ? priv->hw_addr : NULL; } -static void +void nm_device_update_hw_address (NMDevice *self) { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); int ifindex = nm_device_get_ifindex (self); const guint8 *hwaddr; gsize hwaddrlen = 0; + static const guint8 zero_hwaddr[ETH_ALEN]; if (ifindex <= 0) return; hwaddr = nm_platform_link_get_address (NM_PLATFORM_GET, ifindex, &hwaddrlen); + if ( priv->type == NM_DEVICE_TYPE_ETHERNET + && nm_utils_hwaddr_matches (hwaddr, hwaddrlen, zero_hwaddr, sizeof (zero_hwaddr))) + hwaddrlen = 0; + if (hwaddrlen) { + priv->hw_addr_len = hwaddrlen; if (!priv->hw_addr || !nm_utils_hwaddr_matches (priv->hw_addr, -1, hwaddr, hwaddrlen)) { g_free (priv->hw_addr); priv->hw_addr = nm_utils_hwaddr_ntoa (hwaddr, hwaddrlen); @@ -8889,12 +10303,39 @@ nm_device_update_hw_address (NMDevice *self) /* Invalid or no hardware address */ if (priv->hw_addr_len != 0) { g_clear_pointer (&priv->hw_addr, g_free); + priv->hw_addr_len = 0; _LOGD (LOGD_HW | LOGD_DEVICE, "previous hardware address is no longer valid"); g_object_notify (G_OBJECT (self), NM_DEVICE_HW_ADDRESS); } } - priv->hw_addr_len = hwaddrlen; +} + +void +nm_device_update_initial_hw_address (NMDevice *self) +{ + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + + if (priv->hw_addr_len) { + priv->initial_hw_addr = g_strdup (priv->hw_addr); + _LOGD (LOGD_DEVICE | LOGD_HW, "read initial MAC address %s", priv->initial_hw_addr); + + if (priv->ifindex > 0) { + guint8 buf[NM_UTILS_HWADDR_LEN_MAX]; + size_t len = 0; + + if (nm_platform_link_get_permanent_address (NM_PLATFORM_GET, priv->ifindex, buf, &len)) { + g_warn_if_fail (len == priv->hw_addr_len); + priv->perm_hw_addr = nm_utils_hwaddr_ntoa (buf, priv->hw_addr_len); + _LOGD (LOGD_DEVICE | LOGD_HW, "read permanent MAC address %s", + priv->perm_hw_addr); + } else { + /* Fall back to current address */ + _LOGD (LOGD_HW | LOGD_ETHER, "unable to read permanent MAC address"); + priv->perm_hw_addr = g_strdup (priv->hw_addr); + } + } + } } gboolean @@ -9004,7 +10445,7 @@ spec_match_list (NMDevice *self, const GSList *specs) break; } } - if (priv->hw_addr_len) { + if (priv->hw_addr_len && priv->hw_addr) { m = nm_match_spec_hwaddr (specs, priv->hw_addr); matched = MAX (matched, m); } @@ -9021,12 +10462,34 @@ spec_match_list (NMDevice *self, const GSList *specs) /***********************************************************/ -#define DEFAULT_AUTOCONNECT TRUE +static const char * +_activation_func_to_string (ActivationHandleFunc func) +{ +#define FUNC_TO_STRING_CHECK_AND_RETURN(func, f) \ + G_STMT_START { \ + if ((func) == (f)) \ + return #f; \ + } G_STMT_END + FUNC_TO_STRING_CHECK_AND_RETURN (func, activate_stage1_device_prepare); + FUNC_TO_STRING_CHECK_AND_RETURN (func, activate_stage2_device_config); + FUNC_TO_STRING_CHECK_AND_RETURN (func, activate_stage3_ip_config_start); + FUNC_TO_STRING_CHECK_AND_RETURN (func, activate_stage4_ip4_config_timeout); + FUNC_TO_STRING_CHECK_AND_RETURN (func, activate_stage4_ip6_config_timeout); + FUNC_TO_STRING_CHECK_AND_RETURN (func, activate_stage5_ip4_config_commit); + FUNC_TO_STRING_CHECK_AND_RETURN (func, activate_stage5_ip6_config_commit); + g_return_val_if_reached ("unknown"); +} + +/***********************************************************/ static void nm_device_init (NMDevice *self) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMDevicePrivate *priv; + + priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_DEVICE, NMDevicePrivate); + + self->priv = priv; priv->type = NM_DEVICE_TYPE_UNKNOWN; priv->capabilities = NM_DEVICE_CAP_NM_SUPPORTED; @@ -9052,133 +10515,50 @@ constructor (GType type, GObjectConstructParam *construct_params) { GObject *object; + GObjectClass *klass; NMDevice *self; NMDevicePrivate *priv; - NMPlatform *platform; - static guint32 id = 0; + const NMPlatformLink *pllink; - object = G_OBJECT_CLASS (nm_device_parent_class)->constructor (type, - n_construct_params, - construct_params); + klass = G_OBJECT_CLASS (nm_device_parent_class); + object = klass->constructor (type, n_construct_params, construct_params); if (!object) return NULL; self = NM_DEVICE (object); priv = NM_DEVICE_GET_PRIVATE (self); - _LOGD (LOGD_DEVICE, "constructor(): %s, kernel ifindex %d", G_OBJECT_TYPE_NAME (self), priv->ifindex); + if (priv->iface) { + pllink = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, priv->iface); - if (!priv->iface) { - _LOGE (LOGD_DEVICE, "No device interface provided, ignoring"); - goto error; - } - - if (!priv->udi) { - /* Use a placeholder UDI until we get a real one */ - priv->udi = g_strdup_printf ("/virtual/device/placeholder/%d", id++); + if (pllink && link_type_compatible (self, pllink->type, NULL, NULL)) { + priv->ifindex = pllink->ifindex; + priv->up = NM_FLAGS_HAS (pllink->flags, IFF_UP); + } } - if (NM_DEVICE_GET_CLASS (self)->get_generic_capabilities) - priv->capabilities |= NM_DEVICE_GET_CLASS (self)->get_generic_capabilities (self); + return object; +} - if (priv->ifindex > 0) { - priv->physical_port_id = nm_platform_link_get_physical_port_id (NM_PLATFORM_GET, priv->ifindex); - priv->dev_id = nm_platform_link_get_dev_id (NM_PLATFORM_GET, priv->ifindex); - if (nm_platform_link_is_software (NM_PLATFORM_GET, priv->ifindex)) - priv->capabilities |= NM_DEVICE_CAP_IS_SOFTWARE; - priv->mtu = nm_platform_link_get_mtu (NM_PLATFORM_GET, priv->ifindex); +static void +constructed (GObject *object) +{ + NMDevice *self = NM_DEVICE (object); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); + NMPlatform *platform; - nm_platform_link_get_driver_info (NM_PLATFORM_GET, - priv->ifindex, - NULL, - &priv->driver_version, - &priv->firmware_version); - } + platform = nm_platform_get (); if (NM_DEVICE_GET_CLASS (self)->get_generic_capabilities) priv->capabilities |= NM_DEVICE_GET_CLASS (self)->get_generic_capabilities (self); /* Watch for external IP config changes */ - platform = nm_platform_get (); g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP4_ADDRESS_CHANGED, G_CALLBACK (device_ipx_changed), self); g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP6_ADDRESS_CHANGED, G_CALLBACK (device_ipx_changed), self); g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP4_ROUTE_CHANGED, G_CALLBACK (device_ipx_changed), self); g_signal_connect (platform, NM_PLATFORM_SIGNAL_IP6_ROUTE_CHANGED, G_CALLBACK (device_ipx_changed), self); g_signal_connect (platform, NM_PLATFORM_SIGNAL_LINK_CHANGED, G_CALLBACK (link_changed_cb), self); - /* trigger initial ip config change to initialize ip-config */ - priv->queued_ip4_config_id = g_idle_add (queued_ip4_config_change, self); - priv->queued_ip6_config_id = g_idle_add (queued_ip6_config_change, self); - - if (nm_platform_check_support_user_ipv6ll (NM_PLATFORM_GET)) { - int ip_ifindex = nm_device_get_ip_ifindex (self); - - if (ip_ifindex > 0) - priv->nm_ipv6ll = nm_platform_link_get_user_ipv6ll_enabled (NM_PLATFORM_GET, ip_ifindex); - } - - return object; - -error: - g_object_unref (self); - return NULL; -} - -static void -constructed (GObject *object) -{ - NMDevice *self = NM_DEVICE (object); - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - int master; - - nm_device_update_hw_address (self); - - if (priv->hw_addr_len) { - priv->initial_hw_addr = g_strdup (priv->hw_addr); - _LOGD (LOGD_DEVICE | LOGD_HW, "read initial MAC address %s", priv->initial_hw_addr); - - if (priv->ifindex > 0) { - guint8 buf[NM_UTILS_HWADDR_LEN_MAX]; - size_t len = 0; - - if (nm_platform_link_get_permanent_address (NM_PLATFORM_GET, priv->ifindex, buf, &len)) { - g_warn_if_fail (len == priv->hw_addr_len); - priv->perm_hw_addr = nm_utils_hwaddr_ntoa (buf, priv->hw_addr_len); - _LOGD (LOGD_DEVICE | LOGD_HW, "read permanent MAC address %s", - priv->perm_hw_addr); - } else { - /* Fall back to current address */ - _LOGD (LOGD_HW | LOGD_ETHER, "unable to read permanent MAC address"); - priv->perm_hw_addr = g_strdup (priv->hw_addr); - } - } - } - - /* Note: initial hardware address must be read before calling get_ignore_carrier() */ - if (nm_device_has_capability (self, NM_DEVICE_CAP_CARRIER_DETECT)) { - NMConfig *config = nm_config_get (); - - priv->ignore_carrier = nm_config_data_get_ignore_carrier (nm_config_get_data (config), self); - g_signal_connect (G_OBJECT (config), - NM_CONFIG_SIGNAL_CONFIG_CHANGED, - G_CALLBACK (config_changed_update_ignore_carrier), - self); - - check_carrier (self); - _LOGD (LOGD_HW, - "carrier is %s%s", - priv->carrier ? "ON" : "OFF", - priv->ignore_carrier ? " (but ignored)" : ""); - } else { - /* Fake online link when carrier detection is not available. */ - priv->carrier = TRUE; - } - - /* Enslave ourselves */ - master = nm_platform_link_get_master (NM_PLATFORM_GET, priv->ifindex); - if (master) - device_set_master (self, master); - priv->con_provider = nm_connection_provider_get (); g_assert (priv->con_provider); g_signal_connect (priv->con_provider, @@ -9206,6 +10586,8 @@ constructed (GObject *object) } G_OBJECT_CLASS (nm_device_parent_class)->constructed (object); + + _LOGD (LOGD_DEVICE, "constructed (%s)", G_OBJECT_TYPE_NAME (self)); } static void @@ -9215,7 +10597,7 @@ dispose (GObject *object) NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMPlatform *platform; - _LOGD (LOGD_DEVICE, "dispose(): %s", G_OBJECT_TYPE_NAME (self)); + _LOGD (LOGD_DEVICE, "disposing"); g_signal_handlers_disconnect_by_func (nm_config_get (), config_changed_update_ignore_carrier, self); @@ -9233,15 +10615,10 @@ dispose (GObject *object) g_hash_table_remove_all (priv->ip6_saved_properties); - if (priv->recheck_assume_id) { - g_source_remove (priv->recheck_assume_id); - priv->recheck_assume_id = 0; - } + nm_clear_g_source (&priv->recheck_assume_id); + nm_clear_g_source (&priv->recheck_available.call_id); - if (priv->recheck_available.call_id) { - g_source_remove (priv->recheck_available.call_id); - priv->recheck_available.call_id = 0; - } + nm_clear_g_source (&priv->check_delete_unrealized_id); link_disconnect_action_cancel (self); @@ -9265,7 +10642,22 @@ dispose (GObject *object) nm_clear_g_source (&priv->device_link_changed_id); nm_clear_g_source (&priv->device_ip_link_changed_id); + if (priv->lldp_listener) { + g_signal_handlers_disconnect_by_func (priv->lldp_listener, + G_CALLBACK (lldp_neighbors_changed), + self); + nm_lldp_listener_stop (priv->lldp_listener); + g_clear_object (&priv->lldp_listener); + } + G_OBJECT_CLASS (nm_device_parent_class)->dispose (object); + + if (nm_clear_g_source (&priv->queued_state.id)) { + /* FIXME: we'd expect the queud_state to be alredy cleared and this statement + * not being necessary. Add this check here to hopefully investigate crash + * rh#1270247. */ + g_return_if_reached (); + } } static void @@ -9280,9 +10672,9 @@ finalize (GObject *object) g_free (priv->perm_hw_addr); g_free (priv->initial_hw_addr); g_slist_free_full (priv->pending_actions, g_free); + g_slist_free_full (priv->dad6_failed_addrs, g_free); g_clear_pointer (&priv->physical_port_id, g_free); g_free (priv->udi); - g_free (priv->path); g_free (priv->iface); g_free (priv->ip_iface); g_free (priv->driver); @@ -9304,25 +10696,11 @@ set_property (GObject *object, guint prop_id, { NMDevice *self = NM_DEVICE (object); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - NMPlatformLink *platform_device; const char *hw_addr, *p; guint count; + gboolean val_bool; switch (prop_id) { - case PROP_PLATFORM_DEVICE: - platform_device = g_value_get_pointer (value); - if (platform_device) { - g_free (priv->udi); - priv->udi = g_strdup (nm_platform_link_get_udi (NM_PLATFORM_GET, platform_device->ifindex)); - g_free (priv->iface); - priv->iface = g_strdup (platform_device->name); - priv->ifindex = platform_device->ifindex; - priv->up = NM_FLAGS_HAS (platform_device->flags, IFF_UP); - g_free (priv->driver); - priv->driver = g_strdup (platform_device->driver); - priv->platform_link_initialized = platform_device->initialized; - } - break; case PROP_UDI: if (g_value_get_string (value)) { g_free (priv->udi); @@ -9330,13 +10708,9 @@ set_property (GObject *object, guint prop_id, } break; case PROP_IFACE: - if (g_value_get_string (value)) { - g_free (priv->iface); - priv->iface = g_value_dup_string (value); - priv->ifindex = nm_platform_link_get_ifindex (NM_PLATFORM_GET, priv->iface); - if (priv->ifindex > 0) - priv->up = nm_platform_link_is_up (NM_PLATFORM_GET, priv->ifindex); - } + /* construct only */ + g_return_if_fail (!priv->iface); + priv->iface = g_value_dup_string (value); break; case PROP_DRIVER: if (g_value_get_string (value)) { @@ -9358,16 +10732,32 @@ set_property (GObject *object, guint prop_id, case PROP_IP4_ADDRESS: priv->ip4_address = g_value_get_uint (value); break; + case PROP_MANAGED: + val_bool = g_value_get_boolean (value); + priv->managed_touched_by_user = TRUE; + nm_device_set_unmanaged_flags (self, + NM_UNMANAGED_USER | (val_bool ? NM_UNMANAGED_DEFAULT : NM_UNMANAGED_NONE), + !val_bool, + NM_DEVICE_STATE_REASON_USER_REQUESTED); + break; case PROP_AUTOCONNECT: nm_device_set_autoconnect (self, g_value_get_boolean (value)); break; case PROP_FIRMWARE_MISSING: priv->firmware_missing = g_value_get_boolean (value); break; + case PROP_NM_PLUGIN_MISSING: + priv->nm_plugin_missing = g_value_get_boolean (value); + break; case PROP_DEVICE_TYPE: g_return_if_fail (priv->type == NM_DEVICE_TYPE_UNKNOWN); priv->type = g_value_get_uint (value); break; + case PROP_LINK_TYPE: + /* construct only */ + g_return_if_fail (priv->link_type == NM_LINK_TYPE_NONE); + priv->link_type = g_value_get_uint (value); + break; case PROP_TYPE_DESC: g_free (priv->type_desc); priv->type_desc = g_value_dup_string (value); @@ -9411,18 +10801,16 @@ set_property (GObject *object, guint prop_id, } } -#define DBUS_TYPE_STATE_REASON_STRUCT (dbus_g_type_get_struct ("GValueArray", G_TYPE_UINT, G_TYPE_UINT, G_TYPE_INVALID)) - static void get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) + GValue *value, GParamSpec *pspec) { NMDevice *self = NM_DEVICE (object); NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); - const char *ac_path = NULL; GPtrArray *array; GHashTableIter iter; NMConnection *connection; + GVariantBuilder array_builder; switch (prop_id) { case PROP_UDI: @@ -9462,44 +10850,33 @@ get_property (GObject *object, guint prop_id, g_value_set_uint (value, priv->mtu); break; case PROP_IP4_CONFIG: - if (ip_config_valid (priv->state) && priv->ip4_config) - g_value_set_boxed (value, nm_ip4_config_get_dbus_path (priv->ip4_config)); - else - g_value_set_boxed (value, "/"); + nm_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->ip4_config : NULL); break; case PROP_DHCP4_CONFIG: - if (ip_config_valid (priv->state) && priv->dhcp4_config) - g_value_set_boxed (value, nm_dhcp4_config_get_dbus_path (priv->dhcp4_config)); - else - g_value_set_boxed (value, "/"); + nm_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->dhcp4_config : NULL); break; case PROP_IP6_CONFIG: - if (ip_config_valid (priv->state) && priv->ip6_config) - g_value_set_boxed (value, nm_ip6_config_get_dbus_path (priv->ip6_config)); - else - g_value_set_boxed (value, "/"); + nm_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->ip6_config : NULL); break; case PROP_DHCP6_CONFIG: - if (ip_config_valid (priv->state) && priv->dhcp6_config) - g_value_set_boxed (value, nm_dhcp6_config_get_dbus_path (priv->dhcp6_config)); - else - g_value_set_boxed (value, "/"); + nm_utils_g_value_set_object_path (value, ip_config_valid (priv->state) ? priv->dhcp6_config : NULL); break; case PROP_STATE: g_value_set_uint (value, priv->state); break; case PROP_STATE_REASON: - g_value_take_boxed (value, dbus_g_type_specialized_construct (DBUS_TYPE_STATE_REASON_STRUCT)); - dbus_g_type_struct_set (value, 0, priv->state, 1, priv->state_reason, G_MAXUINT); + g_value_take_variant (value, + g_variant_new ("(uu)", priv->state, priv->state_reason)); break; case PROP_ACTIVE_CONNECTION: - if (priv->act_request) - ac_path = nm_active_connection_get_path (NM_ACTIVE_CONNECTION (priv->act_request)); - g_value_set_boxed (value, ac_path ? ac_path : "/"); + nm_utils_g_value_set_object_path (value, priv->act_request); break; case PROP_DEVICE_TYPE: g_value_set_uint (value, priv->type); break; + case PROP_LINK_TYPE: + g_value_set_uint (value, priv->link_type); + break; case PROP_MANAGED: g_value_set_boolean (value, nm_device_get_managed (self)); break; @@ -9509,6 +10886,9 @@ get_property (GObject *object, guint prop_id, case PROP_FIRMWARE_MISSING: g_value_set_boolean (value, priv->firmware_missing); break; + case PROP_NM_PLUGIN_MISSING: + g_value_set_boolean (value, priv->nm_plugin_missing); + break; case PROP_TYPE_DESC: g_value_set_string (value, priv->type_desc); break; @@ -9520,7 +10900,8 @@ get_property (GObject *object, guint prop_id, g_hash_table_iter_init (&iter, priv->available_connections); while (g_hash_table_iter_next (&iter, (gpointer) &connection, NULL)) g_ptr_array_add (array, g_strdup (nm_connection_get_path (connection))); - g_value_take_boxed (value, array); + g_ptr_array_add (array, NULL); + g_value_take_boxed (value, (char **) g_ptr_array_free (array, FALSE)); break; case PROP_PHYSICAL_PORT_ID: g_value_set_string (value, priv->physical_port_id); @@ -9529,7 +10910,7 @@ get_property (GObject *object, guint prop_id, g_value_set_boolean (value, priv->is_master); break; case PROP_MASTER: - g_value_set_object (value, priv->master); + g_value_set_object (value, nm_device_get_master (self)); break; case PROP_HW_ADDRESS: g_value_set_string (value, priv->hw_addr); @@ -9540,6 +10921,37 @@ get_property (GObject *object, guint prop_id, case PROP_METERED: g_value_set_uint (value, priv->metered); break; + case PROP_LLDP_NEIGHBORS: + if (priv->lldp_listener) + g_value_set_variant (value, nm_lldp_listener_get_neighbors (priv->lldp_listener)); + else { + g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}")); + g_value_take_variant (value, g_variant_builder_end (&array_builder)); + } + break; + case PROP_REAL: + g_value_set_boolean (value, nm_device_is_real (self)); + break; + case PROP_SLAVES: { + GSList *slave_iter; + char **slave_list; + guint i; + + slave_list = g_new (char *, g_slist_length (priv->slaves) + 1); + for (slave_iter = priv->slaves, i = 0; slave_iter; slave_iter = slave_iter->next) { + SlaveInfo *info = slave_iter->data; + const char *path; + + if (!NM_DEVICE_GET_PRIVATE (info->slave)->is_enslaved) + continue; + path = nm_exported_object_get_path ((NMExportedObject *) info->slave); + if (path) + slave_list[i++] = g_strdup (path); + } + slave_list[i] = NULL; + g_value_take_boxed (value, slave_list); + break; + } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -9550,9 +10962,12 @@ static void nm_device_class_init (NMDeviceClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMExportedObjectClass *exported_object_class = NM_EXPORTED_OBJECT_CLASS (klass); g_type_class_add_private (object_class, sizeof (NMDevicePrivate)); + exported_object_class->export_path = NM_DBUS_PATH "/Devices/%u"; + /* Virtual methods */ object_class->dispose = dispose; object_class->finalize = finalize; @@ -9578,6 +10993,8 @@ nm_device_class_init (NMDeviceClass *klass) klass->check_connection_compatible = check_connection_compatible; klass->check_connection_available = check_connection_available; klass->can_unmanaged_external_down = can_unmanaged_external_down; + klass->realize_start_notify = realize_start_notify; + klass->unrealize_notify = unrealize_notify; klass->is_up = is_up; klass->bring_up = bring_up; klass->take_down = take_down; @@ -9586,12 +11003,6 @@ nm_device_class_init (NMDeviceClass *klass) /* Properties */ g_object_class_install_property - (object_class, PROP_PLATFORM_DEVICE, - g_param_spec_pointer (NM_DEVICE_PLATFORM_DEVICE, "", "", - G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (object_class, PROP_UDI, g_param_spec_string (NM_DEVICE_UDI, "", "", NULL, @@ -9663,31 +11074,31 @@ nm_device_class_init (NMDeviceClass *klass) g_object_class_install_property (object_class, PROP_IP4_CONFIG, - g_param_spec_boxed (NM_DEVICE_IP4_CONFIG, "", "", - DBUS_TYPE_G_OBJECT_PATH, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + g_param_spec_string (NM_DEVICE_IP4_CONFIG, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_DHCP4_CONFIG, - g_param_spec_boxed (NM_DEVICE_DHCP4_CONFIG, "", "", - DBUS_TYPE_G_OBJECT_PATH, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + g_param_spec_string (NM_DEVICE_DHCP4_CONFIG, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_IP6_CONFIG, - g_param_spec_boxed (NM_DEVICE_IP6_CONFIG, "", "", - DBUS_TYPE_G_OBJECT_PATH, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + g_param_spec_string (NM_DEVICE_IP6_CONFIG, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_DHCP6_CONFIG, - g_param_spec_boxed (NM_DEVICE_DHCP6_CONFIG, "", "", - DBUS_TYPE_G_OBJECT_PATH, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); + g_param_spec_string (NM_DEVICE_DHCP6_CONFIG, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_STATE, @@ -9698,17 +11109,18 @@ nm_device_class_init (NMDeviceClass *klass) g_object_class_install_property (object_class, PROP_STATE_REASON, - g_param_spec_boxed (NM_DEVICE_STATE_REASON, "", "", - DBUS_TYPE_STATE_REASON_STRUCT, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + g_param_spec_variant (NM_DEVICE_STATE_REASON, "", "", + G_VARIANT_TYPE ("(uu)"), + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_ACTIVE_CONNECTION, - g_param_spec_boxed (NM_DEVICE_ACTIVE_CONNECTION, "", "", - DBUS_TYPE_G_OBJECT_PATH, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + g_param_spec_string (NM_DEVICE_ACTIVE_CONNECTION, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_DEVICE_TYPE, @@ -9718,10 +11130,17 @@ nm_device_class_init (NMDeviceClass *klass) G_PARAM_STATIC_STRINGS)); g_object_class_install_property + (object_class, PROP_LINK_TYPE, + g_param_spec_uint (NM_DEVICE_LINK_TYPE, "", "", + 0, G_MAXUINT32, NM_LINK_TYPE_NONE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_MANAGED, g_param_spec_boolean (NM_DEVICE_MANAGED, "", "", FALSE, - G_PARAM_READABLE | + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property @@ -9739,6 +11158,13 @@ nm_device_class_init (NMDeviceClass *klass) G_PARAM_STATIC_STRINGS)); g_object_class_install_property + (object_class, PROP_NM_PLUGIN_MISSING, + g_param_spec_boolean (NM_DEVICE_NM_PLUGIN_MISSING, "", "", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_TYPE_DESC, g_param_spec_string (NM_DEVICE_TYPE_DESC, "", "", NULL, @@ -9764,7 +11190,7 @@ nm_device_class_init (NMDeviceClass *klass) g_object_class_install_property (object_class, PROP_AVAILABLE_CONNECTIONS, g_param_spec_boxed (NM_DEVICE_AVAILABLE_CONNECTIONS, "", "", - DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, + G_TYPE_STRV, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); @@ -9808,7 +11234,7 @@ nm_device_class_init (NMDeviceClass *klass) * * Whether the connection is metered. * - * Since: 1.0.6 + * Since: 1.2 **/ g_object_class_install_property (object_class, PROP_METERED, @@ -9817,9 +11243,31 @@ nm_device_class_init (NMDeviceClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property + (object_class, PROP_LLDP_NEIGHBORS, + g_param_spec_variant (NM_DEVICE_LLDP_NEIGHBORS, "", "", + G_VARIANT_TYPE ("aa{sv}"), + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_REAL, + g_param_spec_boolean (NM_DEVICE_REAL, "", "", + FALSE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_SLAVES, + g_param_spec_boxed (NM_DEVICE_SLAVES, "", "", + G_TYPE_STRV, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); + /* Signals */ signals[STATE_CHANGED] = - g_signal_new ("state-changed", + g_signal_new (NM_DEVICE_STATE_CHANGED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (NMDeviceClass, state_changed), @@ -9840,8 +11288,8 @@ nm_device_class_init (NMDeviceClass *klass) G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, 0, NULL, NULL, NULL, - /* dbus-glib context, connection, permission, allow_interaction, callback, user_data */ - G_TYPE_NONE, 6, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_POINTER, G_TYPE_POINTER); + /* context, connection, permission, allow_interaction, callback, user_data */ + G_TYPE_NONE, 6, G_TYPE_DBUS_METHOD_INVOCATION, NM_TYPE_CONNECTION, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_POINTER, G_TYPE_POINTER); signals[IP4_CONFIG_CHANGED] = g_signal_new (NM_DEVICE_IP4_CONFIG_CHANGED, @@ -9878,17 +11326,10 @@ nm_device_class_init (NMDeviceClass *klass) 0, NULL, NULL, NULL, G_TYPE_NONE, 0); - signals[LINK_INITIALIZED] = - g_signal_new (NM_DEVICE_LINK_INITIALIZED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, NULL, - G_TYPE_NONE, 0); - - nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), - G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_object_info); - - dbus_g_error_domain_register (NM_DEVICE_ERROR, NULL, NM_TYPE_DEVICE_ERROR); + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_SKELETON, + "Reapply", impl_device_reapply, + "Disconnect", impl_device_disconnect, + "Delete", impl_device_delete, + NULL); } - diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h index 49cef8e1..e173b2db 100644 --- a/src/devices/nm-device.h +++ b/src/devices/nm-device.h @@ -22,13 +22,11 @@ #ifndef __NETWORKMANAGER_DEVICE_H__ #define __NETWORKMANAGER_DEVICE_H__ -#include <glib-object.h> -#include <gio/gio.h> -#include <dbus/dbus-glib.h> #include <netinet/in.h> +#include "nm-exported-object.h" #include "nm-dbus-interface.h" -#include "nm-types.h" +#include "nm-default.h" #include "nm-connection.h" #include "nm-rfkill-manager.h" #include "NetworkManagerUtils.h" @@ -51,14 +49,23 @@ #define NM_DEVICE_STATE_REASON "state-reason" #define NM_DEVICE_ACTIVE_CONNECTION "active-connection" #define NM_DEVICE_DEVICE_TYPE "device-type" /* ugh */ +#define NM_DEVICE_LINK_TYPE "link-type" #define NM_DEVICE_MANAGED "managed" #define NM_DEVICE_AUTOCONNECT "autoconnect" #define NM_DEVICE_FIRMWARE_MISSING "firmware-missing" +#define NM_DEVICE_NM_PLUGIN_MISSING "nm-plugin-missing" #define NM_DEVICE_AVAILABLE_CONNECTIONS "available-connections" #define NM_DEVICE_PHYSICAL_PORT_ID "physical-port-id" #define NM_DEVICE_MTU "mtu" #define NM_DEVICE_HW_ADDRESS "hw-address" #define NM_DEVICE_METERED "metered" +#define NM_DEVICE_LLDP_NEIGHBORS "lldp-neighbors" +#define NM_DEVICE_REAL "real" + +/* the "slaves" property is internal in the parent class, but exposed + * by the derived classes NMDeviceBond, NMDeviceBridge and NMDeviceTeam. + * It is thus important that the property name matches. */ +#define NM_DEVICE_SLAVES "slaves" /* partially internal */ #define NM_DEVICE_TYPE_DESC "type-desc" /* Internal only */ #define NM_DEVICE_RFKILL_TYPE "rfkill-type" /* Internal only */ @@ -74,6 +81,7 @@ #define NM_DEVICE_REMOVED "removed" #define NM_DEVICE_RECHECK_AUTO_ACTIVATE "recheck-auto-activate" #define NM_DEVICE_RECHECK_ASSUME "recheck-assume" +#define NM_DEVICE_STATE_CHANGED "state-changed" #define NM_DEVICE_LINK_INITIALIZED "link-initialized" G_BEGIN_DECLS @@ -100,28 +108,34 @@ typedef enum { /*< skip >*/ NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST = _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_WAITING_CARRIER | _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP, - __NM_DEVICE_CHECK_CON_AVAILABLE_ALL, - NM_DEVICE_CHECK_CON_AVAILABLE_ALL = (((__NM_DEVICE_CHECK_CON_AVAILABLE_ALL - 1) << 1) - 1), + NM_DEVICE_CHECK_CON_AVAILABLE_ALL = (1L << 2) - 1, } NMDeviceCheckConAvailableFlags; +struct _NMDevicePrivate; + struct _NMDevice { - GObject parent; + NMExportedObject parent; + + /* private */ + struct _NMDevicePrivate *priv; }; /* The flags have an relaxing meaning, that means, specifying more flags, can make * a device appear more available. It can never make a device less available. */ typedef enum { /*< skip >*/ NM_DEVICE_CHECK_DEV_AVAILABLE_NONE = 0, - NM_DEVICE_CHECK_DEV_AVAILABLE_IGNORE_CARRIER = (1L << 0), - __NM_DEVICE_CHECK_DEV_AVAILABLE_ALL, - NM_DEVICE_CHECK_DEV_AVAILABLE_ALL = (((__NM_DEVICE_CHECK_DEV_AVAILABLE_ALL - 1) << 1) - 1), + _NM_DEVICE_CHECK_DEV_AVAILABLE_IGNORE_CARRIER = (1L << 0), + NM_DEVICE_CHECK_DEV_AVAILABLE_FOR_USER_REQUEST = _NM_DEVICE_CHECK_DEV_AVAILABLE_IGNORE_CARRIER, + + NM_DEVICE_CHECK_DEV_AVAILABLE_ALL = (1L << 1) - 1, } NMDeviceCheckDevAvailableFlags; typedef struct { - GObjectClass parent; + NMExportedObjectClass parent; const char *connection_type; + const NMLinkType *link_types; void (*state_changed) (NMDevice *device, NMDeviceState new_state, @@ -130,6 +144,48 @@ typedef struct { void (* link_changed) (NMDevice *self, NMPlatformLink *info); + /** + * create_and_realize(): + * @self: the #NMDevice + * @connection: the #NMConnection being activated + * @parent: the parent #NMDevice, if any + * @out_plink: on success, a backing kernel network device if one exists. + * The returned pointer is owned by platform and only valid until the + * next platform operation. + * @error: location to store error, or %NULL + * + * Create any backing resources (kernel devices, etc) required for this + * device to activate @connection. If the device is backed by a kernel + * network device, that device should be returned in @out_plink after + * being created. + * + * Returns: %TRUE on success, %FALSE on error + */ + gboolean (*create_and_realize) (NMDevice *self, + NMConnection *connection, + NMDevice *parent, + const NMPlatformLink **out_plink, + GError **error); + + /** + * realize_start_notify(): + * @self: the #NMDevice + * @plink: the #NMPlatformLink if backed by a kernel netdevice + * + * Hook for derived classes to be notfied during realize_start_setup() + * and perform additional setup. + */ + void (*realize_start_notify) (NMDevice *self, const NMPlatformLink *plink); + + /** + * unrealize_notify(): + * @self: the #NMDevice + * + * Hook for derived classes to clear any properties that depend on backing resources + * (kernel devices, etc). This is called by nm_device_unrealize() during unrealization. + */ + void (*unrealize_notify) (NMDevice *self); + /* Hardware state (IFF_UP) */ gboolean (*can_unmanaged_external_down) (NMDevice *self); gboolean (*is_up) (NMDevice *self); @@ -155,7 +211,7 @@ typedef struct { /* Checks whether the connection is compatible with the device using * only the devices type and characteristics. Does not use any live - * network information like WiFi/WiMAX scan lists etc. + * network information like WiFi scan lists etc. */ gboolean (* check_connection_compatible) (NMDevice *self, NMConnection *connection); @@ -186,11 +242,11 @@ typedef struct { NMActStageReturn (* act_stage2_config) (NMDevice *self, NMDeviceStateReason *reason); NMActStageReturn (* act_stage3_ip4_config_start) (NMDevice *self, - NMIP4Config **out_config, - NMDeviceStateReason *reason); + NMIP4Config **out_config, + NMDeviceStateReason *reason); NMActStageReturn (* act_stage3_ip6_config_start) (NMDevice *self, - NMIP6Config **out_config, - NMDeviceStateReason *reason); + NMIP6Config **out_config, + NMDeviceStateReason *reason); NMActStageReturn (* act_stage4_ip4_config_timeout) (NMDevice *self, NMDeviceStateReason *reason); NMActStageReturn (* act_stage4_ip6_config_timeout) (NMDevice *self, @@ -229,13 +285,15 @@ typedef struct { NMConnection *connection, gboolean configure); - gboolean (* release_slave) (NMDevice *self, + void (* release_slave) (NMDevice *self, NMDevice *slave, gboolean configure); gboolean (* have_any_ready_slaves) (NMDevice *self, const GSList *slaves); + void (* notify_new_device_added) (NMDevice *self, NMDevice *new_device); + /** * component_added: * @self: the #NMDevice @@ -258,23 +316,21 @@ typedef struct { NMConnection * (* new_default_connection) (NMDevice *self); } NMDeviceClass; - typedef void (*NMDeviceAuthRequestFunc) (NMDevice *device, - DBusGMethodInvocation *context, + GDBusMethodInvocation *context, + NMAuthSubject *subject, GError *error, gpointer user_data); GType nm_device_get_type (void); -const char * nm_device_get_path (NMDevice *dev); -void nm_device_dbus_export (NMDevice *device); - void nm_device_finish_init (NMDevice *device); const char * nm_device_get_udi (NMDevice *dev); const char * nm_device_get_iface (NMDevice *dev); int nm_device_get_ifindex (NMDevice *dev); gboolean nm_device_is_software (NMDevice *dev); +gboolean nm_device_is_real (NMDevice *dev); const char * nm_device_get_ip_iface (NMDevice *dev); int nm_device_get_ip_ifindex(NMDevice *dev); const char * nm_device_get_driver (NMDevice *dev); @@ -282,6 +338,7 @@ const char * nm_device_get_driver_version (NMDevice *dev); const char * nm_device_get_type_desc (NMDevice *dev); const char * nm_device_get_type_description (NMDevice *dev); NMDeviceType nm_device_get_device_type (NMDevice *dev); +NMLinkType nm_device_get_link_type (NMDevice *dev); NMMetered nm_device_get_metered (NMDevice *dev); int nm_device_get_priority (NMDevice *dev); @@ -296,21 +353,28 @@ NMDhcp4Config * nm_device_get_dhcp4_config (NMDevice *dev); NMDhcp6Config * nm_device_get_dhcp6_config (NMDevice *dev); NMIP4Config * nm_device_get_ip4_config (NMDevice *dev); -void nm_device_set_vpn4_config (NMDevice *dev, NMIP4Config *config); +void nm_device_replace_vpn4_config (NMDevice *dev, + NMIP4Config *old, + NMIP4Config *config); NMIP6Config * nm_device_get_ip6_config (NMDevice *dev); -void nm_device_set_vpn6_config (NMDevice *dev, NMIP6Config *config); +void nm_device_replace_vpn6_config (NMDevice *dev, + NMIP6Config *old, + NMIP6Config *config); void nm_device_capture_initial_config (NMDevice *dev); /* Master */ -GSList * nm_device_master_get_slaves (NMDevice *dev); +gboolean nm_device_is_master (NMDevice *dev); /* Slave */ NMDevice * nm_device_get_master (NMDevice *dev); -NMActRequest * nm_device_get_act_request (NMDevice *dev); -NMConnection * nm_device_get_connection (NMDevice *dev); +NMActRequest * nm_device_get_act_request (NMDevice *dev); +NMSettingsConnection * nm_device_get_settings_connection (NMDevice *dev); +NMConnection * nm_device_get_applied_connection (NMDevice *dev); +gboolean nm_device_has_unmodified_applied_connection (NMDevice *self, + NMSettingCompareFlags compare_flags); void nm_device_removed (NMDevice *dev); @@ -335,6 +399,7 @@ gboolean nm_device_complete_connection (NMDevice *device, GError **error); gboolean nm_device_check_connection_compatible (NMDevice *device, NMConnection *connection); +gboolean nm_device_check_slave_connection_compatible (NMDevice *device, NMConnection *connection); gboolean nm_device_uses_assumed_connection (NMDevice *device); @@ -356,23 +421,27 @@ RfKillType nm_device_get_rfkill_type (NMDevice *device); /** * NMUnmanagedFlags: * @NM_UNMANAGED_NONE: placeholder value - * @NM_UNMANAGED_DEFAULT: %TRUE when unmanaged by default (ie, Generic devices) * @NM_UNMANAGED_INTERNAL: %TRUE when unmanaged by internal decision (ie, * because NM is sleeping or not managed for some other reason) - * @NM_UNMANAGED_USER: %TRUE when unmanaged by user decision (via unmanaged-specs) * @NM_UNMANAGED_PARENT: %TRUE when unmanaged due to parent device being unmanaged - * @NM_UNMANAGED_EXTERNAL_DOWN: %TRUE when unmanaged because !IFF_UP and not created by NM + * @NM_UNMANAGED_LOOPBACK: %TRUE for unmanaging loopback device * @NM_UNMANAGED_PLATFORM_INIT: %TRUE when unmanaged because platform link not * yet initialized + * @NM_UNMANAGED_USER: %TRUE when unmanaged by user decision (via unmanaged-specs) + * @NM_UNMANAGED_DEFAULT: %TRUE when unmanaged by default (ie, Generic devices) + * @NM_UNMANAGED_EXTERNAL_DOWN: %TRUE when unmanaged because !IFF_UP and not created by NM */ -typedef enum { - NM_UNMANAGED_NONE = 0x00, - NM_UNMANAGED_DEFAULT = 0x01, - NM_UNMANAGED_INTERNAL = 0x02, - NM_UNMANAGED_USER = 0x04, - NM_UNMANAGED_PARENT = 0x08, - NM_UNMANAGED_EXTERNAL_DOWN = 0x10, - NM_UNMANAGED_PLATFORM_INIT = 0x20, +typedef enum { /*< skip >*/ + NM_UNMANAGED_NONE = 0, + + NM_UNMANAGED_INTERNAL = (1LL << 0), + NM_UNMANAGED_PARENT = (1LL << 1), + NM_UNMANAGED_LOOPBACK = (1LL << 2), + NM_UNMANAGED_PLATFORM_INIT = (1LL << 3), + NM_UNMANAGED_USER = (1LL << 4), + + NM_UNMANAGED_DEFAULT = (1LL << 8), + NM_UNMANAGED_EXTERNAL_DOWN = (1LL << 11), /* Boundary value */ __NM_UNMANAGED_LAST, @@ -381,26 +450,37 @@ typedef enum { } NMUnmanagedFlags; gboolean nm_device_get_managed (NMDevice *device); -gboolean nm_device_get_unmanaged_flag (NMDevice *device, NMUnmanagedFlags flag); -void nm_device_set_unmanaged (NMDevice *device, - NMUnmanagedFlags flag, - gboolean unmanaged, - NMDeviceStateReason reason); +NMUnmanagedFlags nm_device_get_unmanaged_flags (NMDevice *device, NMUnmanagedFlags flag); +void nm_device_set_unmanaged_flags (NMDevice *device, + NMUnmanagedFlags flag, + gboolean unmanaged, + NMDeviceStateReason reason); +void nm_device_set_unmanaged_flags_by_device_spec (NMDevice *self, const GSList *unmanaged_specs); +void nm_device_set_unmanaged_flags_initial (NMDevice *device, + NMUnmanagedFlags flag, + gboolean unmanaged); void nm_device_set_unmanaged_quitting (NMDevice *device); -void nm_device_set_initial_unmanaged_flag (NMDevice *device, - NMUnmanagedFlags flag, - gboolean unmanaged); gboolean nm_device_get_is_nm_owned (NMDevice *device); -void nm_device_set_nm_owned (NMDevice *device); gboolean nm_device_has_capability (NMDevice *self, NMDeviceCapabilities caps); -gboolean nm_device_get_autoconnect (NMDevice *device); +gboolean nm_device_realize_start (NMDevice *device, + const NMPlatformLink *plink, + gboolean *out_compatible, + GError **error); +void nm_device_realize_finish (NMDevice *self, + const NMPlatformLink *plink); +gboolean nm_device_create_and_realize (NMDevice *self, + NMConnection *connection, + NMDevice *parent, + GError **error); +gboolean nm_device_unrealize (NMDevice *device, + gboolean remove_resources, + GError **error); -void nm_device_handle_autoip4_event (NMDevice *self, - const char *event, - const char *address); +gboolean nm_device_get_autoconnect (NMDevice *device); +void nm_device_set_autoconnect (NMDevice *device, gboolean autoconnect); void nm_device_state_changed (NMDevice *device, NMDeviceState state, @@ -411,8 +491,11 @@ void nm_device_queue_state (NMDevice *self, NMDeviceStateReason reason); gboolean nm_device_get_firmware_missing (NMDevice *self); +gboolean nm_device_get_nm_plugin_missing (NMDevice *self); +void nm_device_set_nm_plugin_missing (NMDevice *self, + gboolean missing); -void nm_device_steal_connection (NMDevice *device, NMConnection *connection); +void nm_device_steal_connection (NMDevice *device, NMSettingsConnection *connection); void nm_device_queue_activation (NMDevice *device, NMActRequest *req); @@ -430,6 +513,7 @@ gboolean nm_device_check_connection_available (NMDevice *device, NMDeviceCheckConAvailableFlags flags, const char *specific_object); +void nm_device_notify_new_device_added (NMDevice *self, NMDevice *new_device); gboolean nm_device_notify_component_added (NMDevice *device, GObject *component); gboolean nm_device_owns_iface (NMDevice *device, const char *iface); @@ -441,9 +525,20 @@ const NMPlatformIP6Route *nm_device_get_ip6_default_route (NMDevice *self, gbool void nm_device_spawn_iface_helper (NMDevice *self); -G_END_DECLS +void nm_device_reapply_settings_immediately (NMDevice *self); + +void nm_device_update_firewall_zone (NMDevice *self); +void nm_device_update_metered (NMDevice *self); +void nm_device_reactivate_ip4_config (NMDevice *device, + NMSettingIPConfig *s_ip4_old, + NMSettingIPConfig *s_ip4_new); +void nm_device_reactivate_ip6_config (NMDevice *device, + NMSettingIPConfig *s_ip6_old, + NMSettingIPConfig *s_ip6_new); -/* For testing only */ -extern const char* nm_device_autoipd_helper_path; +void nm_device_update_hw_address (NMDevice *self); +void nm_device_update_initial_hw_address (NMDevice *self); + +G_END_DECLS #endif /* NM_DEVICE_H */ diff --git a/src/devices/nm-lldp-listener.c b/src/devices/nm-lldp-listener.c new file mode 100644 index 00000000..91181292 --- /dev/null +++ b/src/devices/nm-lldp-listener.c @@ -0,0 +1,648 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2015 Red Hat, Inc. + */ + +#include "config.h" + +#include <net/ethernet.h> + +#include "sd-lldp.h" +#include "lldp.h" +#include "nm-lldp-listener.h" +#include "nm-platform.h" +#include "nm-utils.h" + +#define MAX_NEIGHBORS 4096 +#define MIN_UPDATE_INTERVAL 2 + +typedef struct { + char *iface; + int ifindex; + sd_lldp *lldp_handle; + GHashTable *lldp_neighbors; + guint timer; + guint num_pending_events; + GVariant *variant; +} NMLldpListenerPrivate; + +enum { + PROP_0, + PROP_NEIGHBORS, + + LAST_PROP +}; + +G_DEFINE_TYPE (NMLldpListener, nm_lldp_listener, G_TYPE_OBJECT) + +#define NM_LLDP_LISTENER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_LLDP_LISTENER, NMLldpListenerPrivate)) + +typedef struct { + guint8 chassis_id_type; + guint8 port_id_type; + char *chassis_id; + char *port_id; + + int dest; + + GHashTable *tlvs; +} LLDPNeighbor; + +static void process_lldp_neighbors (NMLldpListener *self); + +static void +gvalue_destroy (gpointer data) +{ + GValue *value = (GValue *) data; + + g_value_unset (value); + g_slice_free (GValue, value); +} + +static GValue * +gvalue_new_nstr (const char *str, guint16 len) +{ + GValue *value; + + value = g_slice_new0 (GValue); + g_value_init (value, G_TYPE_STRING); + g_value_take_string (value, strndup (str, len)); + return value; +} + +static GValue * +gvalue_new_uint (guint val) +{ + GValue *value; + + value = g_slice_new0 (GValue); + g_value_init (value, G_TYPE_UINT); + g_value_set_uint (value, val); + return value; +} + +static guint +lldp_neighbor_id_hash (gconstpointer ptr) +{ + const LLDPNeighbor *neigh = ptr; + + return g_str_hash (neigh->chassis_id) ^ + g_str_hash (neigh->port_id) ^ + neigh->chassis_id_type ^ + (neigh->port_id_type * 33); +} + +static gboolean +lldp_neighbor_id_equal (gconstpointer a, gconstpointer b) +{ + const LLDPNeighbor *x = a, *y = b; + + return x->chassis_id_type == y->chassis_id_type && + x->port_id_type == y->port_id_type && + !g_strcmp0 (x->chassis_id, y->chassis_id) && + !g_strcmp0 (x->port_id, y->port_id); +} + +static void +lldp_neighbor_free (gpointer data) +{ + LLDPNeighbor *neighbor = data; + + if (neighbor) { + g_free (neighbor->chassis_id); + g_free (neighbor->port_id); + g_hash_table_unref (neighbor->tlvs); + g_free (neighbor); + } +} + +static gboolean +lldp_neighbor_equal (LLDPNeighbor *a, LLDPNeighbor *b) +{ + GHashTableIter iter; + gpointer k, v; + + g_return_val_if_fail (a && a->tlvs, FALSE); + g_return_val_if_fail (b && b->tlvs, FALSE); + + if ( a->chassis_id_type != b->chassis_id_type + || a->port_id_type != b->port_id_type + || a->dest != b->dest + || g_strcmp0 (a->chassis_id, b->chassis_id) + || g_strcmp0 (a->port_id, b->port_id)) + return FALSE; + + if (g_hash_table_size (a->tlvs) != g_hash_table_size (b->tlvs)) + return FALSE; + + g_hash_table_iter_init (&iter, a->tlvs); + while (g_hash_table_iter_next (&iter, &k, &v)) { + GValue *value_a, *value_b; + + value_a = v; + value_b = g_hash_table_lookup (b->tlvs, k); + + if (!value_b) + return FALSE; + + g_return_val_if_fail (G_VALUE_TYPE (value_a) == G_VALUE_TYPE (value_b), FALSE); + + if (G_VALUE_HOLDS_STRING (value_a)) { + if (g_strcmp0 (g_value_get_string (value_a), g_value_get_string (value_b))) + return FALSE; + } else if (G_VALUE_HOLDS_UINT (value_a)) { + if (g_value_get_uint (value_a) != g_value_get_uint (value_b)) + return FALSE; + } else + g_return_val_if_reached (FALSE); + } + + return TRUE; +} + +static gboolean +lldp_hash_table_equal (GHashTable *a, GHashTable *b) +{ + GHashTableIter iter; + gpointer val; + + g_return_val_if_fail (a, FALSE); + g_return_val_if_fail (b, FALSE); + + if (g_hash_table_size (a) != g_hash_table_size (b)) + return FALSE; + + g_hash_table_iter_init (&iter, a); + while (g_hash_table_iter_next (&iter, NULL, &val)) { + LLDPNeighbor *neigh_a, *neigh_b; + + neigh_a = val; + neigh_b = g_hash_table_lookup (b, val); + + if (!neigh_b) + return FALSE; + + if (!lldp_neighbor_equal (neigh_a, neigh_b)) + return FALSE; + } + + return TRUE; +} + +static gboolean +lldp_timeout (gpointer user_data) +{ + NMLldpListener *self = NM_LLDP_LISTENER (user_data); + NMLldpListenerPrivate *priv = NM_LLDP_LISTENER_GET_PRIVATE (self); + + priv->timer = 0; + + if (priv->num_pending_events) + process_lldp_neighbors (self); + + return G_SOURCE_REMOVE; +} + +static void +process_lldp_neighbors (NMLldpListener *self) +{ + NMLldpListenerPrivate *priv = NM_LLDP_LISTENER_GET_PRIVATE (self); + sd_lldp_packet **packets = NULL; + GHashTable *hash; + int num, i; + + num = sd_lldp_get_packets (priv->lldp_handle, &packets); + if (num < 0) { + nm_log_dbg (LOGD_DEVICE, "LLDP: error %d retrieving neighbor packets for %s", + num, priv->iface); + return; + } + + hash = g_hash_table_new_full (lldp_neighbor_id_hash, lldp_neighbor_id_equal, + lldp_neighbor_free, NULL); + + for (i = 0; packets && i < num; i++) { + uint8_t chassis_id_type, port_id_type, *chassis_id, *port_id, data8; + uint16_t chassis_id_len, port_id_len, len, data16; + LLDPNeighbor *neigh; + GValue *value; + char *str; + int r; + + if (i >= MAX_NEIGHBORS) + goto next_packet; + + r = sd_lldp_packet_read_chassis_id (packets[i], &chassis_id_type, + &chassis_id, &chassis_id_len); + if (r < 0) + goto next_packet; + + r = sd_lldp_packet_read_port_id (packets[i], &port_id_type, + &port_id, &port_id_len); + if (r < 0) + goto next_packet; + + neigh = g_malloc0 (sizeof (LLDPNeighbor)); + neigh->tlvs = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, gvalue_destroy); + neigh->chassis_id_type = chassis_id_type; + neigh->port_id_type = port_id_type; + sd_lldp_packet_get_destination_type (packets[i], &neigh->dest); + + if (chassis_id_len < 1) { + lldp_neighbor_free (neigh); + goto next_packet; + } + + switch (chassis_id_type) { + case LLDP_CHASSIS_SUBTYPE_INTERFACE_ALIAS: + case LLDP_CHASSIS_SUBTYPE_INTERFACE_NAME: + case LLDP_CHASSIS_SUBTYPE_LOCALLY_ASSIGNED: + case LLDP_CHASSIS_SUBTYPE_CHASSIS_COMPONENT: + neigh->chassis_id = strndup ((char *) chassis_id, chassis_id_len); + break; + case LLDP_CHASSIS_SUBTYPE_MAC_ADDRESS: + neigh->chassis_id = nm_utils_hwaddr_ntoa (chassis_id, chassis_id_len); + break; + default: + nm_log_dbg (LOGD_DEVICE, "LLDP: unsupported chassis ID type %d", chassis_id_type); + lldp_neighbor_free (neigh); + goto next_packet; + } + + if (port_id_len < 1) { + lldp_neighbor_free (neigh); + goto next_packet; + } + + switch (port_id_type) { + case LLDP_PORT_SUBTYPE_INTERFACE_ALIAS: + case LLDP_PORT_SUBTYPE_INTERFACE_NAME: + case LLDP_PORT_SUBTYPE_LOCALLY_ASSIGNED: + case LLDP_PORT_SUBTYPE_PORT_COMPONENT: + neigh->port_id = strndup ((char *) port_id, port_id_len); + break; + case LLDP_PORT_SUBTYPE_MAC_ADDRESS: + neigh->port_id = nm_utils_hwaddr_ntoa (port_id, port_id_len); + break; + default: + nm_log_dbg (LOGD_DEVICE, "LLDP: unsupported port ID type %d", port_id_type); + lldp_neighbor_free (neigh); + goto next_packet; + } + + if (sd_lldp_packet_read_port_description (packets[i], &str, &len) == 0) { + value = gvalue_new_nstr (str, len); + g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_PORT_DESCRIPTION, value); + } + + if (sd_lldp_packet_read_system_name (packets[i], &str, &len) == 0) { + value = gvalue_new_nstr (str, len); + g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_SYSTEM_NAME, value); + } + + if (sd_lldp_packet_read_system_description (packets[i], &str, &len) == 0) { + value = gvalue_new_nstr (str, len); + g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_SYSTEM_DESCRIPTION, value); + } + + if (sd_lldp_packet_read_system_capability (packets[i], &data16) == 0) { + value = gvalue_new_uint (data16); + g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_SYSTEM_CAPABILITIES, value); + } + + if (sd_lldp_packet_read_port_vlan_id (packets[i], &data16) == 0) { + value = gvalue_new_uint (data16); + g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_PVID, value); + } + + if (sd_lldp_packet_read_port_protocol_vlan_id (packets[i], &data8, &data16) == 0) { + value = gvalue_new_uint (data16); + g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_PPVID, value); + + value = gvalue_new_uint (data8); + g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_PPVID_FLAGS, value); + } + + if (sd_lldp_packet_read_vlan_name (packets[i], &data16, &str, &len) == 0) { + value = gvalue_new_uint (data16); + g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_VID, value); + + value = gvalue_new_nstr (str, len); + g_hash_table_insert (neigh->tlvs, NM_LLDP_ATTR_IEEE_802_1_VLAN_NAME, value); + } + + nm_log_dbg (LOGD_DEVICE, "LLDP: new neigh: CHASSIS='%s' PORT='%s'", + neigh->chassis_id, neigh->port_id); + + g_hash_table_add (hash, neigh); +next_packet: + sd_lldp_packet_unref (packets[i]); + } + + g_free (packets); + + if (lldp_hash_table_equal (priv->lldp_neighbors, hash)) { + g_hash_table_destroy (hash); + } else { + g_hash_table_destroy (priv->lldp_neighbors); + priv->lldp_neighbors = hash; + nm_clear_g_variant (&priv->variant); + g_object_notify (G_OBJECT (self), NM_LLDP_LISTENER_NEIGHBORS); + } + + /* Since the processing of the neighbor list is potentially + * expensive when there are many neighbors, coalesce multiple + * events arriving in short time. + */ + priv->timer = g_timeout_add_seconds (MIN_UPDATE_INTERVAL, lldp_timeout, self); + priv->num_pending_events = 0; +} + +static void +lldp_event_handler (sd_lldp *lldp, int event, void *userdata) +{ + NMLldpListener *self = userdata; + NMLldpListenerPrivate *priv; + + g_return_if_fail (NM_IS_LLDP_LISTENER (self)); + priv = NM_LLDP_LISTENER_GET_PRIVATE (self); + + if (priv->timer > 0) { + priv->num_pending_events++; + return; + } + + process_lldp_neighbors (self); +} + +gboolean +nm_lldp_listener_start (NMLldpListener *self, int ifindex, const char *iface, + const guint8 *mac, guint mac_len, GError **error) +{ + NMLldpListenerPrivate *priv; + int ret; + + g_return_val_if_fail (NM_IS_LLDP_LISTENER (self), FALSE); + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (iface, FALSE); + g_return_val_if_fail (!error || !*error, FALSE); + + priv = NM_LLDP_LISTENER_GET_PRIVATE (self); + + if (priv->lldp_handle) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "already running"); + return FALSE; + } + + if (!mac || mac_len != ETH_ALEN) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "unsupported device"); + return FALSE; + } + + ret = sd_lldp_new (ifindex, iface, (struct ether_addr *) mac, &priv->lldp_handle); + if (ret) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "initialization failed"); + return FALSE; + } + + ret = sd_lldp_attach_event (priv->lldp_handle, NULL, 0); + if (ret) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "attach event failed"); + goto err_free; + } + + ret = sd_lldp_set_callback (priv->lldp_handle, lldp_event_handler, self); + if (ret) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "set callback failed"); + goto err; + } + + ret = sd_lldp_start (priv->lldp_handle); + if (ret) { + g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_FAILED, + "start failed"); + goto err; + } + + priv->ifindex = ifindex; + priv->iface = strdup (iface); + return TRUE; + +err: + sd_lldp_detach_event (priv->lldp_handle); +err_free: + sd_lldp_unref (priv->lldp_handle); + priv->lldp_handle = NULL; + return FALSE; +} + +void +nm_lldp_listener_stop (NMLldpListener *self) +{ + NMLldpListenerPrivate *priv; + guint size; + + g_return_if_fail (NM_IS_LLDP_LISTENER (self)); + priv = NM_LLDP_LISTENER_GET_PRIVATE (self); + + if (priv->lldp_handle) { + sd_lldp_stop (priv->lldp_handle); + sd_lldp_detach_event (priv->lldp_handle); + sd_lldp_unref (priv->lldp_handle); + g_clear_pointer (&priv->iface, g_free); + priv->lldp_handle = NULL; + + size = g_hash_table_size (priv->lldp_neighbors); + g_hash_table_remove_all (priv->lldp_neighbors); + if (size) { + nm_clear_g_variant (&priv->variant); + g_object_notify (G_OBJECT (self), NM_LLDP_LISTENER_NEIGHBORS); + } + } + + nm_clear_g_source (&priv->timer); +} + +gboolean +nm_lldp_listener_is_running (NMLldpListener *self) +{ + NMLldpListenerPrivate *priv; + + g_return_val_if_fail (NM_IS_LLDP_LISTENER (self), FALSE); + + priv = NM_LLDP_LISTENER_GET_PRIVATE (self); + return !!priv->lldp_handle; +} + +GVariant * +nm_lldp_listener_get_neighbors (NMLldpListener *self) +{ + GVariantBuilder array_builder, neigh_builder; + GHashTableIter iter; + NMLldpListenerPrivate *priv; + LLDPNeighbor *neigh; + char *dest_str = NULL; + + priv = NM_LLDP_LISTENER_GET_PRIVATE (self); + + if (priv->variant) + goto out; + + g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("aa{sv}")); + g_hash_table_iter_init (&iter, priv->lldp_neighbors); + + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &neigh)) { + GHashTableIter val_iter; + gpointer key, val; + + g_variant_builder_init (&neigh_builder, G_VARIANT_TYPE ("a{sv}")); + + g_variant_builder_add (&neigh_builder, "{sv}", + NM_LLDP_ATTR_CHASSIS_ID_TYPE, + g_variant_new_uint32 (neigh->chassis_id_type)); + g_variant_builder_add (&neigh_builder, "{sv}", + NM_LLDP_ATTR_CHASSIS_ID, + g_variant_new_string (neigh->chassis_id)); + g_variant_builder_add (&neigh_builder, "{sv}", + NM_LLDP_ATTR_PORT_ID_TYPE, + g_variant_new_uint32 (neigh->port_id_type)); + g_variant_builder_add (&neigh_builder, "{sv}", + NM_LLDP_ATTR_PORT_ID, + g_variant_new_string (neigh->port_id)); + + switch (neigh->dest) { + case SD_LLDP_DESTINATION_TYPE_NEAREST_BRIDGE: + dest_str = NM_LLDP_DEST_NEAREST_BRIDGE; + break; + case SD_LLDP_DESTINATION_TYPE_NEAREST_NON_TPMR_BRIDGE: + dest_str = NM_LLDP_DEST_NEAREST_NON_TPMR_BRIDGE; + break; + case SD_LLDP_DESTINATION_TYPE_NEAREST_CUSTOMER_BRIDGE: + dest_str = NM_LLDP_DEST_NEAREST_CUSTOMER_BRIDGE; + break; + } + + if (dest_str) { + g_variant_builder_add (&neigh_builder, "{sv}", + NM_LLDP_ATTR_DESTINATION, + g_variant_new_string (dest_str)); + } + + g_hash_table_iter_init (&val_iter, neigh->tlvs); + while (g_hash_table_iter_next (&val_iter, &key, &val)) { + GValue *item = val; + + if (G_VALUE_HOLDS_STRING (item)) { + g_variant_builder_add (&neigh_builder, "{sv}", + key, + g_variant_new_string (g_value_get_string (item))); + } else if (G_VALUE_HOLDS_UINT (item)) { + g_variant_builder_add (&neigh_builder, "{sv}", + key, + g_variant_new_uint32 (g_value_get_uint (item))); + } + } + + g_variant_builder_add (&array_builder, "a{sv}", &neigh_builder); + } + + priv->variant = g_variant_ref_sink (g_variant_builder_end (&array_builder)); + +out: + return priv->variant; +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMLldpListener *self = NM_LLDP_LISTENER (object); + + switch (prop_id) { + case PROP_NEIGHBORS: + g_value_set_variant (value, nm_lldp_listener_get_neighbors (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_lldp_listener_init (NMLldpListener *self) +{ + NMLldpListenerPrivate *priv = NM_LLDP_LISTENER_GET_PRIVATE (self); + + priv->lldp_neighbors = g_hash_table_new_full (lldp_neighbor_id_hash, + lldp_neighbor_id_equal, + lldp_neighbor_free, NULL); +} + +NMLldpListener * +nm_lldp_listener_new (void) +{ + return (NMLldpListener *) g_object_new (NM_TYPE_LLDP_LISTENER, NULL); +} + +static void +dispose (GObject *object) +{ + nm_lldp_listener_stop (NM_LLDP_LISTENER (object)); + + G_OBJECT_CLASS (nm_lldp_listener_parent_class)->dispose (object); +} + +static void +finalize (GObject *object) +{ + NMLldpListener *self = NM_LLDP_LISTENER (object); + NMLldpListenerPrivate *priv = NM_LLDP_LISTENER_GET_PRIVATE (self); + + nm_lldp_listener_stop (self); + g_hash_table_unref (priv->lldp_neighbors); + + nm_clear_g_variant (&priv->variant); + + G_OBJECT_CLASS (nm_lldp_listener_parent_class)->finalize (object); +} + +static void +nm_lldp_listener_class_init (NMLldpListenerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMLldpListenerPrivate)); + + object_class->dispose = dispose; + object_class->finalize = finalize; + object_class->get_property = get_property; + + g_object_class_install_property + (object_class, PROP_NEIGHBORS, + g_param_spec_variant (NM_LLDP_LISTENER_NEIGHBORS, "", "", + G_VARIANT_TYPE ("aa{sv}"), + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); +} + diff --git a/src/devices/nm-lldp-listener.h b/src/devices/nm-lldp-listener.h new file mode 100644 index 00000000..492752c1 --- /dev/null +++ b/src/devices/nm-lldp-listener.h @@ -0,0 +1,57 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2015 Red Hat, Inc. + */ + +#ifndef __NM_LLDP_LISTENER__ +#define __NM_LLDP_LISTENER__ + +#include "nm-glib.h" +#include "nm-types.h" + +G_BEGIN_DECLS + +#define NM_TYPE_LLDP_LISTENER (nm_lldp_listener_get_type ()) +#define NM_LLDP_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_LLDP_LISTENER, NMLldpListener)) +#define NM_LLDP_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_LLDP_LISTENER, NMLldpListenerClass)) +#define NM_IS_LLDP_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_LLDP_LISTENER)) +#define NM_IS_LLDP_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_LLDP_LISTENER)) +#define NM_LLDP_LISTENER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_LLDP_LISTENER, NMLldpListenerClass)) + +#define NM_LLDP_LISTENER_NEIGHBORS "neighbors" + +struct _NMLldpListener { + GObject parent; +}; + +typedef struct { + GObjectClass parent; +} NMLldpListenerClass; + +GType nm_lldp_listener_get_type (void); +NMLldpListener *nm_lldp_listener_new (void); +gboolean nm_lldp_listener_start (NMLldpListener *self, int ifindex, const char *iface, + const guint8 *mac, guint mac_len, GError **error); +void nm_lldp_listener_stop (NMLldpListener *self); +gboolean nm_lldp_listener_is_running (NMLldpListener *self); + +GVariant *nm_lldp_listener_get_neighbors (NMLldpListener *self); + +G_END_DECLS + +#endif /* __NM_LLDP_LISTENER__ */ diff --git a/src/devices/team/Makefile.am b/src/devices/team/Makefile.am index 46c5fe1d..a6645833 100644 --- a/src/devices/team/Makefile.am +++ b/src/devices/team/Makefile.am @@ -7,32 +7,20 @@ AM_CPPFLAGS = \ -I${top_builddir}/src \ -I${top_srcdir}/src/devices \ -I${top_srcdir}/src/platform \ - -I${top_srcdir}/include \ - -I$(top_builddir)/include \ + -I${top_builddir}/introspection \ + -I${top_srcdir}/shared \ + -I$(top_builddir)/shared \ -I${top_builddir}/libnm-core \ -I${top_srcdir}/libnm-core \ -DG_LOG_DOMAIN=\""NetworkManager-team"\" \ - -DNETWORKMANAGER_COMPILATION \ + -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ - $(DBUS_CFLAGS) + $(GLIB_CFLAGS) if WITH_TEAMDCTL AM_CPPFLAGS += ${LIBTEAMDCTL_CFLAGS} endif -GLIB_GENERATED = nm-team-enum-types.h nm-team-enum-types.c -GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM -GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM -nm_team_enum_types_sources = $(srcdir)/nm-device-team.h - -glue_sources = \ - nm-device-team-glue.h - -%-glue.h: $(top_srcdir)/introspection/%.xml - $(AM_V_GEN) dbus-binding-tool --prefix=$(subst -,_,$(subst -glue.h,,$@)) --mode=glib-server --output=$@ $< - -BUILT_SOURCES = $(GLIB_GENERATED) $(glue_sources) - pkglib_LTLIBRARIES = libnm-device-plugin-team.la SYMBOL_VIS_FILE=$(srcdir)/exports.ver @@ -41,23 +29,21 @@ libnm_device_plugin_team_la_SOURCES = \ nm-device-team.c \ nm-device-team.h \ nm-team-factory.c \ - nm-team-factory.h \ - \ - $(BUILT_SOURCES) + nm-team-factory.h libnm_device_plugin_team_la_LDFLAGS = \ -module -avoid-version \ -Wl,--version-script=$(SYMBOL_VIS_FILE) libnm_device_plugin_team_la_LIBADD = \ - $(DBUS_LIBS) \ + $(top_builddir)/introspection/libnmdbus.la \ + $(GLIB_LIBS) \ $(GUDEV_LIBS) if WITH_TEAMDCTL libnm_device_plugin_team_la_LIBADD += $(LIBTEAMDCTL_LIBS) endif -CLEANFILES = $(BUILT_SOURCES) EXTRA_DIST = $(SYMBOL_VIS_FILE) if ENABLE_TESTS diff --git a/src/devices/team/Makefile.in b/src/devices/team/Makefile.in index 7305b05a..6dce463e 100644 --- a/src/devices/team/Makefile.in +++ b/src/devices/team/Makefile.in @@ -143,13 +143,12 @@ am__installdirs = "$(DESTDIR)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) am__DEPENDENCIES_1 = @WITH_TEAMDCTL_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) -libnm_device_plugin_team_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) -am__objects_1 = nm-team-enum-types.lo -am__objects_2 = -am__objects_3 = $(am__objects_1) $(am__objects_2) +libnm_device_plugin_team_la_DEPENDENCIES = \ + $(top_builddir)/introspection/libnmdbus.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_2) am_libnm_device_plugin_team_la_OBJECTS = nm-device-team.lo \ - nm-team-factory.lo $(am__objects_3) + nm-team-factory.lo libnm_device_plugin_team_la_OBJECTS = \ $(am_libnm_device_plugin_team_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) @@ -238,7 +237,6 @@ BLUEZ5_LIBS = @BLUEZ5_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ -CKDB_PATH = @CKDB_PATH@ CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ @@ -250,8 +248,6 @@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DBUS_CFLAGS = @DBUS_CFLAGS@ -DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@ -DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@ DBUS_LIBS = @DBUS_LIBS@ DBUS_SYS_DIR = @DBUS_SYS_DIR@ DEFS = @DEFS@ @@ -261,6 +257,7 @@ DHCPCD_PATH = @DHCPCD_PATH@ DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ DLLTOOL = @DLLTOOL@ DNSMASQ_PATH = @DNSMASQ_PATH@ +DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ @@ -315,16 +312,13 @@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ IPTABLES_PATH = @IPTABLES_PATH@ -IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ -IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ +LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@ +LIBAUDIT_LIBS = @LIBAUDIT_LIBS@ LIBDL = @LIBDL@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ @@ -361,6 +355,8 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ +NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ NM_MICRO_VERSION = @NM_MICRO_VERSION@ NM_MINOR_VERSION = @NM_MINOR_VERSION@ @@ -389,7 +385,6 @@ POLKIT_LIBS = @POLKIT_LIBS@ POSUB = @POSUB@ PPPD_PATH = @PPPD_PATH@ PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ -PPPOE_PATH = @PPPOE_PATH@ QT_CFLAGS = @QT_CFLAGS@ QT_LIBS = @QT_LIBS@ RANLIB = @RANLIB@ @@ -404,6 +399,8 @@ SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ +SYSTEMD_JOURNAL_CFLAGS = @SYSTEMD_JOURNAL_CFLAGS@ +SYSTEMD_JOURNAL_LIBS = @SYSTEMD_JOURNAL_LIBS@ SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ @@ -464,6 +461,7 @@ mkdir_p = @mkdir_p@ nmbinary = @nmbinary@ nmconfdir = @nmconfdir@ nmdatadir = @nmdatadir@ +nmlibdir = @nmlibdir@ nmrundir = @nmrundir@ nmstatedir = @nmstatedir@ oldincludedir = @oldincludedir@ @@ -471,6 +469,7 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -488,40 +487,30 @@ with_resolvconf = @with_resolvconf@ with_valgrind = @with_valgrind@ AM_CPPFLAGS = -I${top_srcdir}/src -I${top_builddir}/src \ -I${top_srcdir}/src/devices -I${top_srcdir}/src/platform \ - -I${top_srcdir}/include -I$(top_builddir)/include \ - -I${top_builddir}/libnm-core -I${top_srcdir}/libnm-core \ + -I${top_builddir}/introspection -I${top_srcdir}/shared \ + -I$(top_builddir)/shared -I${top_builddir}/libnm-core \ + -I${top_srcdir}/libnm-core \ -DG_LOG_DOMAIN=\""NetworkManager-team"\" \ - -DNETWORKMANAGER_COMPILATION \ - -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE $(DBUS_CFLAGS) \ + -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE $(GLIB_CFLAGS) \ $(am__append_1) -GLIB_GENERATED = nm-team-enum-types.h nm-team-enum-types.c -GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM -GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM -nm_team_enum_types_sources = $(srcdir)/nm-device-team.h -glue_sources = \ - nm-device-team-glue.h - -BUILT_SOURCES = $(GLIB_GENERATED) $(glue_sources) pkglib_LTLIBRARIES = libnm-device-plugin-team.la SYMBOL_VIS_FILE = $(srcdir)/exports.ver libnm_device_plugin_team_la_SOURCES = \ nm-device-team.c \ nm-device-team.h \ nm-team-factory.c \ - nm-team-factory.h \ - \ - $(BUILT_SOURCES) + nm-team-factory.h libnm_device_plugin_team_la_LDFLAGS = \ -module -avoid-version \ -Wl,--version-script=$(SYMBOL_VIS_FILE) -libnm_device_plugin_team_la_LIBADD = $(DBUS_LIBS) $(GUDEV_LIBS) \ - $(am__append_2) -CLEANFILES = $(BUILT_SOURCES) +libnm_device_plugin_team_la_LIBADD = \ + $(top_builddir)/introspection/libnmdbus.la $(GLIB_LIBS) \ + $(GUDEV_LIBS) $(am__append_2) EXTRA_DIST = $(SYMBOL_VIS_FILE) -all: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) all-am +all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj @@ -600,7 +589,6 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-team.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-team-enum-types.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-team-factory.Plo@am__quote@ .c.o: @@ -715,15 +703,13 @@ distdir: $(DISTFILES) @ENABLE_TESTS_FALSE@check-local: check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local -check: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) check-am +check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(pkglibdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done -install: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) install-am +install: install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am @@ -745,7 +731,6 @@ install-strip: mostlyclean-generic: clean-generic: - -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) @@ -754,7 +739,6 @@ distclean-generic: maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." - -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-am clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ @@ -826,7 +810,7 @@ ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES -.MAKE: all check check-am install install-am install-strip +.MAKE: check-am install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am check-local clean \ clean-generic clean-libtool clean-pkglibLTLIBRARIES \ @@ -849,9 +833,6 @@ include $(GLIB_MAKEFILE) @GNOME_CODE_COVERAGE_RULES@ -%-glue.h: $(top_srcdir)/introspection/%.xml - $(AM_V_GEN) dbus-binding-tool --prefix=$(subst -,_,$(subst -glue.h,,$@)) --mode=glib-server --output=$@ $< - @ENABLE_TESTS_TRUE@check-local: @ENABLE_TESTS_TRUE@ $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-team.so $(SYMBOL_VIS_FILE) diff --git a/src/devices/team/nm-device-team-glue.h b/src/devices/team/nm-device-team-glue.h deleted file mode 100644 index 405975c8..00000000 --- a/src/devices/team/nm-device-team-glue.h +++ /dev/null @@ -1,73 +0,0 @@ -/* Generated by dbus-binding-tool; do not edit! */ - - -#ifndef __dbus_glib_marshal_nm_device_team_MARSHAL_H__ -#define __dbus_glib_marshal_nm_device_team_MARSHAL_H__ - -#include <glib-object.h> - -G_BEGIN_DECLS - -#ifdef G_ENABLE_DEBUG -#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) -#define g_marshal_value_peek_char(v) g_value_get_schar (v) -#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) -#define g_marshal_value_peek_int(v) g_value_get_int (v) -#define g_marshal_value_peek_uint(v) g_value_get_uint (v) -#define g_marshal_value_peek_long(v) g_value_get_long (v) -#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) -#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) -#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) -#define g_marshal_value_peek_enum(v) g_value_get_enum (v) -#define g_marshal_value_peek_flags(v) g_value_get_flags (v) -#define g_marshal_value_peek_float(v) g_value_get_float (v) -#define g_marshal_value_peek_double(v) g_value_get_double (v) -#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) -#define g_marshal_value_peek_param(v) g_value_get_param (v) -#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) -#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) -#define g_marshal_value_peek_object(v) g_value_get_object (v) -#define g_marshal_value_peek_variant(v) g_value_get_variant (v) -#else /* !G_ENABLE_DEBUG */ -/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. - * Do not access GValues directly in your code. Instead, use the - * g_value_get_*() functions - */ -#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int -#define g_marshal_value_peek_char(v) (v)->data[0].v_int -#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint -#define g_marshal_value_peek_int(v) (v)->data[0].v_int -#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint -#define g_marshal_value_peek_long(v) (v)->data[0].v_long -#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong -#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 -#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 -#define g_marshal_value_peek_enum(v) (v)->data[0].v_long -#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong -#define g_marshal_value_peek_float(v) (v)->data[0].v_float -#define g_marshal_value_peek_double(v) (v)->data[0].v_double -#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer -#endif /* !G_ENABLE_DEBUG */ - - -G_END_DECLS - -#endif /* __dbus_glib_marshal_nm_device_team_MARSHAL_H__ */ - -#include <dbus/dbus-glib.h> -static const DBusGMethodInfo dbus_glib_nm_device_team_methods[] = { -}; - -const DBusGObjectInfo dbus_glib_nm_device_team_object_info = { 1, - dbus_glib_nm_device_team_methods, - 0, -"\0", -"org.freedesktop.NetworkManager.Device.Team\0PropertiesChanged\0\0", -"org.freedesktop.NetworkManager.Device.Team\0HwAddress\0hw_address\0read\0org.freedesktop.NetworkManager.Device.Team\0Carrier\0carrier\0read\0org.freedesktop.NetworkManager.Device.Team\0Slaves\0slaves\0read\0\0" -}; - diff --git a/src/devices/team/nm-device-team.c b/src/devices/team/nm-device-team.c index 1950fd2a..c0b83b84 100644 --- a/src/devices/team/nm-device-team.c +++ b/src/devices/team/nm-device-team.c @@ -24,26 +24,20 @@ #include <unistd.h> #include <signal.h> #include <sys/wait.h> -#include <glib.h> -#include <glib/gi18n.h> -#include <gio/gio.h> #include <teamdctl.h> #include <stdlib.h> +#include "nm-default.h" #include "nm-device-team.h" -#include "nm-logging.h" #include "NetworkManagerUtils.h" #include "nm-device-private.h" #include "nm-platform.h" -#include "nm-dbus-glib-types.h" -#include "nm-dbus-manager.h" #include "nm-enum-types.h" -#include "nm-team-enum-types.h" #include "nm-core-internal.h" #include "nm-ip4-config.h" -#include "gsystem-local-alloc.h" +#include "nm-dbus-compat.h" -#include "nm-device-team-glue.h" +#include "nmdbus-device-team.h" #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceTeam); @@ -60,13 +54,6 @@ typedef struct { guint teamd_dbus_watch; } NMDeviceTeamPrivate; -enum { - PROP_0, - PROP_SLAVES, - - LAST_PROP -}; - static gboolean teamd_start (NMDevice *device, NMSettingTeam *s_team); /******************************************************************/ @@ -265,15 +252,8 @@ teamd_cleanup (NMDevice *device, gboolean free_tdc) { NMDeviceTeamPrivate *priv = NM_DEVICE_TEAM_GET_PRIVATE (device); - if (priv->teamd_process_watch) { - g_source_remove (priv->teamd_process_watch); - priv->teamd_process_watch = 0; - } - - if (priv->teamd_timeout) { - g_source_remove (priv->teamd_timeout); - priv->teamd_timeout = 0; - } + nm_clear_g_source (&priv->teamd_process_watch); + nm_clear_g_source (&priv->teamd_timeout); if (priv->teamd_pid > 0) { nm_utils_kill_child_async (priv->teamd_pid, SIGTERM, LOGD_TEAM, "teamd", 2000, NULL, NULL); @@ -333,9 +313,9 @@ teamd_dbus_appeared (GDBusConnection *connection, guint32 pid; ret = g_dbus_connection_call_sync (connection, - "org.freedesktop.DBus", - "/org/freedesktop/DBus", - "org.freedesktop.DBus", + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, "GetConnectionUnixProcessID", g_variant_new ("(s)", name_owner), NULL, @@ -388,7 +368,7 @@ teamd_dbus_vanished (GDBusConnection *dbus_connection, /* Attempt to respawn teamd */ if (state >= NM_DEVICE_STATE_PREPARE && state <= NM_DEVICE_STATE_ACTIVATED) { - NMConnection *connection = nm_device_get_connection (device); + NMConnection *connection = nm_device_get_applied_connection (device); g_assert (connection); if (!teamd_start (device, nm_connection_get_setting_team (connection))) @@ -531,7 +511,7 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) if (ret != NM_ACT_STAGE_RETURN_SUCCESS) return ret; - connection = nm_device_get_connection (device); + connection = nm_device_get_applied_connection (device); g_assert (connection); s_team = nm_connection_get_setting_team (connection); g_assert (s_team); @@ -572,7 +552,7 @@ ip4_config_pre_commit (NMDevice *self, NMIP4Config *config) NMSettingWired *s_wired; guint32 mtu; - connection = nm_device_get_connection (self); + connection = nm_device_get_applied_connection (self); g_assert (connection); s_wired = nm_connection_get_setting_wired (connection); @@ -650,18 +630,16 @@ enslave_slave (NMDevice *device, } else _LOGI (LOGD_TEAM, "team port %s was enslaved", slave_iface); - g_object_notify (G_OBJECT (device), NM_DEVICE_TEAM_SLAVES); - return TRUE; } -static gboolean +static void release_slave (NMDevice *device, NMDevice *slave, gboolean configure) { NMDeviceTeam *self = NM_DEVICE_TEAM (device); - gboolean success = TRUE, no_firmware = FALSE; + gboolean success, no_firmware = FALSE; if (configure) { success = nm_platform_link_release (NM_PLATFORM_GET, @@ -672,13 +650,7 @@ release_slave (NMDevice *device, _LOGI (LOGD_TEAM, "released team port %s", nm_device_get_ip_iface (slave)); else _LOGW (LOGD_TEAM, "failed to release team port %s", nm_device_get_ip_iface (slave)); - } else - _LOGI (LOGD_TEAM, "team port %s was released", nm_device_get_ip_iface (slave)); - - if (success) - g_object_notify (G_OBJECT (device), NM_DEVICE_TEAM_SLAVES); - if (configure) { /* Kernel team code "closes" the port when releasing it, (which clears * IFF_UP), so we must bring it back up here to ensure carrier changes and * other state is noticed by the now-released port. @@ -686,50 +658,44 @@ release_slave (NMDevice *device, if (!nm_device_bring_up (slave, TRUE, &no_firmware)) _LOGW (LOGD_TEAM, "released team port %s could not be brought up", nm_device_get_ip_iface (slave)); - } - - return success; -} - -/******************************************************************/ - -NMDevice * -nm_device_team_new (NMPlatformLink *platform_device) -{ - return (NMDevice *) g_object_new (NM_TYPE_DEVICE_TEAM, - NM_DEVICE_PLATFORM_DEVICE, platform_device, - NM_DEVICE_DRIVER, "team", - NM_DEVICE_TYPE_DESC, "Team", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_TEAM, - NM_DEVICE_IS_MASTER, TRUE, - NULL); + } else + _LOGI (LOGD_TEAM, "team port %s was released", nm_device_get_ip_iface (slave)); } -NMDevice * -nm_device_team_new_for_connection (NMConnection *connection, GError **error) +static gboolean +create_and_realize (NMDevice *device, + NMConnection *connection, + NMDevice *parent, + const NMPlatformLink **out_plink, + GError **error) { - const char *iface = nm_connection_get_interface_name (connection); + const char *iface = nm_device_get_iface (device); NMPlatformError plerr; - const NMPlatformLink *plink; - - g_assert (iface); - plerr = nm_platform_team_add (NM_PLATFORM_GET, iface, NULL); + plerr = nm_platform_link_team_add (NM_PLATFORM_GET, iface, out_plink); if (plerr != NM_PLATFORM_ERROR_SUCCESS && plerr != NM_PLATFORM_ERROR_EXISTS) { g_set_error (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_CREATION_FAILED, "Failed to create team master interface '%s' for '%s': %s", iface, nm_connection_get_id (connection), nm_platform_error_to_string (plerr)); - return NULL; + return FALSE; } - plink = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, iface); + return TRUE; +} + +/******************************************************************/ + +NMDevice * +nm_device_team_new (const char *iface) +{ return (NMDevice *) g_object_new (NM_TYPE_DEVICE_TEAM, - NM_DEVICE_PLATFORM_DEVICE, plink, + NM_DEVICE_IFACE, iface, NM_DEVICE_DRIVER, "team", NM_DEVICE_TYPE_DESC, "Team", NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_TEAM, + NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_TEAM, NM_DEVICE_IS_MASTER, TRUE, NULL); } @@ -761,40 +727,6 @@ constructed (GObject *object) } static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - GPtrArray *slaves; - GSList *list, *iter; - - switch (prop_id) { - break; - case PROP_SLAVES: - slaves = g_ptr_array_new (); - list = nm_device_master_get_slaves (NM_DEVICE (object)); - for (iter = list; iter; iter = iter->next) - g_ptr_array_add (slaves, g_strdup (nm_device_get_path (NM_DEVICE (iter->data)))); - g_slist_free (list); - g_value_take_boxed (value, slaves); - 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) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void dispose (GObject *object) { NMDevice *device = NM_DEVICE (object); @@ -818,14 +750,12 @@ nm_device_team_class_init (NMDeviceTeamClass *klass) g_type_class_add_private (object_class, sizeof (NMDeviceTeamPrivate)); - parent_class->connection_type = NM_SETTING_TEAM_SETTING_NAME; + NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_TEAM_SETTING_NAME, NM_LINK_TYPE_TEAM) - /* virtual methods */ object_class->constructed = constructed; - object_class->get_property = get_property; - object_class->set_property = set_property; object_class->dispose = dispose; + parent_class->create_and_realize = create_and_realize; parent_class->get_generic_capabilities = get_generic_capabilities; parent_class->is_available = is_available; parent_class->check_connection_compatible = check_connection_compatible; @@ -840,15 +770,7 @@ nm_device_team_class_init (NMDeviceTeamClass *klass) parent_class->enslave_slave = enslave_slave; parent_class->release_slave = release_slave; - /* properties */ - g_object_class_install_property - (object_class, PROP_SLAVES, - g_param_spec_boxed (NM_DEVICE_TEAM_SLAVES, "", "", - DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), - G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_team_object_info); + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_TEAM_SKELETON, + NULL); } diff --git a/src/devices/team/nm-device-team.h b/src/devices/team/nm-device-team.h index 26ba5737..0e81afa7 100644 --- a/src/devices/team/nm-device-team.h +++ b/src/devices/team/nm-device-team.h @@ -21,8 +21,6 @@ #ifndef __NETWORKMANAGER_DEVICE_TEAM_H__ #define __NETWORKMANAGER_DEVICE_TEAM_H__ -#include <glib-object.h> - #include "nm-device.h" G_BEGIN_DECLS @@ -34,22 +32,12 @@ G_BEGIN_DECLS #define NM_IS_DEVICE_TEAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_TEAM)) #define NM_DEVICE_TEAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_TEAM, NMDeviceTeamClass)) -#define NM_DEVICE_TEAM_SLAVES "slaves" - -typedef struct { - NMDevice parent; -} NMDeviceTeam; - -typedef struct { - NMDeviceClass parent; - -} NMDeviceTeamClass; - +typedef NMDevice NMDeviceTeam; +typedef NMDeviceClass NMDeviceTeamClass; GType nm_device_team_get_type (void); -NMDevice *nm_device_team_new (NMPlatformLink *platform_device); -NMDevice *nm_device_team_new_for_connection (NMConnection *connection, GError **error); +NMDevice *nm_device_team_new (const char *iface); G_END_DECLS diff --git a/src/devices/team/nm-team-enum-types.c b/src/devices/team/nm-team-enum-types.c deleted file mode 100644 index 5ac3494d..00000000 --- a/src/devices/team/nm-team-enum-types.c +++ /dev/null @@ -1,12 +0,0 @@ - - - -/* Generated by glib-mkenums. Do not edit */ - -#include "nm-team-enum-types.h" - -#include "nm-device-team.h" - - - - diff --git a/src/devices/team/nm-team-enum-types.h b/src/devices/team/nm-team-enum-types.h deleted file mode 100644 index 136cadc2..00000000 --- a/src/devices/team/nm-team-enum-types.h +++ /dev/null @@ -1,17 +0,0 @@ - - - -/* Generated by glib-mkenums. Do not edit */ - -#ifndef __NM_TEAM_ENUM_TYPES_H__ -#define __NM_TEAM_ENUM_TYPES_H__ - -#include <glib-object.h> - -G_BEGIN_DECLS -G_END_DECLS - -#endif /* __NM_TEAM_ENUM_TYPES_H__ */ - - - diff --git a/src/devices/team/nm-team-factory.c b/src/devices/team/nm-team-factory.c index d87919b6..5f9e142a 100644 --- a/src/devices/team/nm-team-factory.c +++ b/src/devices/team/nm-team-factory.c @@ -26,13 +26,13 @@ #include "nm-device-factory.h" #include "nm-team-factory.h" #include "nm-device-team.h" -#include "nm-logging.h" +#include "nm-default.h" #include "nm-platform.h" #include "nm-core-internal.h" static GType nm_team_factory_get_type (void); -static void device_factory_interface_init (NMDeviceFactory *factory_iface); +static void device_factory_interface_init (NMDeviceFactoryInterface *factory_iface); G_DEFINE_TYPE_EXTENDED (NMTeamFactory, nm_team_factory, G_TYPE_OBJECT, 0, G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_FACTORY, device_factory_interface_init)) @@ -48,18 +48,13 @@ nm_device_factory_create (GError **error) /************************************************************************/ static NMDevice * -new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error) +create_device (NMDeviceFactory *factory, + const char *iface, + const NMPlatformLink *plink, + NMConnection *connection, + gboolean *out_ignore) { - return nm_device_team_new (plink); -} - -static NMDevice * -create_virtual_device_for_connection (NMDeviceFactory *factory, - NMConnection *connection, - NMDevice *parent, - GError **error) -{ - return nm_device_team_new_for_connection (connection, error); + return nm_device_team_new (iface); } NM_DEVICE_FACTORY_DECLARE_TYPES ( @@ -75,10 +70,9 @@ nm_team_factory_init (NMTeamFactory *self) } static void -device_factory_interface_init (NMDeviceFactory *factory_iface) +device_factory_interface_init (NMDeviceFactoryInterface *factory_iface) { - factory_iface->new_link = new_link; - factory_iface->create_virtual_device_for_connection = create_virtual_device_for_connection; + factory_iface->create_device = create_device; factory_iface->get_supported_types = get_supported_types; } diff --git a/src/devices/team/nm-team-factory.h b/src/devices/team/nm-team-factory.h index 2f02ac57..9049478d 100644 --- a/src/devices/team/nm-team-factory.h +++ b/src/devices/team/nm-team-factory.h @@ -21,7 +21,7 @@ #ifndef __NETWORKMANAGER_TEAM_FACTORY_H__ #define __NETWORKMANAGER_TEAM_FACTORY_H__ -#include <glib-object.h> +#include "nm-default.h" #define NM_TYPE_TEAM_FACTORY (nm_team_factory_get_type ()) #define NM_TEAM_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_TEAM_FACTORY, NMTeamFactory)) diff --git a/src/devices/tests/Makefile.am b/src/devices/tests/Makefile.am new file mode 100644 index 00000000..330377b0 --- /dev/null +++ b/src/devices/tests/Makefile.am @@ -0,0 +1,42 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/shared \ + -I$(top_builddir)/shared \ + -I$(top_srcdir)/libnm-core \ + -I$(top_builddir)/libnm-core \ + -I$(top_srcdir)/src/platform \ + -I$(top_srcdir)/src/devices \ + -I$(top_srcdir)/src/systemd/ \ + -I$(top_srcdir)/src/systemd/src/systemd/ \ + -I$(top_srcdir)/src/systemd/src/libsystemd-network/ \ + -I$(top_srcdir)/src \ + -I$(top_builddir)/src \ + -DG_LOG_DOMAIN=\""NetworkManager"\" \ + -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(GLIB_CFLAGS) + +AM_CFLAGS = $(CODE_COVERAGE_CFLAGS) +AM_LDFLAGS = $(GLIB_LIBS) $(CODE_COVERAGE_LDFLAGS) +DEVICES_LDADD = \ + $(top_builddir)/src/libNetworkManager.la + +@GNOME_CODE_COVERAGE_RULES@ + +noinst_PROGRAMS = \ + test-lldp + +test_lldp_SOURCES = \ + test-lldp.c \ + ../nm-lldp-listener.c \ + $(top_srcdir)/src/platform/tests/test-common.c + +test_lldp_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -I$(top_srcdir)/src/platform/tests \ + -DSETUP=nm_linux_platform_setup + +test_lldp_LDADD = $(DEVICES_LDADD) + +@VALGRIND_RULES@ +TESTS = \ + test-lldp diff --git a/src/devices/tests/Makefile.in b/src/devices/tests/Makefile.in new file mode 100644 index 00000000..1cfe46b6 --- /dev/null +++ b/src/devices/tests/Makefile.in @@ -0,0 +1,1193 @@ +# Makefile.in generated by automake 1.15 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2014 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +noinst_PROGRAMS = test-lldp$(EXEEXT) +TESTS = test-lldp$(EXEEXT) +subdir = src/devices/tests +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ + $(top_srcdir)/m4/compiler_warnings.m4 \ + $(top_srcdir)/m4/gettext.m4 \ + $(top_srcdir)/m4/gnome-code-coverage.m4 \ + $(top_srcdir)/m4/gtk-doc.m4 $(top_srcdir)/m4/iconv.m4 \ + $(top_srcdir)/m4/intlmacosx.m4 $(top_srcdir)/m4/intltool.m4 \ + $(top_srcdir)/m4/introspection.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +PROGRAMS = $(noinst_PROGRAMS) +am_test_lldp_OBJECTS = test_lldp-test-lldp.$(OBJEXT) \ + test_lldp-nm-lldp-listener.$(OBJEXT) \ + test_lldp-test-common.$(OBJEXT) +test_lldp_OBJECTS = $(am_test_lldp_OBJECTS) +test_lldp_DEPENDENCIES = $(DEVICES_LDADD) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(test_lldp_SOURCES) +DIST_SOURCES = $(test_lldp_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +ETAGS = etags +CTAGS = ctags +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red='[0;31m'; \ + grn='[0;32m'; \ + lgn='[1;32m'; \ + blu='[1;34m'; \ + mgn='[0;35m'; \ + brg='[1m'; \ + std='[m'; \ + fi; \ +} +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/build-aux/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(srcdir)/Makefile.in \ + $(top_srcdir)/build-aux/depcomp \ + $(top_srcdir)/build-aux/test-driver +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AM_TESTS_FD_REDIRECT = @AM_TESTS_FD_REDIRECT@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BLUEZ5_CFLAGS = @BLUEZ5_CFLAGS@ +BLUEZ5_LIBS = @BLUEZ5_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DHCLIENT_PATH = @DHCLIENT_PATH@ +DHCPCD_PATH = @DHCPCD_PATH@ +DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ +DLLTOOL = @DLLTOOL@ +DNSMASQ_PATH = @DNSMASQ_PATH@ +DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GENHTML = @GENHTML@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ +GNUTLS_LIBS = @GNUTLS_LIBS@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +IPTABLES_PATH = @IPTABLES_PATH@ +KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@ +LIBAUDIT_LIBS = @LIBAUDIT_LIBS@ +LIBDL = @LIBDL@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBNDP_CFLAGS = @LIBNDP_CFLAGS@ +LIBNDP_LIBS = @LIBNDP_LIBS@ +LIBNL_CFLAGS = @LIBNL_CFLAGS@ +LIBNL_LIBS = @LIBNL_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ +LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBTEAMDCTL_CFLAGS = @LIBTEAMDCTL_CFLAGS@ +LIBTEAMDCTL_LIBS = @LIBTEAMDCTL_LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LOG_DRIVER = @LOG_DRIVER@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MM_GLIB_CFLAGS = @MM_GLIB_CFLAGS@ +MM_GLIB_LIBS = @MM_GLIB_LIBS@ +MOC = @MOC@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NEWT_CFLAGS = @NEWT_CFLAGS@ +NEWT_LIBS = @NEWT_LIBS@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ +NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ +NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ +NM_MICRO_VERSION = @NM_MICRO_VERSION@ +NM_MINOR_VERSION = @NM_MINOR_VERSION@ +NM_MODIFY_SYSTEM_POLICY = @NM_MODIFY_SYSTEM_POLICY@ +NM_VERSION = @NM_VERSION@ +NSS_CFLAGS = @NSS_CFLAGS@ +NSS_LIBS = @NSS_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PPPD_PATH = @PPPD_PATH@ +PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ +QT_CFLAGS = @QT_CFLAGS@ +QT_LIBS = @QT_LIBS@ +RANLIB = @RANLIB@ +READLINE_LIBS = @READLINE_LIBS@ +SED = @SED@ +SELINUX_CFLAGS = @SELINUX_CFLAGS@ +SELINUX_LIBS = @SELINUX_LIBS@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ +SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ +SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ +SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ +SYSTEMD_JOURNAL_CFLAGS = @SYSTEMD_JOURNAL_CFLAGS@ +SYSTEMD_JOURNAL_LIBS = @SYSTEMD_JOURNAL_LIBS@ +SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ +SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ +SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ +UDEV_DIR = @UDEV_DIR@ +USE_NLS = @USE_NLS@ +UUID_CFLAGS = @UUID_CFLAGS@ +UUID_LIBS = @UUID_LIBS@ +VALGRIND_RULES = @VALGRIND_RULES@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ +VERSION = @VERSION@ +XGETTEXT = @XGETTEXT@ +XGETTEXT_015 = @XGETTEXT_015@ +XGETTEXT_EXTRA_OPTIONS = @XGETTEXT_EXTRA_OPTIONS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +intltool__v_merge_options_ = @intltool__v_merge_options_@ +intltool__v_merge_options_0 = @intltool__v_merge_options_0@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +nmbinary = @nmbinary@ +nmconfdir = @nmconfdir@ +nmdatadir = @nmdatadir@ +nmlibdir = @nmlibdir@ +nmrundir = @nmrundir@ +nmstatedir = @nmstatedir@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +subdirs = @subdirs@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +with_dhclient = @with_dhclient@ +with_dhcpcd = @with_dhcpcd@ +with_netconfig = @with_netconfig@ +with_resolvconf = @with_resolvconf@ +with_valgrind = @with_valgrind@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/shared \ + -I$(top_builddir)/shared \ + -I$(top_srcdir)/libnm-core \ + -I$(top_builddir)/libnm-core \ + -I$(top_srcdir)/src/platform \ + -I$(top_srcdir)/src/devices \ + -I$(top_srcdir)/src/systemd/ \ + -I$(top_srcdir)/src/systemd/src/systemd/ \ + -I$(top_srcdir)/src/systemd/src/libsystemd-network/ \ + -I$(top_srcdir)/src \ + -I$(top_builddir)/src \ + -DG_LOG_DOMAIN=\""NetworkManager"\" \ + -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \ + -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ + $(GLIB_CFLAGS) + +AM_CFLAGS = $(CODE_COVERAGE_CFLAGS) +AM_LDFLAGS = $(GLIB_LIBS) $(CODE_COVERAGE_LDFLAGS) +DEVICES_LDADD = \ + $(top_builddir)/src/libNetworkManager.la + +test_lldp_SOURCES = \ + test-lldp.c \ + ../nm-lldp-listener.c \ + $(top_srcdir)/src/platform/tests/test-common.c + +test_lldp_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -I$(top_srcdir)/src/platform/tests \ + -DSETUP=nm_linux_platform_setup + +test_lldp_LDADD = $(DEVICES_LDADD) +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs +$(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/devices/tests/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/devices/tests/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +test-lldp$(EXEEXT): $(test_lldp_OBJECTS) $(test_lldp_DEPENDENCIES) $(EXTRA_test_lldp_DEPENDENCIES) + @rm -f test-lldp$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(test_lldp_OBJECTS) $(test_lldp_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_lldp-nm-lldp-listener.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_lldp-test-common.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_lldp-test-lldp.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +test_lldp-test-lldp.o: test-lldp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_lldp_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_lldp-test-lldp.o -MD -MP -MF $(DEPDIR)/test_lldp-test-lldp.Tpo -c -o test_lldp-test-lldp.o `test -f 'test-lldp.c' || echo '$(srcdir)/'`test-lldp.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_lldp-test-lldp.Tpo $(DEPDIR)/test_lldp-test-lldp.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-lldp.c' object='test_lldp-test-lldp.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_lldp_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_lldp-test-lldp.o `test -f 'test-lldp.c' || echo '$(srcdir)/'`test-lldp.c + +test_lldp-test-lldp.obj: test-lldp.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_lldp_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_lldp-test-lldp.obj -MD -MP -MF $(DEPDIR)/test_lldp-test-lldp.Tpo -c -o test_lldp-test-lldp.obj `if test -f 'test-lldp.c'; then $(CYGPATH_W) 'test-lldp.c'; else $(CYGPATH_W) '$(srcdir)/test-lldp.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_lldp-test-lldp.Tpo $(DEPDIR)/test_lldp-test-lldp.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test-lldp.c' object='test_lldp-test-lldp.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_lldp_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_lldp-test-lldp.obj `if test -f 'test-lldp.c'; then $(CYGPATH_W) 'test-lldp.c'; else $(CYGPATH_W) '$(srcdir)/test-lldp.c'; fi` + +test_lldp-nm-lldp-listener.o: ../nm-lldp-listener.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_lldp_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_lldp-nm-lldp-listener.o -MD -MP -MF $(DEPDIR)/test_lldp-nm-lldp-listener.Tpo -c -o test_lldp-nm-lldp-listener.o `test -f '../nm-lldp-listener.c' || echo '$(srcdir)/'`../nm-lldp-listener.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_lldp-nm-lldp-listener.Tpo $(DEPDIR)/test_lldp-nm-lldp-listener.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-lldp-listener.c' object='test_lldp-nm-lldp-listener.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_lldp_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_lldp-nm-lldp-listener.o `test -f '../nm-lldp-listener.c' || echo '$(srcdir)/'`../nm-lldp-listener.c + +test_lldp-nm-lldp-listener.obj: ../nm-lldp-listener.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_lldp_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_lldp-nm-lldp-listener.obj -MD -MP -MF $(DEPDIR)/test_lldp-nm-lldp-listener.Tpo -c -o test_lldp-nm-lldp-listener.obj `if test -f '../nm-lldp-listener.c'; then $(CYGPATH_W) '../nm-lldp-listener.c'; else $(CYGPATH_W) '$(srcdir)/../nm-lldp-listener.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_lldp-nm-lldp-listener.Tpo $(DEPDIR)/test_lldp-nm-lldp-listener.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='../nm-lldp-listener.c' object='test_lldp-nm-lldp-listener.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_lldp_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_lldp-nm-lldp-listener.obj `if test -f '../nm-lldp-listener.c'; then $(CYGPATH_W) '../nm-lldp-listener.c'; else $(CYGPATH_W) '$(srcdir)/../nm-lldp-listener.c'; fi` + +test_lldp-test-common.o: $(top_srcdir)/src/platform/tests/test-common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_lldp_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_lldp-test-common.o -MD -MP -MF $(DEPDIR)/test_lldp-test-common.Tpo -c -o test_lldp-test-common.o `test -f '$(top_srcdir)/src/platform/tests/test-common.c' || echo '$(srcdir)/'`$(top_srcdir)/src/platform/tests/test-common.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_lldp-test-common.Tpo $(DEPDIR)/test_lldp-test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/src/platform/tests/test-common.c' object='test_lldp-test-common.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_lldp_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_lldp-test-common.o `test -f '$(top_srcdir)/src/platform/tests/test-common.c' || echo '$(srcdir)/'`$(top_srcdir)/src/platform/tests/test-common.c + +test_lldp-test-common.obj: $(top_srcdir)/src/platform/tests/test-common.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_lldp_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT test_lldp-test-common.obj -MD -MP -MF $(DEPDIR)/test_lldp-test-common.Tpo -c -o test_lldp-test-common.obj `if test -f '$(top_srcdir)/src/platform/tests/test-common.c'; then $(CYGPATH_W) '$(top_srcdir)/src/platform/tests/test-common.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/src/platform/tests/test-common.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/test_lldp-test-common.Tpo $(DEPDIR)/test_lldp-test-common.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(top_srcdir)/src/platform/tests/test-common.c' object='test_lldp-test-common.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(test_lldp_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o test_lldp-test-common.obj `if test -f '$(top_srcdir)/src/platform/tests/test-common.c'; then $(CYGPATH_W) '$(top_srcdir)/src/platform/tests/test-common.c'; else $(CYGPATH_W) '$(srcdir)/$(top_srcdir)/src/platform/tests/test-common.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +test-lldp.log: test-lldp$(EXEEXT) + @p='test-lldp$(EXEEXT)'; \ + b='test-lldp'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(PROGRAMS) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \ + clean-generic clean-libtool clean-noinstPROGRAMS cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + recheck tags tags-am uninstall uninstall-am + +.PRECIOUS: Makefile + + +@GNOME_CODE_COVERAGE_RULES@ + +@VALGRIND_RULES@ + +# 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/devices/tests/test-lldp.c b/src/devices/tests/test-lldp.c new file mode 100644 index 00000000..c339d9ca --- /dev/null +++ b/src/devices/tests/test-lldp.c @@ -0,0 +1,221 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* nm-platform.c - Handle runtime kernel networking configuration + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright (C) 2015 Red Hat, Inc. + */ + +#include "config.h" + +#include <fcntl.h> +#include <linux/if_tun.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include "nm-default.h" +#include "nm-lldp-listener.h" +#include "test-common.h" + +typedef struct { + int ifindex; + int fd; + guint8 mac[ETH_ALEN]; +} test_fixture; + +#define TEST_IFNAME "nm-tap-test0" + +static void +fixture_setup (test_fixture *fixture, gconstpointer user_data) +{ + const NMPlatformLink *link; + struct ifreq ifr = { }; + int fd, s; + + fd = open ("/dev/net/tun", O_RDWR); + g_assert (fd >= 0); + + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + strncpy (ifr.ifr_name, TEST_IFNAME, IFNAMSIZ); + g_assert (ioctl (fd, TUNSETIFF, &ifr) >= 0); + + /* Bring the interface up */ + s = socket (AF_INET, SOCK_DGRAM, 0); + g_assert (s >= 0); + ifr.ifr_flags |= IFF_UP; + g_assert (ioctl (s, SIOCSIFFLAGS, &ifr) >= 0); + close (s); + + nm_platform_process_events (NM_PLATFORM_GET); + link = nm_platform_link_get_by_ifname (NM_PLATFORM_GET, TEST_IFNAME); + g_assert (link); + fixture->ifindex = link->ifindex; + fixture->fd = fd; + memcpy (fixture->mac, link->addr.data, ETH_ALEN); +} + +typedef struct { + int num_called; +} TestInfo; + +static gboolean +loop_quit (gpointer user_data) +{ + g_main_loop_quit ((GMainLoop *) user_data); + return G_SOURCE_REMOVE; +} + +static void +lldp_neighbors_changed (NMLldpListener *lldp_listener, GParamSpec *pspec, + gpointer user_data) +{ + TestInfo *info = user_data; + + info->num_called++; +} + +static GVariant * +get_lldp_neighbor_attribute (GVariant *neighbors, + const char *chassis, const char *port, + const char *name) +{ + GVariantIter iter, attrs_iter; + GVariant *variant, *attr_variant; + const char *attr_name; + GVariant *chassis_v, *port_v, *attr_v; + + g_return_val_if_fail (g_variant_is_of_type (neighbors, + G_VARIANT_TYPE ("aa{sv}")), + NULL); + g_variant_iter_init (&iter, neighbors); + + while (g_variant_iter_next (&iter, "@a{sv}", &variant)) { + g_variant_iter_init (&attrs_iter, variant); + chassis_v = NULL; + port_v = NULL; + attr_v = NULL; + + while (g_variant_iter_next (&attrs_iter, "{&sv}", &attr_name, &attr_variant)) { + if (!g_strcmp0 (attr_name, NM_LLDP_ATTR_CHASSIS_ID)) + chassis_v = attr_variant; + else if (!g_strcmp0 (attr_name, NM_LLDP_ATTR_PORT_ID)) + port_v = attr_variant; + else if (!g_strcmp0 (attr_name, name)) + attr_v = attr_variant; + } + + if ( g_variant_is_of_type (chassis_v, G_VARIANT_TYPE_STRING) + && g_variant_is_of_type (port_v, G_VARIANT_TYPE_STRING) + && !g_strcmp0 (chassis, g_variant_get_string (chassis_v, NULL)) + && !g_strcmp0 (port, g_variant_get_string (port_v, NULL))) { + + g_variant_ref (attr_v); + g_variant_unref (variant); + + return attr_v; + } + g_variant_unref (variant); + } + + /* neighbor not found */ + return NULL; +} + +static void +test_receive_frame (test_fixture *fixture, gconstpointer user_data) +{ + NMLldpListener *listener; + GMainLoop *loop; + TestInfo info = { }; + GVariant *neighbors, *attr; + uint8_t frame[] = { + /* Ethernet header */ + 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03, /* Destination MAC */ + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, /* Source MAC */ + 0x88, 0xcc, /* Ethertype */ + /* LLDP mandatory TLVs */ + 0x02, 0x07, 0x04, 0x00, 0x01, 0x02, /* Chassis: MAC, 00:01:02:03:04:05 */ + 0x03, 0x04, 0x05, + 0x04, 0x04, 0x05, 0x31, 0x2f, 0x33, /* Port: interface name, "1/3" */ + 0x06, 0x02, 0x00, 0x78, /* TTL: 120 seconds */ + /* LLDP optional TLVs */ + 0x08, 0x04, 0x50, 0x6f, 0x72, 0x74, /* Port Description: "Port" */ + 0x0a, 0x03, 0x53, 0x59, 0x53, /* System Name: "SYS" */ + 0x0c, 0x04, 0x66, 0x6f, 0x6f, 0x00, /* System Description: "foo" (NULL-terminated) */ + 0x00, 0x00 /* End Of LLDPDU */ + }; + + listener = nm_lldp_listener_new (); + g_assert (listener != NULL); + g_assert (nm_lldp_listener_start (listener, fixture->ifindex, TEST_IFNAME, fixture->mac, ETH_ALEN, NULL)); + + g_signal_connect (listener, "notify::" NM_LLDP_LISTENER_NEIGHBORS, + (GCallback) lldp_neighbors_changed, &info); + loop = g_main_loop_new (NULL, FALSE); + g_timeout_add_seconds (1, loop_quit, loop); + + g_assert (write (fixture->fd, frame, sizeof (frame)) == sizeof (frame)); + g_assert (write (fixture->fd, frame, sizeof (frame)) == sizeof (frame)); + + g_main_loop_run (loop); + + g_assert_cmpint (info.num_called, ==, 1); + neighbors = nm_lldp_listener_get_neighbors (listener); + g_assert (neighbors != NULL); + + /* Check port description */ + attr = get_lldp_neighbor_attribute (neighbors, "00:01:02:03:04:05", "1/3", + NM_LLDP_ATTR_PORT_DESCRIPTION); + g_assert (attr != NULL); + g_assert (g_variant_is_of_type (attr, G_VARIANT_TYPE_STRING)); + g_assert_cmpstr (g_variant_get_string (attr, NULL), ==, "Port"); + + /* Check system name */ + attr = get_lldp_neighbor_attribute (neighbors, "00:01:02:03:04:05", "1/3", + NM_LLDP_ATTR_SYSTEM_NAME); + g_assert (attr != NULL); + g_assert (g_variant_is_of_type (attr, G_VARIANT_TYPE_STRING)); + g_assert_cmpstr (g_variant_get_string (attr, NULL), ==, "SYS"); + + /* Check destination */ + attr = get_lldp_neighbor_attribute (neighbors, "00:01:02:03:04:05", "1/3", + NM_LLDP_ATTR_DESTINATION); + g_assert (attr != NULL); + g_assert (g_variant_is_of_type (attr, G_VARIANT_TYPE_STRING)); + g_assert_cmpstr (g_variant_get_string (attr, NULL), ==, + NM_LLDP_DEST_NEAREST_NON_TPMR_BRIDGE); + + g_clear_pointer (&loop, g_main_loop_unref); +} + +static void +fixture_teardown (test_fixture *fixture, gconstpointer user_data) +{ + nm_platform_link_delete (NM_PLATFORM_GET, fixture->ifindex); +} + +void +init_tests (int *argc, char ***argv) +{ + nmtst_init_assert_logging (argc, argv, "WARN", "ALL"); +} + +void +setup_tests (void) +{ + g_test_add ("/lldp/receive_frame", test_fixture, NULL, fixture_setup, + test_receive_frame, fixture_teardown); +} diff --git a/src/devices/wifi/Makefile.am b/src/devices/wifi/Makefile.am index 4ac59e3d..b0919ef7 100644 --- a/src/devices/wifi/Makefile.am +++ b/src/devices/wifi/Makefile.am @@ -2,7 +2,9 @@ include $(GLIB_MAKEFILE) @GNOME_CODE_COVERAGE_RULES@ +if ENABLE_TESTS SUBDIRS=. tests +endif AM_CPPFLAGS = \ -I${top_srcdir}/src \ @@ -11,31 +13,15 @@ AM_CPPFLAGS = \ -I${top_srcdir}/src/settings \ -I${top_srcdir}/src/platform \ -I${top_srcdir}/src/supplicant-manager \ - -I${top_srcdir}/include \ - -I$(top_builddir)/include \ + -I${top_builddir}/introspection \ + -I${top_srcdir}/shared \ + -I$(top_builddir)/shared \ -I${top_builddir}/libnm-core \ -I${top_srcdir}/libnm-core \ -DG_LOG_DOMAIN=\""NetworkManager-wifi"\" \ - -DNETWORKMANAGER_COMPILATION \ + -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ - $(DBUS_CFLAGS) - -GLIB_GENERATED = nm-wifi-enum-types.h nm-wifi-enum-types.c -GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM -GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM -nm_wifi_enum_types_sources = \ - $(srcdir)/nm-device-wifi.h \ - $(srcdir)/nm-wifi-ap.h \ - $(srcdir)/nm-device-olpc-mesh.h - -glue_sources = \ - nm-device-wifi-glue.h \ - nm-device-olpc-mesh-glue.h - -%-glue.h: $(top_srcdir)/introspection/%.xml - $(AM_V_GEN) dbus-binding-tool --prefix=$(subst -,_,$(subst -glue.h,,$@)) --mode=glib-server --output=$@ $< - -BUILT_SOURCES = $(GLIB_GENERATED) $(glue_sources) + $(GLIB_CFLAGS) pkglib_LTLIBRARIES = libnm-device-plugin-wifi.la @@ -48,9 +34,7 @@ libnm_device_plugin_wifi_la_SOURCES = \ nm-wifi-ap-utils.c \ nm-wifi-ap-utils.h \ nm-device-olpc-mesh.c \ - nm-device-olpc-mesh.h \ - \ - $(BUILT_SOURCES) + nm-device-olpc-mesh.h SYMBOL_VIS_FILE=$(srcdir)/exports.ver @@ -59,11 +43,10 @@ libnm_device_plugin_wifi_la_LDFLAGS = \ -Wl,--version-script=$(SYMBOL_VIS_FILE) libnm_device_plugin_wifi_la_LIBADD = \ - $(DBUS_LIBS) \ + $(top_builddir)/introspection/libnmdbus.la \ + $(GLIB_LIBS) \ $(GUDEV_LIBS) -CLEANFILES = $(BUILT_SOURCES) - EXTRA_DIST = $(SYMBOL_VIS_FILE) if ENABLE_TESTS diff --git a/src/devices/wifi/Makefile.in b/src/devices/wifi/Makefile.in index 82ebad74..1286a480 100644 --- a/src/devices/wifi/Makefile.in +++ b/src/devices/wifi/Makefile.in @@ -140,14 +140,12 @@ am__uninstall_files_from_dir = { \ am__installdirs = "$(DESTDIR)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) am__DEPENDENCIES_1 = -libnm_device_plugin_wifi_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) -am__objects_1 = nm-wifi-enum-types.lo -am__objects_2 = -am__objects_3 = $(am__objects_1) $(am__objects_2) +libnm_device_plugin_wifi_la_DEPENDENCIES = \ + $(top_builddir)/introspection/libnmdbus.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libnm_device_plugin_wifi_la_OBJECTS = nm-wifi-factory.lo \ nm-device-wifi.lo nm-wifi-ap.lo nm-wifi-ap-utils.lo \ - nm-device-olpc-mesh.lo $(am__objects_3) + nm-device-olpc-mesh.lo libnm_device_plugin_wifi_la_OBJECTS = \ $(am_libnm_device_plugin_wifi_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) @@ -234,7 +232,7 @@ am__define_uniq_tagged_files = \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags -DIST_SUBDIRS = $(SUBDIRS) +DIST_SUBDIRS = . tests am__DIST_COMMON = $(srcdir)/Makefile.in \ $(top_srcdir)/build-aux/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -278,7 +276,6 @@ BLUEZ5_LIBS = @BLUEZ5_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ -CKDB_PATH = @CKDB_PATH@ CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ @@ -290,8 +287,6 @@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DBUS_CFLAGS = @DBUS_CFLAGS@ -DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@ -DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@ DBUS_LIBS = @DBUS_LIBS@ DBUS_SYS_DIR = @DBUS_SYS_DIR@ DEFS = @DEFS@ @@ -301,6 +296,7 @@ DHCPCD_PATH = @DHCPCD_PATH@ DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ DLLTOOL = @DLLTOOL@ DNSMASQ_PATH = @DNSMASQ_PATH@ +DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ @@ -355,16 +351,13 @@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ IPTABLES_PATH = @IPTABLES_PATH@ -IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ -IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ +LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@ +LIBAUDIT_LIBS = @LIBAUDIT_LIBS@ LIBDL = @LIBDL@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ @@ -401,6 +394,8 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ +NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ NM_MICRO_VERSION = @NM_MICRO_VERSION@ NM_MINOR_VERSION = @NM_MINOR_VERSION@ @@ -429,7 +424,6 @@ POLKIT_LIBS = @POLKIT_LIBS@ POSUB = @POSUB@ PPPD_PATH = @PPPD_PATH@ PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ -PPPOE_PATH = @PPPOE_PATH@ QT_CFLAGS = @QT_CFLAGS@ QT_LIBS = @QT_LIBS@ RANLIB = @RANLIB@ @@ -444,6 +438,8 @@ SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ +SYSTEMD_JOURNAL_CFLAGS = @SYSTEMD_JOURNAL_CFLAGS@ +SYSTEMD_JOURNAL_LIBS = @SYSTEMD_JOURNAL_LIBS@ SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ @@ -504,6 +500,7 @@ mkdir_p = @mkdir_p@ nmbinary = @nmbinary@ nmconfdir = @nmconfdir@ nmdatadir = @nmdatadir@ +nmlibdir = @nmlibdir@ nmrundir = @nmrundir@ nmstatedir = @nmstatedir@ oldincludedir = @oldincludedir@ @@ -511,6 +508,7 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -526,7 +524,7 @@ with_dhcpcd = @with_dhcpcd@ with_netconfig = @with_netconfig@ with_resolvconf = @with_resolvconf@ with_valgrind = @with_valgrind@ -SUBDIRS = . tests +@ENABLE_TESTS_TRUE@SUBDIRS = . tests AM_CPPFLAGS = \ -I${top_srcdir}/src \ -I${top_builddir}/src \ @@ -534,28 +532,16 @@ AM_CPPFLAGS = \ -I${top_srcdir}/src/settings \ -I${top_srcdir}/src/platform \ -I${top_srcdir}/src/supplicant-manager \ - -I${top_srcdir}/include \ - -I$(top_builddir)/include \ + -I${top_builddir}/introspection \ + -I${top_srcdir}/shared \ + -I$(top_builddir)/shared \ -I${top_builddir}/libnm-core \ -I${top_srcdir}/libnm-core \ -DG_LOG_DOMAIN=\""NetworkManager-wifi"\" \ - -DNETWORKMANAGER_COMPILATION \ + -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ - $(DBUS_CFLAGS) + $(GLIB_CFLAGS) -GLIB_GENERATED = nm-wifi-enum-types.h nm-wifi-enum-types.c -GLIB_MKENUMS_H_FLAGS = --identifier-prefix NM -GLIB_MKENUMS_C_FLAGS = --identifier-prefix NM -nm_wifi_enum_types_sources = \ - $(srcdir)/nm-device-wifi.h \ - $(srcdir)/nm-wifi-ap.h \ - $(srcdir)/nm-device-olpc-mesh.h - -glue_sources = \ - nm-device-wifi-glue.h \ - nm-device-olpc-mesh-glue.h - -BUILT_SOURCES = $(GLIB_GENERATED) $(glue_sources) pkglib_LTLIBRARIES = libnm-device-plugin-wifi.la libnm_device_plugin_wifi_la_SOURCES = \ nm-wifi-factory.c \ @@ -566,9 +552,7 @@ libnm_device_plugin_wifi_la_SOURCES = \ nm-wifi-ap-utils.c \ nm-wifi-ap-utils.h \ nm-device-olpc-mesh.c \ - nm-device-olpc-mesh.h \ - \ - $(BUILT_SOURCES) + nm-device-olpc-mesh.h SYMBOL_VIS_FILE = $(srcdir)/exports.ver libnm_device_plugin_wifi_la_LDFLAGS = \ @@ -576,13 +560,12 @@ libnm_device_plugin_wifi_la_LDFLAGS = \ -Wl,--version-script=$(SYMBOL_VIS_FILE) libnm_device_plugin_wifi_la_LIBADD = \ - $(DBUS_LIBS) \ + $(top_builddir)/introspection/libnmdbus.la \ + $(GLIB_LIBS) \ $(GUDEV_LIBS) -CLEANFILES = $(BUILT_SOURCES) EXTRA_DIST = $(SYMBOL_VIS_FILE) -all: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) all-recursive +all: all-recursive .SUFFIXES: .SUFFIXES: .c .lo .o .obj @@ -664,7 +647,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-device-wifi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-wifi-ap-utils.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-wifi-ap.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-wifi-enum-types.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nm-wifi-factory.Plo@am__quote@ .c.o: @@ -851,16 +833,14 @@ distdir: $(DISTFILES) @ENABLE_TESTS_FALSE@check-local: check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-local -check: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) check-recursive +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: $(BUILT_SOURCES) - $(MAKE) $(AM_MAKEFLAGS) install-recursive +install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive @@ -882,7 +862,6 @@ install-strip: mostlyclean-generic: clean-generic: - -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) @@ -891,7 +870,6 @@ distclean-generic: maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." - -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-recursive clean-am: clean-generic clean-libtool clean-pkglibLTLIBRARIES \ @@ -963,8 +941,7 @@ ps-am: uninstall-am: uninstall-pkglibLTLIBRARIES -.MAKE: $(am__recursive_targets) all check check-am install install-am \ - install-strip +.MAKE: $(am__recursive_targets) check-am install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am check-local clean clean-generic clean-libtool \ @@ -988,9 +965,6 @@ include $(GLIB_MAKEFILE) @GNOME_CODE_COVERAGE_RULES@ -%-glue.h: $(top_srcdir)/introspection/%.xml - $(AM_V_GEN) dbus-binding-tool --prefix=$(subst -,_,$(subst -glue.h,,$@)) --mode=glib-server --output=$@ $< - @ENABLE_TESTS_TRUE@check-local: @ENABLE_TESTS_TRUE@ $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-wifi.so $(SYMBOL_VIS_FILE) diff --git a/src/devices/wifi/nm-device-olpc-mesh-glue.h b/src/devices/wifi/nm-device-olpc-mesh-glue.h deleted file mode 100644 index 04b5e83f..00000000 --- a/src/devices/wifi/nm-device-olpc-mesh-glue.h +++ /dev/null @@ -1,73 +0,0 @@ -/* Generated by dbus-binding-tool; do not edit! */ - - -#ifndef __dbus_glib_marshal_nm_device_olpc_mesh_MARSHAL_H__ -#define __dbus_glib_marshal_nm_device_olpc_mesh_MARSHAL_H__ - -#include <glib-object.h> - -G_BEGIN_DECLS - -#ifdef G_ENABLE_DEBUG -#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) -#define g_marshal_value_peek_char(v) g_value_get_schar (v) -#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) -#define g_marshal_value_peek_int(v) g_value_get_int (v) -#define g_marshal_value_peek_uint(v) g_value_get_uint (v) -#define g_marshal_value_peek_long(v) g_value_get_long (v) -#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) -#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) -#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) -#define g_marshal_value_peek_enum(v) g_value_get_enum (v) -#define g_marshal_value_peek_flags(v) g_value_get_flags (v) -#define g_marshal_value_peek_float(v) g_value_get_float (v) -#define g_marshal_value_peek_double(v) g_value_get_double (v) -#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) -#define g_marshal_value_peek_param(v) g_value_get_param (v) -#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) -#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) -#define g_marshal_value_peek_object(v) g_value_get_object (v) -#define g_marshal_value_peek_variant(v) g_value_get_variant (v) -#else /* !G_ENABLE_DEBUG */ -/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. - * Do not access GValues directly in your code. Instead, use the - * g_value_get_*() functions - */ -#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int -#define g_marshal_value_peek_char(v) (v)->data[0].v_int -#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint -#define g_marshal_value_peek_int(v) (v)->data[0].v_int -#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint -#define g_marshal_value_peek_long(v) (v)->data[0].v_long -#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong -#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 -#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 -#define g_marshal_value_peek_enum(v) (v)->data[0].v_long -#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong -#define g_marshal_value_peek_float(v) (v)->data[0].v_float -#define g_marshal_value_peek_double(v) (v)->data[0].v_double -#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer -#endif /* !G_ENABLE_DEBUG */ - - -G_END_DECLS - -#endif /* __dbus_glib_marshal_nm_device_olpc_mesh_MARSHAL_H__ */ - -#include <dbus/dbus-glib.h> -static const DBusGMethodInfo dbus_glib_nm_device_olpc_mesh_methods[] = { -}; - -const DBusGObjectInfo dbus_glib_nm_device_olpc_mesh_object_info = { 1, - dbus_glib_nm_device_olpc_mesh_methods, - 0, -"\0", -"org.freedesktop.NetworkManager.Device.OlpcMesh\0PropertiesChanged\0\0", -"org.freedesktop.NetworkManager.Device.OlpcMesh\0HwAddress\0hw_address\0read\0org.freedesktop.NetworkManager.Device.OlpcMesh\0Companion\0companion\0read\0org.freedesktop.NetworkManager.Device.OlpcMesh\0ActiveChannel\0active_channel\0read\0\0" -}; - diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c index e67d1a20..23ebd9c8 100644 --- a/src/devices/wifi/nm-device-olpc-mesh.c +++ b/src/devices/wifi/nm-device-olpc-mesh.c @@ -26,9 +26,6 @@ #include "config.h" -#include <glib.h> -#include <glib/gi18n.h> -#include <dbus/dbus.h> #include <netinet/in.h> #include <string.h> #include <sys/stat.h> @@ -38,27 +35,24 @@ #include <sys/ioctl.h> #include <errno.h> +#include "nm-default.h" #include "nm-device.h" #include "nm-device-wifi.h" #include "nm-device-olpc-mesh.h" #include "nm-device-private.h" #include "nm-utils.h" -#include "nm-logging.h" #include "NetworkManagerUtils.h" #include "nm-activation-request.h" #include "nm-setting-connection.h" #include "nm-setting-olpc-mesh.h" #include "nm-manager.h" #include "nm-enum-types.h" -#include "nm-dbus-manager.h" #include "nm-platform.h" -#include "nm-wifi-enum-types.h" /* This is a bug; but we can't really change API now... */ #include "nm-vpn-dbus-interface.h" - -#include "nm-device-olpc-mesh-glue.h" +#include "nmdbus-device-olpc-mesh.h" #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceOlpcMesh); @@ -77,6 +71,7 @@ enum { struct _NMDeviceOlpcMeshPrivate { NMDevice *companion; + NMManager *manager; gboolean stage1_waiting; }; @@ -213,7 +208,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) GBytes *ssid; const char *anycast_addr; - connection = nm_device_get_connection (device); + connection = nm_device_get_applied_connection (device); g_assert (connection); s_mesh = nm_connection_get_setting_olpc_mesh (connection); @@ -345,7 +340,7 @@ check_companion (NMDeviceOlpcMesh *self, NMDevice *other) _LOGI (LOGD_OLPC, "found companion WiFi device %s", nm_device_get_iface (other)); - g_signal_connect (G_OBJECT (other), "state-changed", + g_signal_connect (G_OBJECT (other), NM_DEVICE_STATE_CHANGED, G_CALLBACK (companion_state_changed_cb), self); g_signal_connect (G_OBJECT (other), "notify::scanning", @@ -397,7 +392,7 @@ find_companion (NMDeviceOlpcMesh *self) nm_device_add_pending_action (NM_DEVICE (self), "waiting for companion", TRUE); /* Try to find the companion if it's already known to the NMManager */ - for (list = nm_manager_get_devices (nm_manager_get ()); list ; list = g_slist_next (list)) { + for (list = nm_manager_get_devices (priv->manager); list ; list = g_slist_next (list)) { if (check_companion (self, NM_DEVICE (list->data))) { nm_device_queue_recheck_available (NM_DEVICE (self), NM_DEVICE_STATE_REASON_NONE, @@ -421,14 +416,13 @@ state_changed (NMDevice *device, /*******************************************************************/ NMDevice * -nm_device_olpc_mesh_new (NMPlatformLink *platform_device) +nm_device_olpc_mesh_new (const char *iface) { - g_return_val_if_fail (platform_device != NULL, NULL); - return (NMDevice *) g_object_new (NM_TYPE_DEVICE_OLPC_MESH, - NM_DEVICE_PLATFORM_DEVICE, platform_device, + NM_DEVICE_IFACE, iface, NM_DEVICE_TYPE_DESC, "802.11 OLPC Mesh", NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_OLPC_MESH, + NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_OLPC_MESH, NULL); } @@ -437,35 +431,21 @@ nm_device_olpc_mesh_init (NMDeviceOlpcMesh * self) { } -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) +static void +constructed (GObject *object) { - GObject *object; - GObjectClass *klass; - NMDeviceOlpcMesh *self; - NMDeviceWifiCapabilities caps; - - klass = G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class); - object = klass->constructor (type, n_construct_params, construct_params); - if (!object) - return NULL; - - self = NM_DEVICE_OLPC_MESH (object); - - if (!nm_platform_wifi_get_capabilities (NM_PLATFORM_GET, nm_device_get_ifindex (NM_DEVICE (self)), &caps)) { - _LOGW (LOGD_HW | LOGD_OLPC, "failed to initialize WiFi driver"); - g_object_unref (object); - return NULL; - } + NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (object); + NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); - g_signal_connect (nm_manager_get (), "device-added", G_CALLBACK (device_added_cb), self); - g_signal_connect (nm_manager_get (), "device-removed", G_CALLBACK (device_removed_cb), self); + G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->constructed (object); + + priv->manager = g_object_ref (nm_manager_get ()); + + g_signal_connect (priv->manager, "device-added", G_CALLBACK (device_added_cb), self); + g_signal_connect (priv->manager, "device-removed", G_CALLBACK (device_removed_cb), self); /* shorter timeout for mesh connectivity */ nm_device_set_dhcp_timeout (NM_DEVICE (self), 20); - return object; } static void @@ -477,10 +457,7 @@ get_property (GObject *object, guint prop_id, switch (prop_id) { case PROP_COMPANION: - if (priv->companion) - g_value_set_boxed (value, nm_device_get_path (priv->companion)); - else - g_value_set_boxed (value, "/"); + nm_utils_g_value_set_object_path (value, priv->companion); break; case PROP_ACTIVE_CHANNEL: g_value_set_uint (value, nm_platform_mesh_get_channel (NM_PLATFORM_GET, nm_device_get_ifindex (NM_DEVICE (device)))); @@ -506,10 +483,15 @@ static void dispose (GObject *object) { NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (object); + NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self); companion_cleanup (self); - g_signal_handlers_disconnect_by_func (nm_manager_get (), G_CALLBACK (device_added_cb), self); - g_signal_handlers_disconnect_by_func (nm_manager_get (), G_CALLBACK (device_removed_cb), self); + + if (priv->manager) { + g_signal_handlers_disconnect_by_func (priv->manager, G_CALLBACK (device_added_cb), self); + g_signal_handlers_disconnect_by_func (priv->manager, G_CALLBACK (device_removed_cb), self); + g_clear_object (&priv->manager); + } G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->dispose (object); } @@ -522,7 +504,9 @@ nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass) g_type_class_add_private (object_class, sizeof (NMDeviceOlpcMeshPrivate)); - object_class->constructor = constructor; + NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_OLPC_MESH_SETTING_NAME, NM_LINK_TYPE_OLPC_MESH) + + object_class->constructed = constructed; object_class->get_property = get_property; object_class->set_property = set_property; object_class->dispose = dispose; @@ -540,10 +524,10 @@ nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass) /* Properties */ g_object_class_install_property (object_class, PROP_COMPANION, - g_param_spec_boxed (NM_DEVICE_OLPC_MESH_COMPANION, "", "", - DBUS_TYPE_G_OBJECT_PATH, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + g_param_spec_string (NM_DEVICE_OLPC_MESH_COMPANION, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_ACTIVE_CHANNEL, @@ -552,8 +536,8 @@ nm_device_olpc_mesh_class_init (NMDeviceOlpcMeshClass *klass) G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), - G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_olpc_mesh_object_info); + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_OLPC_MESH_SKELETON, + NULL); } diff --git a/src/devices/wifi/nm-device-olpc-mesh.h b/src/devices/wifi/nm-device-olpc-mesh.h index 67d83fb0..63895a88 100644 --- a/src/devices/wifi/nm-device-olpc-mesh.h +++ b/src/devices/wifi/nm-device-olpc-mesh.h @@ -28,8 +28,6 @@ #ifndef __NETWORKMANAGER_DEVICE_OLPC_MESH_H__ #define __NETWORKMANAGER_DEVICE_OLPC_MESH_H__ -#include <glib-object.h> - #include "nm-device.h" G_BEGIN_DECLS @@ -67,7 +65,7 @@ struct _NMDeviceOlpcMeshClass GType nm_device_olpc_mesh_get_type (void); -NMDevice *nm_device_olpc_mesh_new (NMPlatformLink *platform_device); +NMDevice *nm_device_olpc_mesh_new (const char *iface); G_END_DECLS diff --git a/src/devices/wifi/nm-device-wifi-glue.h b/src/devices/wifi/nm-device-wifi-glue.h deleted file mode 100644 index 8f8da2af..00000000 --- a/src/devices/wifi/nm-device-wifi-glue.h +++ /dev/null @@ -1,167 +0,0 @@ -/* Generated by dbus-binding-tool; do not edit! */ - - -#ifndef __dbus_glib_marshal_nm_device_wifi_MARSHAL_H__ -#define __dbus_glib_marshal_nm_device_wifi_MARSHAL_H__ - -#include <glib-object.h> - -G_BEGIN_DECLS - -#ifdef G_ENABLE_DEBUG -#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) -#define g_marshal_value_peek_char(v) g_value_get_schar (v) -#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) -#define g_marshal_value_peek_int(v) g_value_get_int (v) -#define g_marshal_value_peek_uint(v) g_value_get_uint (v) -#define g_marshal_value_peek_long(v) g_value_get_long (v) -#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) -#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) -#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) -#define g_marshal_value_peek_enum(v) g_value_get_enum (v) -#define g_marshal_value_peek_flags(v) g_value_get_flags (v) -#define g_marshal_value_peek_float(v) g_value_get_float (v) -#define g_marshal_value_peek_double(v) g_value_get_double (v) -#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) -#define g_marshal_value_peek_param(v) g_value_get_param (v) -#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) -#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) -#define g_marshal_value_peek_object(v) g_value_get_object (v) -#define g_marshal_value_peek_variant(v) g_value_get_variant (v) -#else /* !G_ENABLE_DEBUG */ -/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. - * Do not access GValues directly in your code. Instead, use the - * g_value_get_*() functions - */ -#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int -#define g_marshal_value_peek_char(v) (v)->data[0].v_int -#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint -#define g_marshal_value_peek_int(v) (v)->data[0].v_int -#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint -#define g_marshal_value_peek_long(v) (v)->data[0].v_long -#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong -#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 -#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 -#define g_marshal_value_peek_enum(v) (v)->data[0].v_long -#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong -#define g_marshal_value_peek_float(v) (v)->data[0].v_float -#define g_marshal_value_peek_double(v) (v)->data[0].v_double -#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer -#endif /* !G_ENABLE_DEBUG */ - - -/* BOOLEAN:POINTER,POINTER */ -extern void dbus_glib_marshal_nm_device_wifi_BOOLEAN__POINTER_POINTER (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); -void -dbus_glib_marshal_nm_device_wifi_BOOLEAN__POINTER_POINTER (GClosure *closure, - GValue *return_value G_GNUC_UNUSED, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint G_GNUC_UNUSED, - gpointer marshal_data) -{ - typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER_POINTER) (gpointer data1, - gpointer arg_1, - gpointer arg_2, - gpointer data2); - GMarshalFunc_BOOLEAN__POINTER_POINTER callback; - GCClosure *cc = (GCClosure*) closure; - gpointer data1, data2; - gboolean v_return; - - g_return_if_fail (return_value != NULL); - g_return_if_fail (n_param_values == 3); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_BOOLEAN__POINTER_POINTER) (marshal_data ? marshal_data : cc->callback); - - v_return = callback (data1, - g_marshal_value_peek_pointer (param_values + 1), - g_marshal_value_peek_pointer (param_values + 2), - data2); - - g_value_set_boolean (return_value, v_return); -} - -/* NONE:BOXED,POINTER */ -extern void dbus_glib_marshal_nm_device_wifi_VOID__BOXED_POINTER (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); -void -dbus_glib_marshal_nm_device_wifi_VOID__BOXED_POINTER (GClosure *closure, - GValue *return_value G_GNUC_UNUSED, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint G_GNUC_UNUSED, - gpointer marshal_data) -{ - typedef void (*GMarshalFunc_VOID__BOXED_POINTER) (gpointer data1, - gpointer arg_1, - gpointer arg_2, - gpointer data2); - GMarshalFunc_VOID__BOXED_POINTER callback; - GCClosure *cc = (GCClosure*) closure; - gpointer data1, data2; - - g_return_if_fail (n_param_values == 3); - - if (G_CCLOSURE_SWAP_DATA (closure)) - { - data1 = closure->data; - data2 = g_value_peek_pointer (param_values + 0); - } - else - { - data1 = g_value_peek_pointer (param_values + 0); - data2 = closure->data; - } - callback = (GMarshalFunc_VOID__BOXED_POINTER) (marshal_data ? marshal_data : cc->callback); - - callback (data1, - g_marshal_value_peek_boxed (param_values + 1), - g_marshal_value_peek_pointer (param_values + 2), - data2); -} -#define dbus_glib_marshal_nm_device_wifi_NONE__BOXED_POINTER dbus_glib_marshal_nm_device_wifi_VOID__BOXED_POINTER - -G_END_DECLS - -#endif /* __dbus_glib_marshal_nm_device_wifi_MARSHAL_H__ */ - -#include <dbus/dbus-glib.h> -static const DBusGMethodInfo dbus_glib_nm_device_wifi_methods[] = { - { (GCallback) impl_device_get_access_points, dbus_glib_marshal_nm_device_wifi_BOOLEAN__POINTER_POINTER, 0 }, - { (GCallback) impl_device_get_all_access_points, dbus_glib_marshal_nm_device_wifi_BOOLEAN__POINTER_POINTER, 89 }, - { (GCallback) impl_device_request_scan, dbus_glib_marshal_nm_device_wifi_NONE__BOXED_POINTER, 181 }, -}; - -const DBusGObjectInfo dbus_glib_nm_device_wifi_object_info = { 1, - dbus_glib_nm_device_wifi_methods, - 3, -"org.freedesktop.NetworkManager.Device.Wireless\0GetAccessPoints\0S\0access_points\0O\0F\0N\0ao\0\0org.freedesktop.NetworkManager.Device.Wireless\0GetAllAccessPoints\0S\0access_points\0O\0F\0N\0ao\0\0org.freedesktop.NetworkManager.Device.Wireless\0RequestScan\0A\0options\0I\0a{sv}\0\0\0", -"org.freedesktop.NetworkManager.Device.Wireless\0PropertiesChanged\0org.freedesktop.NetworkManager.Device.Wireless\0AccessPointAdded\0org.freedesktop.NetworkManager.Device.Wireless\0AccessPointRemoved\0\0", -"org.freedesktop.NetworkManager.Device.Wireless\0HwAddress\0hw_address\0read\0org.freedesktop.NetworkManager.Device.Wireless\0PermHwAddress\0perm_hw_address\0read\0org.freedesktop.NetworkManager.Device.Wireless\0Mode\0mode\0read\0org.freedesktop.NetworkManager.Device.Wireless\0Bitrate\0bitrate\0read\0org.freedesktop.NetworkManager.Device.Wireless\0AccessPoints\0access_points\0read\0org.freedesktop.NetworkManager.Device.Wireless\0ActiveAccessPoint\0active_access_point\0read\0org.freedesktop.NetworkManager.Device.Wireless\0WirelessCapabilities\0wireless_capabilities\0read\0\0" -}; - diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c index 1bf64bcc..64da03e1 100644 --- a/src/devices/wifi/nm-device-wifi.c +++ b/src/devices/wifi/nm-device-wifi.c @@ -21,21 +21,16 @@ #include "config.h" -#include <glib.h> -#include <glib/gi18n.h> -#include <dbus/dbus.h> #include <netinet/in.h> #include <string.h> #include <unistd.h> #include <errno.h> -#include "nm-glib-compat.h" -#include "nm-dbus-manager.h" +#include "nm-default.h" #include "nm-device.h" #include "nm-device-wifi.h" #include "nm-device-private.h" #include "nm-utils.h" -#include "nm-logging.h" #include "NetworkManagerUtils.h" #include "nm-activation-request.h" #include "nm-supplicant-manager.h" @@ -52,25 +47,11 @@ #include "nm-auth-utils.h" #include "nm-settings-connection.h" #include "nm-enum-types.h" -#include "nm-dbus-glib-types.h" -#include "nm-wifi-enum-types.h" #include "nm-connection-provider.h" -#include "gsystem-local-alloc.h" +#include "nm-core-internal.h" +#include "nm-config.h" - -static gboolean impl_device_get_access_points (NMDeviceWifi *device, - GPtrArray **aps, - GError **err); - -static gboolean impl_device_get_all_access_points (NMDeviceWifi *device, - GPtrArray **aps, - GError **err); - -static void impl_device_request_scan (NMDeviceWifi *device, - GHashTable *options, - DBusGMethodInvocation *context); - -#include "nm-device-wifi-glue.h" +#include "nmdbus-device-wifi.h" #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceWifi); @@ -111,29 +92,27 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; struct _NMDeviceWifiPrivate { - gboolean disposed; - gint8 invalid_strength_counter; - GSList * ap_list; + GHashTable * aps; NMAccessPoint * current_ap; guint32 rate; gboolean enabled; /* rfkilled or not */ + gint32 last_scan; gint32 scheduled_scan_time; guint8 scan_interval; /* seconds */ guint pending_scan_id; - guint scanlist_cull_id; - gboolean requested_scan; + guint ap_dump_id; + bool requested_scan; NMSupplicantManager *sup_mgr; NMSupplicantInterface *sup_iface; guint sup_timeout_id; /* supplicant association timeout */ - gboolean ssid_found; + bool ssid_found; NM80211Mode mode; - guint32 failed_link_count; guint periodic_source_id; guint link_timeout_id; guint32 failed_iface_count; @@ -164,7 +143,7 @@ static void supplicant_iface_new_bss_cb (NMSupplicantInterface * iface, static void supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface, const char *object_path, - GHashTable *properties, + GVariant *properties, NMDeviceWifi *self); static void supplicant_iface_bss_removed_cb (NMSupplicantInterface *iface, @@ -179,49 +158,34 @@ static void supplicant_iface_notify_scanning_cb (NMSupplicantInterface * iface, GParamSpec * pspec, NMDeviceWifi * self); -static void schedule_scanlist_cull (NMDeviceWifi *self); +static void supplicant_iface_notify_current_bss (NMSupplicantInterface *iface, + GParamSpec *pspec, + NMDeviceWifi *self); -static void request_wireless_scan (NMDeviceWifi *self, GHashTable *scan_options); +static void request_wireless_scan (NMDeviceWifi *self, GVariant *scan_options); -static void remove_access_point (NMDeviceWifi *device, NMAccessPoint *ap); +static void ap_add_remove (NMDeviceWifi *self, + guint signum, + NMAccessPoint *ap, + gboolean recheck_available_connections); static void remove_supplicant_interface_error_handler (NMDeviceWifi *self); /*****************************************************************/ -static GObject* -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) +static void +constructed (GObject *object) { - GObject *object; - GObjectClass *klass; - NMDeviceWifi *self; - NMDeviceWifiPrivate *priv; + NMDeviceWifi *self = NM_DEVICE_WIFI (object); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - klass = G_OBJECT_CLASS (nm_device_wifi_parent_class); - object = klass->constructor (type, n_construct_params, construct_params); - if (!object) - return NULL; - - self = NM_DEVICE_WIFI (object); - priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - if (!nm_platform_wifi_get_capabilities (NM_PLATFORM_GET, - nm_device_get_ifindex (NM_DEVICE (self)), - &priv->capabilities)) { - _LOGW (LOGD_HW | LOGD_WIFI, "failed to initialize WiFi driver"); - g_object_unref (object); - return NULL; - } + G_OBJECT_CLASS (nm_device_wifi_parent_class)->constructed (object); if (priv->capabilities & NM_WIFI_DEVICE_CAP_AP) _LOGI (LOGD_HW | LOGD_WIFI, "driver supports Access Point (AP) mode"); /* Connect to the supplicant manager */ priv->sup_mgr = g_object_ref (nm_supplicant_manager_get ()); - - return object; } static gboolean @@ -268,6 +232,10 @@ supplicant_interface_acquire (NMDeviceWifi *self) "notify::scanning", G_CALLBACK (supplicant_iface_notify_scanning_cb), self); + g_signal_connect (priv->sup_iface, + "notify::" NM_SUPPLICANT_INTERFACE_CURRENT_BSS, + G_CALLBACK (supplicant_iface_notify_current_bss), + self); return TRUE; } @@ -288,10 +256,7 @@ supplicant_interface_release (NMDeviceWifi *self) _LOGD (LOGD_WIFI_SCAN, "reset scanning interval to %d seconds", priv->scan_interval); - if (priv->scanlist_cull_id) { - g_source_remove (priv->scanlist_cull_id); - priv->scanlist_cull_id = 0; - } + nm_clear_g_source (&priv->ap_dump_id); if (priv->sup_iface) { remove_supplicant_interface_error_handler (self); @@ -310,177 +275,30 @@ supplicant_interface_release (NMDeviceWifi *self) static NMAccessPoint * get_ap_by_path (NMDeviceWifi *self, const char *path) { - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - GSList *iter; + g_return_val_if_fail (path != NULL, NULL); + return g_hash_table_lookup (NM_DEVICE_WIFI_GET_PRIVATE (self)->aps, path); - if (!path) - return NULL; - - for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) { - if (g_strcmp0 (path, nm_ap_get_dbus_path (NM_AP (iter->data))) == 0) - return NM_AP (iter->data); - } - return NULL; } static NMAccessPoint * get_ap_by_supplicant_path (NMDeviceWifi *self, const char *path) { - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - GSList *iter; + GHashTableIter iter; + NMAccessPoint *ap; - if (!path) - return NULL; + g_return_val_if_fail (path != NULL, NULL); - for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) { - if (g_strcmp0 (path, nm_ap_get_supplicant_path (NM_AP (iter->data))) == 0) - return NM_AP (iter->data); + g_hash_table_iter_init (&iter, NM_DEVICE_WIFI_GET_PRIVATE (self)->aps); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &ap)) { + if (g_strcmp0 (path, nm_ap_get_supplicant_path (ap)) == 0) + return ap; } return NULL; } -static NMAccessPoint * -find_active_ap (NMDeviceWifi *self, - NMAccessPoint *ignore_ap, - gboolean match_hidden) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - int ifindex = nm_device_get_ifindex (NM_DEVICE (self)); - guint8 bssid[ETH_ALEN]; - GByteArray *ssid; - GSList *iter; - int i = 0; - NMAccessPoint *match_nofreq = NULL, *active_ap = NULL; - gboolean found_a_band = FALSE; - gboolean found_bg_band = FALSE; - NM80211Mode devmode; - guint32 devfreq; - - nm_platform_wifi_get_bssid (NM_PLATFORM_GET, ifindex, bssid); - _LOGD (LOGD_WIFI, "active BSSID: %02x:%02x:%02x:%02x:%02x:%02x", - bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]); - - if (!nm_ethernet_address_is_valid (bssid, ETH_ALEN)) - return NULL; - - ssid = nm_platform_wifi_get_ssid (NM_PLATFORM_GET, ifindex); - _LOGD (LOGD_WIFI, "active SSID: %s%s%s", - ssid ? "'" : "", - ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)", - ssid ? "'" : ""); - - devmode = nm_platform_wifi_get_mode (NM_PLATFORM_GET, ifindex); - devfreq = nm_platform_wifi_get_frequency (NM_PLATFORM_GET, ifindex); - - /* When matching hidden APs, do a second pass that ignores the SSID check, - * because NM might not yet know the SSID of the hidden AP in the scan list - * and therefore it won't get matched the first time around. - */ - while (i++ < (match_hidden ? 2 : 1)) { - _LOGD (LOGD_WIFI, " Pass #%d %s", i, i > 1 ? "(ignoring SSID)" : ""); - - /* Find this SSID + BSSID in the device's AP list */ - for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) { - NMAccessPoint *ap = NM_AP (iter->data); - const char *ap_bssid = nm_ap_get_address (ap); - const GByteArray *ap_ssid = nm_ap_get_ssid (ap); - NM80211Mode apmode; - guint32 apfreq; - - _LOGD (LOGD_WIFI, " AP: %s%s%s %s", - ap_ssid ? "'" : "", - ap_ssid ? nm_utils_escape_ssid (ap_ssid->data, ap_ssid->len) : "(none)", - ap_ssid ? "'" : "", - str_if_set (ap_bssid, "(none)")); - - if (ap == ignore_ap) { - _LOGD (LOGD_WIFI, " ignored"); - continue; - } - - if (!nm_utils_hwaddr_matches (bssid, ETH_ALEN, ap_bssid, -1)) { - _LOGD (LOGD_WIFI, " BSSID mismatch"); - continue; - } - - if (i == 0) { - if ( (ssid && !ap_ssid) - || (ap_ssid && !ssid) - || (ssid && ap_ssid && !nm_utils_same_ssid (ssid->data, ssid->len, - ap_ssid->data, ap_ssid->len, - TRUE))) { - _LOGD (LOGD_WIFI, " SSID mismatch"); - continue; - } - } - - apmode = nm_ap_get_mode (ap); - if (devmode != apmode) { - _LOGD (LOGD_WIFI, " mode mismatch (device %d, ap %d)", - devmode, apmode); - continue; - } - - apfreq = nm_ap_get_freq (ap); - if (devfreq != apfreq) { - _LOGD (LOGD_WIFI, " frequency mismatch (device %u, ap %u)", - devfreq, apfreq); - - if (match_nofreq == NULL) - match_nofreq = ap; - - if (apfreq > 4000) - found_a_band = TRUE; - else if (apfreq > 2000) - found_bg_band = TRUE; - continue; - } - - // FIXME: handle security settings here too - _LOGD (LOGD_WIFI, " matched"); - active_ap = ap; - goto done; - } - } - - /* Some proprietary drivers (wl.o) report tuned frequency (like when - * scanning) instead of the associated AP's frequency. This is a great - * example of how WEXT is underspecified. We use frequency to find the - * active AP in the scan list because some configurations use the same - * SSID/BSSID on the 2GHz and 5GHz bands simultaneously, and we need to - * make sure we get the right AP in the right band. This configuration - * is uncommon though, and the frequency check penalizes closed drivers we - * can't fix. Because we're not total dicks, ignore the frequency condition - * if the associated BSSID/SSID exists only in one band since that's most - * likely the AP we want. Sometimes wl.o returns a frequency of 0, so if - * we can't match the AP based on frequency at all, just give up. - */ - if (match_nofreq && ((found_a_band != found_bg_band) || (devfreq == 0))) { - const GByteArray *ap_ssid = nm_ap_get_ssid (match_nofreq); - - _LOGD (LOGD_WIFI, " matched %s%s%s %s", - ap_ssid ? "'" : "", - ap_ssid ? nm_utils_escape_ssid (ap_ssid->data, ap_ssid->len) : "(none)", - ap_ssid ? "'" : "", - str_if_set (nm_ap_get_address (match_nofreq), "(none)")); - - active_ap = match_nofreq; - goto done; - } - - _LOGD (LOGD_WIFI, " No matching AP found."); - -done: - if (ssid) - g_byte_array_free (ssid, TRUE); - return active_ap; -} - static void update_seen_bssids_cache (NMDeviceWifi *self, NMAccessPoint *ap) { - NMConnection *connection; - g_return_if_fail (NM_IS_DEVICE_WIFI (self)); if (ap == NULL) @@ -490,12 +308,10 @@ update_seen_bssids_cache (NMDeviceWifi *self, NMAccessPoint *ap) if (nm_ap_get_mode (ap) != NM_802_11_MODE_INFRA) return; - if (nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_ACTIVATED) { - connection = nm_device_get_connection (NM_DEVICE (self)); - if (connection) { - nm_settings_connection_add_seen_bssid (NM_SETTINGS_CONNECTION (connection), - nm_ap_get_address (ap)); - } + if ( nm_device_get_state (NM_DEVICE (self)) == NM_DEVICE_STATE_ACTIVATED + && nm_device_has_unmodified_applied_connection (NM_DEVICE (self), NM_SETTING_COMPARE_FLAG_NONE)) { + nm_settings_connection_add_seen_bssid (nm_device_get_settings_connection (NM_DEVICE (self)), + nm_ap_get_address (ap)); } } @@ -516,13 +332,6 @@ set_current_ap (NMDeviceWifi *self, NMAccessPoint *new_ap, gboolean recheck_avai if (new_ap) { priv->current_ap = g_object_ref (new_ap); - /* Move the current AP to the front of the scan list. Since we - * do a lot of searches looking for the current AP, it saves - * time to have it in front. - */ - priv->ap_list = g_slist_remove (priv->ap_list, new_ap); - priv->ap_list = g_slist_prepend (priv->ap_list, new_ap); - /* Update seen BSSIDs cache */ update_seen_bssids_cache (self, priv->current_ap); } else @@ -531,11 +340,9 @@ set_current_ap (NMDeviceWifi *self, NMAccessPoint *new_ap, gboolean recheck_avai if (old_ap) { NM80211Mode mode = nm_ap_get_mode (old_ap); - if (mode == NM_802_11_MODE_ADHOC || mode == NM_802_11_MODE_AP || nm_ap_get_fake (old_ap)) { - remove_access_point (self, old_ap); - if (recheck_available_connections) - nm_device_recheck_available_connections (NM_DEVICE (self)); - } + /* Remove any AP from the internal list if it was created by NM or isn't known to the supplicant */ + if (mode == NM_802_11_MODE_ADHOC || mode == NM_802_11_MODE_AP || nm_ap_get_fake (old_ap)) + ap_add_remove (self, ACCESS_POINT_REMOVED, old_ap, recheck_available_connections); g_object_unref (old_ap); } @@ -543,11 +350,10 @@ set_current_ap (NMDeviceWifi *self, NMAccessPoint *new_ap, gboolean recheck_avai } static void -periodic_update (NMDeviceWifi *self, NMAccessPoint *ignore_ap) +periodic_update (NMDeviceWifi *self) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); int ifindex = nm_device_get_ifindex (NM_DEVICE (self)); - NMAccessPoint *new_ap; guint32 new_rate; int percent; NMDeviceState state; @@ -574,65 +380,15 @@ periodic_update (NMDeviceWifi *self, NMAccessPoint *ignore_ap) if (priv->mode == NM_802_11_MODE_AP) return; - /* In IBSS mode, most newer firmware/drivers do "BSS coalescing" where - * multiple IBSS stations using the same SSID will eventually switch to - * using the same BSSID to avoid network segmentation. When this happens, - * the card's reported BSSID will change, but the new BSS may not - * be in the scan list, since scanning isn't done in ad-hoc mode for - * various reasons. So pull the BSSID from the card and update the - * current AP with it, if the current AP is adhoc. - */ - if (priv->current_ap && (nm_ap_get_mode (priv->current_ap) == NM_802_11_MODE_ADHOC)) { - guint8 bssid[ETH_ALEN] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; - - nm_platform_wifi_get_bssid (NM_PLATFORM_GET, ifindex, bssid); - /* 0x02 means "locally administered" and should be OR-ed into - * the first byte of IBSS BSSIDs. - */ - if ((bssid[0] & 0x02) && nm_ethernet_address_is_valid (bssid, ETH_ALEN)) { - char *bssid_str = nm_utils_hwaddr_ntoa (bssid, ETH_ALEN); - nm_ap_set_address (priv->current_ap, bssid_str); - g_free (bssid_str); - } - } - - new_ap = find_active_ap (self, ignore_ap, FALSE); - if (new_ap) { - /* Try to smooth out the strength. Atmel cards, for example, will give no strength - * one second and normal strength the next. - */ + if (priv->current_ap) { + /* Smooth out the strength to work around crappy drivers */ percent = nm_platform_wifi_get_quality (NM_PLATFORM_GET, ifindex); if (percent >= 0 || ++priv->invalid_strength_counter > 3) { - nm_ap_set_strength (new_ap, (gint8) percent); + nm_ap_set_strength (priv->current_ap, (gint8) percent); priv->invalid_strength_counter = 0; } } - if (new_ap != priv->current_ap) { - const char *new_bssid = NULL; - const GByteArray *new_ssid = NULL; - const char *old_bssid = NULL; - const GByteArray *old_ssid = NULL; - - if (new_ap) { - new_bssid = nm_ap_get_address (new_ap); - new_ssid = nm_ap_get_ssid (new_ap); - } - - if (priv->current_ap) { - old_bssid = nm_ap_get_address (priv->current_ap); - old_ssid = nm_ap_get_ssid (priv->current_ap); - } - - _LOGI (LOGD_WIFI, "roamed from BSSID %s (%s) to %s (%s)", - old_bssid ? old_bssid : "(none)", - old_ssid ? nm_utils_escape_ssid (old_ssid->data, old_ssid->len) : "(none)", - new_bssid ? new_bssid : "(none)", - new_ssid ? nm_utils_escape_ssid (new_ssid->data, new_ssid->len) : "(none)"); - - set_current_ap (self, new_ap, TRUE); - } - new_rate = nm_platform_wifi_get_rate (NM_PLATFORM_GET, ifindex); if (new_rate != priv->rate) { priv->rate = new_rate; @@ -643,10 +399,18 @@ periodic_update (NMDeviceWifi *self, NMAccessPoint *ignore_ap) static gboolean periodic_update_cb (gpointer user_data) { - periodic_update (NM_DEVICE_WIFI (user_data), NULL); + periodic_update (NM_DEVICE_WIFI (user_data)); return TRUE; } +static void +realize_start_notify (NMDevice *device, const NMPlatformLink *plink) +{ + NM_DEVICE_CLASS (nm_device_wifi_parent_class)->realize_start_notify (device, plink); + + g_object_notify (G_OBJECT (device), NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS); +} + static gboolean bring_up (NMDevice *device, gboolean *no_firmware) { @@ -657,47 +421,55 @@ bring_up (NMDevice *device, gboolean *no_firmware) } static void -emit_ap_added_removed (NMDeviceWifi *self, - guint signum, - NMAccessPoint *ap, - gboolean recheck_available_connections) +ap_add_remove (NMDeviceWifi *self, + guint signum, + NMAccessPoint *ap, + gboolean recheck_available_connections) { + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + nm_assert (NM_IN_SET (signum, ACCESS_POINT_ADDED, ACCESS_POINT_REMOVED)); + + if (signum == ACCESS_POINT_ADDED) { + g_hash_table_insert (priv->aps, + (gpointer) nm_exported_object_export ((NMExportedObject *) ap), + g_object_ref (ap)); + } + g_signal_emit (self, signals[signum], 0, ap); g_object_notify (G_OBJECT (self), NM_DEVICE_WIFI_ACCESS_POINTS); + + if (signum == ACCESS_POINT_REMOVED) { + g_hash_table_remove (priv->aps, nm_exported_object_get_path ((NMExportedObject *) ap)); + nm_exported_object_unexport ((NMExportedObject *) ap); + g_object_unref (ap); + } + nm_device_emit_recheck_auto_activate (NM_DEVICE (self)); if (recheck_available_connections) nm_device_recheck_available_connections (NM_DEVICE (self)); } static void -remove_access_point (NMDeviceWifi *device, - NMAccessPoint *ap) -{ - NMDeviceWifi *self = NM_DEVICE_WIFI (device); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - g_return_if_fail (ap); - g_return_if_fail (ap != priv->current_ap); - g_return_if_fail (g_slist_find (priv->ap_list, ap)); - - priv->ap_list = g_slist_remove (priv->ap_list, ap); - emit_ap_added_removed (self, ACCESS_POINT_REMOVED, ap, FALSE); - g_object_unref (ap); -} - -static void remove_all_aps (NMDeviceWifi *self) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + GHashTableIter iter; + NMAccessPoint *ap; - if (priv->ap_list) { - set_current_ap (self, NULL, FALSE); + if (!g_hash_table_size (priv->aps)) + return; - while (priv->ap_list) - remove_access_point (self, NM_AP (priv->ap_list->data)); + set_current_ap (self, NULL, FALSE); - nm_device_recheck_available_connections (NM_DEVICE (self)); +again: + g_hash_table_iter_init (&iter, priv->aps); + if (g_hash_table_iter_next (&iter, NULL, (gpointer) &ap)) { + ap_add_remove (self, ACCESS_POINT_REMOVED, ap, FALSE); + goto again; } + + nm_device_recheck_available_connections (NM_DEVICE (self)); } static void @@ -706,29 +478,14 @@ deactivate (NMDevice *device) NMDeviceWifi *self = NM_DEVICE_WIFI (device); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); int ifindex = nm_device_get_ifindex (device); - NMConnection *connection; NM80211Mode old_mode = priv->mode; - connection = nm_device_get_connection (device); - if (connection) { - /* Clear wireless secrets tries when deactivating */ - g_object_set_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES, NULL); - } - - if (priv->periodic_source_id) { - g_source_remove (priv->periodic_source_id); - priv->periodic_source_id = 0; - } + nm_clear_g_source (&priv->periodic_source_id); cleanup_association_attempt (self, TRUE); priv->rate = 0; - /* If the AP is 'fake', i.e. it wasn't actually found from - * a scan but the user tried to connect to it manually (maybe it - * was non-broadcasting or something) get rid of it, because 'fake' - * APs should only live for as long as we're connected to them. - **/ set_current_ap (self, NULL, TRUE); /* Clear any critical protocol notification in the Wi-Fi stack */ @@ -738,6 +495,8 @@ deactivate (NMDevice *device) if (nm_device_get_initial_hw_address (device)) nm_device_set_hw_addr (device, nm_device_get_initial_hw_address (device), "reset", LOGD_WIFI); + nm_platform_wifi_set_powersave (NM_PLATFORM_GET, ifindex, 0); + /* Ensure we're in infrastructure mode after deactivation; some devices * (usually older ones) don't scan well in adhoc mode. */ @@ -848,7 +607,7 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) return FALSE; if (priv->sup_iface) { - if (nm_supplicant_interface_get_ap_support (priv->sup_iface) == AP_SUPPORT_NO) + if (nm_supplicant_interface_get_ap_support (priv->sup_iface) == NM_SUPPLICANT_FEATURE_NO) return FALSE; } } @@ -860,6 +619,28 @@ check_connection_compatible (NMDevice *device, NMConnection *connection) return TRUE; } +static NMAccessPoint * +find_first_compatible_ap (NMDeviceWifi *self, + NMConnection *connection, + gboolean allow_unstable_order) +{ + GHashTableIter iter; + NMAccessPoint *ap; + NMAccessPoint *cand_ap = NULL; + + g_return_val_if_fail (connection != NULL, NULL); + + g_hash_table_iter_init (&iter, NM_DEVICE_WIFI_GET_PRIVATE (self)->aps); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &ap)) { + if (!nm_ap_check_compatible (ap, connection)) + continue; + if (allow_unstable_order) + return ap; + if (!cand_ap || (nm_ap_get_id (cand_ap) < nm_ap_get_id (ap))) + cand_ap = ap; + } + return cand_ap; +} static gboolean check_connection_available (NMDevice *device, @@ -867,10 +648,8 @@ check_connection_available (NMDevice *device, NMDeviceCheckConAvailableFlags flags, const char *specific_object) { - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device); NMSettingWireless *s_wifi; const char *mode; - GSList *ap_iter = NULL; s_wifi = nm_connection_get_setting_wireless (connection); g_return_val_if_fail (s_wifi, FALSE); @@ -904,13 +683,8 @@ check_connection_available (NMDevice *device, if (nm_setting_wireless_get_hidden (s_wifi) || NM_FLAGS_HAS (flags, _NM_DEVICE_CHECK_CON_AVAILABLE_FOR_USER_REQUEST_IGNORE_AP)) return TRUE; - /* check if its visible */ - for (ap_iter = priv->ap_list; ap_iter; ap_iter = g_slist_next (ap_iter)) { - if (nm_ap_check_compatible (NM_AP (ap_iter->data), connection)) - return TRUE; - } - - return FALSE; + /* check at least one AP is compatible with this connection */ + return !!find_first_compatible_ap (NM_DEVICE_WIFI (device), connection, TRUE); } /* @@ -957,7 +731,6 @@ complete_connection (NMDevice *device, GError **error) { NMDeviceWifi *self = NM_DEVICE_WIFI (device); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); NMSettingWireless *s_wifi; const char *setting_mac; char *str_ssid = NULL; @@ -965,7 +738,6 @@ complete_connection (NMDevice *device, const GByteArray *ssid = NULL; GByteArray *tmp_ssid = NULL; GBytes *setting_ssid = NULL; - GSList *iter; gboolean hidden = FALSE; const char *perm_hw_addr; @@ -991,12 +763,7 @@ complete_connection (NMDevice *device, } /* Find a compatible AP in the scan list */ - for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) { - if (nm_ap_check_compatible (NM_AP (iter->data), connection)) { - ap = NM_AP (iter->data); - break; - } - } + ap = find_first_compatible_ap (self, connection, FALSE); /* If we still don't have an AP, then the WiFI settings needs to be * fully specified by the client. Might not be able to find an AP @@ -1159,8 +926,7 @@ can_auto_connect (NMDevice *device, char **specific_object) { NMDeviceWifi *self = NM_DEVICE_WIFI (device); - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - GSList *ap_iter; + NMAccessPoint *ap; const char *method = NULL; guint64 timestamp = 0; @@ -1181,130 +947,141 @@ can_auto_connect (NMDevice *device, if (!strcmp (method, NM_SETTING_IP4_CONFIG_METHOD_SHARED)) return TRUE; - for (ap_iter = priv->ap_list; ap_iter; ap_iter = g_slist_next (ap_iter)) { - NMAccessPoint *ap = NM_AP (ap_iter->data); - - if (nm_ap_check_compatible (ap, connection)) { - /* All good; connection is usable */ - *specific_object = (char *) nm_ap_get_dbus_path (ap); - return TRUE; - } + ap = find_first_compatible_ap (self, connection, FALSE); + if (ap) { + /* All good; connection is usable */ + *specific_object = (char *) nm_exported_object_get_path (NM_EXPORTED_OBJECT (ap)); + return TRUE; } return FALSE; } -static void -ap_list_dump (NMDeviceWifi *self) +static gint +ap_id_compare (NMAccessPoint *a, NMAccessPoint *b) { - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - GSList * elt; - int i = 0; + guint32 a_id = nm_ap_get_id (a); + guint32 b_id = nm_ap_get_id (b); - g_return_if_fail (NM_IS_DEVICE_WIFI (self)); + return a_id < b_id ? -1 : (a_id == b_id ? 0 : 1); +} - _LOGD (LOGD_WIFI_SCAN, "Current AP list:"); - for (elt = priv->ap_list; elt; elt = g_slist_next (elt), i++) { - NMAccessPoint * ap = NM_AP (elt->data); - nm_ap_dump (ap, "List AP: "); - } - _LOGD (LOGD_WIFI_SCAN, "Current AP list: done"); +static GSList * +get_sorted_ap_list (NMDeviceWifi *self) +{ + GSList *sorted = NULL; + GHashTableIter iter; + NMAccessPoint *ap; + + g_hash_table_iter_init (&iter, NM_DEVICE_WIFI_GET_PRIVATE (self)->aps); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &ap)) + sorted = g_slist_prepend (sorted, ap); + return g_slist_sort (sorted, (GCompareFunc) ap_id_compare); } -static gboolean -impl_device_get_access_points (NMDeviceWifi *self, - GPtrArray **aps, - GError **err) +static void +impl_device_wifi_get_access_points (NMDeviceWifi *self, + GDBusMethodInvocation *context) { - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - GSList *elt; + GSList *sorted, *iter; + GPtrArray *paths; - *aps = g_ptr_array_new (); - for (elt = priv->ap_list; elt; elt = g_slist_next (elt)) { - NMAccessPoint *ap = NM_AP (elt->data); + paths = g_ptr_array_new (); + sorted = get_sorted_ap_list (self); + for (iter = sorted; iter; iter = iter->next) { + NMAccessPoint *ap = NM_AP (iter->data); if (nm_ap_get_ssid (ap)) - g_ptr_array_add (*aps, g_strdup (nm_ap_get_dbus_path (ap))); + g_ptr_array_add (paths, g_strdup (nm_exported_object_get_path (NM_EXPORTED_OBJECT (ap)))); } - return TRUE; + g_ptr_array_add (paths, NULL); + g_slist_free (sorted); + + g_dbus_method_invocation_return_value (context, g_variant_new ("(^ao)", (char **) paths->pdata)); + g_ptr_array_unref (paths); } -static gboolean -impl_device_get_all_access_points (NMDeviceWifi *self, - GPtrArray **aps, - GError **err) +static void +impl_device_wifi_get_all_access_points (NMDeviceWifi *self, + GDBusMethodInvocation *context) { - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - GSList *elt; + GSList *sorted, *iter; + GPtrArray *paths; - *aps = g_ptr_array_new (); - for (elt = priv->ap_list; elt; elt = g_slist_next (elt)) - g_ptr_array_add (*aps, g_strdup (nm_ap_get_dbus_path (NM_AP (elt->data)))); - return TRUE; + paths = g_ptr_array_new (); + sorted = get_sorted_ap_list (self); + for (iter = sorted; iter; iter = iter->next) + g_ptr_array_add (paths, g_strdup (nm_exported_object_get_path (NM_EXPORTED_OBJECT (iter->data)))); + g_ptr_array_add (paths, NULL); + g_slist_free (sorted); + + g_dbus_method_invocation_return_value (context, g_variant_new ("(^ao)", (char **) paths->pdata)); + g_ptr_array_unref (paths); } static void request_scan_cb (NMDevice *device, - DBusGMethodInvocation *context, + GDBusMethodInvocation *context, + NMAuthSubject *subject, GError *error, gpointer user_data) { NMDeviceWifi *self = NM_DEVICE_WIFI (device); - GError *local = NULL; - gs_unref_hashtable GHashTable *new_scan_options = user_data; + gs_unref_variant GVariant *new_scan_options = user_data; if (error) { - dbus_g_method_return_error (context, error); + g_dbus_method_invocation_return_gerror (context, error); return; } if (!check_scanning_allowed (self)) { - local = g_error_new_literal (NM_DEVICE_ERROR, - NM_DEVICE_ERROR_NOT_ALLOWED, - "Scanning not allowed at this time"); - dbus_g_method_return_error (context, local); - g_error_free (local); + g_dbus_method_invocation_return_error_literal (context, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_NOT_ALLOWED, + "Scanning not allowed at this time"); return; } cancel_pending_scan (self); request_wireless_scan (self, new_scan_options); - dbus_g_method_return (context); + g_dbus_method_invocation_return_value (context, NULL); } static void -impl_device_request_scan (NMDeviceWifi *self, - GHashTable *options, - DBusGMethodInvocation *context) +impl_device_wifi_request_scan (NMDeviceWifi *self, + GDBusMethodInvocation *context, + GVariant *options) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); NMDevice *device = NM_DEVICE (self); gint32 last_scan; - GError *error; if ( !priv->enabled || !priv->sup_iface || nm_device_get_state (device) < NM_DEVICE_STATE_DISCONNECTED || nm_device_is_activating (device)) { - error = g_error_new_literal (NM_DEVICE_ERROR, - NM_DEVICE_ERROR_NOT_ALLOWED, - "Scanning not allowed while unavailable or activating"); - goto error; + g_dbus_method_invocation_return_error_literal (context, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_NOT_ALLOWED, + "Scanning not allowed while unavailable or activating"); + return; } if (nm_supplicant_interface_get_scanning (priv->sup_iface)) { - error = g_error_new_literal (NM_DEVICE_ERROR, - NM_DEVICE_ERROR_NOT_ALLOWED, - "Scanning not allowed while already scanning"); - goto error; + g_dbus_method_invocation_return_error_literal (context, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_NOT_ALLOWED, + "Scanning not allowed while already scanning"); + return; } last_scan = nm_supplicant_interface_get_last_scan_time (priv->sup_iface); if (last_scan && (nm_utils_get_monotonic_timestamp_s () - last_scan) < 10) { - error = g_error_new_literal (NM_DEVICE_ERROR, - NM_DEVICE_ERROR_NOT_ALLOWED, - "Scanning not allowed immediately following previous scan"); - goto error; + g_dbus_method_invocation_return_error_literal (context, + NM_DEVICE_ERROR, + NM_DEVICE_ERROR_NOT_ALLOWED, + "Scanning not allowed immediately following previous scan"); + return; } /* Ask the manager to authenticate this request for us */ @@ -1315,12 +1092,7 @@ impl_device_request_scan (NMDeviceWifi *self, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE, request_scan_cb, - options ? g_hash_table_ref (options) : NULL); - return; - -error: - dbus_g_method_return_error (context, error); - g_error_free (error); + options ? g_variant_ref (options) : NULL); } static gboolean @@ -1367,7 +1139,7 @@ scanning_allowed (NMDeviceWifi *self) || nm_supplicant_interface_get_scanning (priv->sup_iface)) return FALSE; - connection = nm_device_get_connection (NM_DEVICE (self)); + connection = nm_device_get_applied_connection (NM_DEVICE (self)); if (connection) { NMSettingWireless *s_wifi; const char *ip4_method = NULL; @@ -1481,8 +1253,32 @@ build_hidden_probe_list (NMDeviceWifi *self) return ssids; } +static GPtrArray * +ssids_options_to_ptrarray (GVariant *value) +{ + GPtrArray *ssids = NULL; + GByteArray *ssid_array; + GVariant *v; + const guint8 *bytes; + gsize len; + int num_ssids, i; + + num_ssids = g_variant_n_children (value); + if (num_ssids) { + ssids = g_ptr_array_new_full (num_ssids, (GDestroyNotify) g_byte_array_unref); + for (i = 0; i < num_ssids; i++) { + v = g_variant_get_child_value (value, i); + bytes = g_variant_get_fixed_array (v, &len, sizeof (guint8)); + ssid_array = g_byte_array_new (); + g_byte_array_append (ssid_array, bytes, len); + g_ptr_array_add (ssids, ssid_array); + } + } + return ssids; +} + static void -request_wireless_scan (NMDeviceWifi *self, GHashTable *scan_options) +request_wireless_scan (NMDeviceWifi *self, GVariant *scan_options) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); gboolean backoff = FALSE; @@ -1496,13 +1292,16 @@ request_wireless_scan (NMDeviceWifi *self, GHashTable *scan_options) if (check_scanning_allowed (self)) { _LOGD (LOGD_WIFI_SCAN, "scanning requested"); - if (scan_options && g_hash_table_size (scan_options)) { - GValue *val = g_hash_table_lookup (scan_options, "ssids"); + if (scan_options) { + GVariant *val = g_variant_lookup_value (scan_options, "ssids", NULL); - if (val && G_VALUE_HOLDS (val, DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR)) - ssids = g_ptr_array_ref (g_value_get_boxed (val)); - else - _LOGD (LOGD_WIFI_SCAN, "ignoring invalid scan options"); + if (val) { + if (g_variant_is_of_type (val, G_VARIANT_TYPE ("aay"))) + ssids = ssids_options_to_ptrarray (val); + else + _LOGD (LOGD_WIFI_SCAN, "ignoring invalid 'ssids' scan option"); + g_variant_unref (val); + } } if (!ssids) ssids = build_hidden_probe_list (self); @@ -1606,10 +1405,7 @@ cancel_pending_scan (NMDeviceWifi *self) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - if (priv->pending_scan_id) { - g_source_remove (priv->pending_scan_id); - priv->pending_scan_id = 0; - } + nm_clear_g_source (&priv->pending_scan_id); } static void @@ -1621,13 +1417,9 @@ supplicant_iface_scan_done_cb (NMSupplicantInterface *iface, _LOGD (LOGD_WIFI_SCAN, "scan %s", success ? "successful" : "failed"); + priv->last_scan = nm_utils_get_monotonic_timestamp_s (); schedule_scan (self, success); - /* Ensure that old APs get removed, which otherwise only - * happens when there are new BSSes. - */ - schedule_scanlist_cull (self); - if (priv->requested_scan) { priv->requested_scan = FALSE; nm_device_remove_pending_action (NM_DEVICE (self), "scan", TRUE); @@ -1639,7 +1431,35 @@ supplicant_iface_scan_done_cb (NMSupplicantInterface *iface, * */ -#define WPAS_REMOVED_TAG "supplicant-removed" +static gboolean +ap_list_dump (gpointer user_data) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (user_data); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + GSList *sorted, *iter; + + priv->ap_dump_id = 0; + _LOGD (LOGD_WIFI_SCAN, "APs: [now:%u last:%u next:%u]", + nm_utils_get_monotonic_timestamp_s (), + priv->last_scan, + priv->scheduled_scan_time); + sorted = get_sorted_ap_list (self); + for (iter = sorted; iter; iter = iter->next) + nm_ap_dump (NM_AP (iter->data), "dump ", nm_device_get_iface (NM_DEVICE (self))); + g_slist_free (sorted); + return G_SOURCE_REMOVE; +} + +static void +schedule_ap_list_dump (NMDeviceWifi *self) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + if (!nm_logging_enabled (LOGL_DEBUG, LOGD_WIFI_SCAN)) + return; + nm_clear_g_source (&priv->ap_dump_id); + priv->ap_dump_id = g_timeout_add_seconds (1, ap_list_dump, self); +} static void try_fill_ssid_for_hidden_ap (NMAccessPoint *ap) @@ -1673,213 +1493,77 @@ try_fill_ssid_for_hidden_ap (NMAccessPoint *ap) } } -/* - * merge_scanned_ap - * - * If there is already an entry that matches the BSSID and ESSID of the - * AP to merge, replace that entry with the scanned AP. Otherwise, add - * the scanned AP to the list. - * - * TODO: possibly need to differentiate entries based on security too; i.e. if - * there are two scan results with the same BSSID and SSID but different - * security options? - * - */ static void -merge_scanned_ap (NMDeviceWifi *self, - NMAccessPoint *merge_ap) +supplicant_iface_new_bss_cb (NMSupplicantInterface *iface, + const char *object_path, + GVariant *properties, + NMDeviceWifi *self) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + NMDeviceState state; + NMAccessPoint *ap; NMAccessPoint *found_ap = NULL; const GByteArray *ssid; - gboolean strict_match = TRUE; + + g_return_if_fail (self != NULL); + g_return_if_fail (properties != NULL); + g_return_if_fail (iface != NULL); + + /* Ignore new APs when unavailable, unmanaged, or in AP mode */ + state = nm_device_get_state (NM_DEVICE (self)); + if (state <= NM_DEVICE_STATE_UNAVAILABLE) + return; + if (NM_DEVICE_WIFI_GET_PRIVATE (self)->mode == NM_802_11_MODE_AP) + return; + + ap = nm_ap_new_from_properties (object_path, properties); + if (!ap) { + _LOGD (LOGD_WIFI_SCAN, "invalid AP properties received for %s", object_path); + return; + } /* Let the manager try to fill in the SSID from seen-bssids lists */ - ssid = nm_ap_get_ssid (merge_ap); + ssid = nm_ap_get_ssid (ap); if (!ssid || nm_utils_is_empty_ssid (ssid->data, ssid->len)) { /* Try to fill the SSID from the AP database */ - try_fill_ssid_for_hidden_ap (merge_ap); + try_fill_ssid_for_hidden_ap (ap); - ssid = nm_ap_get_ssid (merge_ap); + ssid = nm_ap_get_ssid (ap); if (ssid && (nm_utils_is_empty_ssid (ssid->data, ssid->len) == FALSE)) { /* Yay, matched it, no longer treat as hidden */ _LOGD (LOGD_WIFI_SCAN, "matched hidden AP %s => '%s'", - nm_ap_get_address (merge_ap), nm_utils_escape_ssid (ssid->data, ssid->len)); - nm_ap_set_broadcast (merge_ap, FALSE); + nm_ap_get_address (ap), nm_utils_escape_ssid (ssid->data, ssid->len)); } else { /* Didn't have an entry for this AP in the database */ _LOGD (LOGD_WIFI_SCAN, "failed to match hidden AP %s", - nm_ap_get_address (merge_ap)); + nm_ap_get_address (ap)); } } - /* If the incoming scan result matches the hidden AP that NM is currently - * connected to but hasn't been seen in the scan list yet, don't use - * strict matching. Because the capabilities of the fake AP have to be - * constructed from the NMConnection of the activation request, they won't - * always be the same as the capabilities of the real AP from the scan. - */ - if (priv->current_ap && nm_ap_get_fake (priv->current_ap)) - strict_match = FALSE; - - found_ap = get_ap_by_supplicant_path (self, nm_ap_get_supplicant_path (merge_ap)); - if (!found_ap) - found_ap = nm_ap_match_in_list (merge_ap, priv->ap_list, strict_match); + found_ap = get_ap_by_supplicant_path (self, object_path); if (found_ap) { - _LOGD (LOGD_WIFI_SCAN, "merging AP '%s' %s (%p) with existing (%p)", - ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)", - nm_ap_get_address (merge_ap), - merge_ap, - found_ap); - - nm_ap_set_supplicant_path (found_ap, nm_ap_get_supplicant_path (merge_ap)); - nm_ap_set_flags (found_ap, nm_ap_get_flags (merge_ap)); - nm_ap_set_wpa_flags (found_ap, nm_ap_get_wpa_flags (merge_ap)); - nm_ap_set_rsn_flags (found_ap, nm_ap_get_rsn_flags (merge_ap)); - nm_ap_set_strength (found_ap, nm_ap_get_strength (merge_ap)); - nm_ap_set_last_seen (found_ap, nm_ap_get_last_seen (merge_ap)); - nm_ap_set_broadcast (found_ap, nm_ap_get_broadcast (merge_ap)); - nm_ap_set_freq (found_ap, nm_ap_get_freq (merge_ap)); - nm_ap_set_max_bitrate (found_ap, nm_ap_get_max_bitrate (merge_ap)); - - /* If the AP is noticed in a scan, it's automatically no longer - * fake, since it clearly exists somewhere. - */ - nm_ap_set_fake (found_ap, FALSE); - g_object_set_data (G_OBJECT (found_ap), WPAS_REMOVED_TAG, NULL); + nm_ap_dump (ap, "updated ", nm_device_get_iface (NM_DEVICE (self))); + nm_ap_update_from_properties (found_ap, object_path, properties); } else { - /* New entry in the list */ - _LOGD (LOGD_WIFI_SCAN, "adding new AP '%s' %s (%p)", - ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)", - nm_ap_get_address (merge_ap), merge_ap); - - g_object_ref (merge_ap); - priv->ap_list = g_slist_prepend (priv->ap_list, merge_ap); - nm_ap_export_to_dbus (merge_ap); - emit_ap_added_removed (self, ACCESS_POINT_ADDED, merge_ap, TRUE); + nm_ap_dump (ap, "added ", nm_device_get_iface (NM_DEVICE (self))); + ap_add_remove (self, ACCESS_POINT_ADDED, ap, TRUE); } -} -static gboolean -cull_scan_list (NMDeviceWifi *self) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - gint32 now = nm_utils_get_monotonic_timestamp_s (); - GSList *outdated_list = NULL; - GSList *elt; - guint32 removed = 0, total = 0; - - priv->scanlist_cull_id = 0; - - _LOGD (LOGD_WIFI_SCAN, "checking scan list for outdated APs"); + g_object_unref (ap); - /* Walk the access point list and remove any access points older than - * three times the inactive scan interval. + /* Update the current AP if the supplicant notified a current BSS change + * before it sent the current BSS's scan result. */ - for (elt = priv->ap_list; elt; elt = g_slist_next (elt), total++) { - NMAccessPoint *ap = elt->data; - const guint prune_interval_s = SCAN_INTERVAL_MAX * 3; - gint32 last_seen; - - /* Don't cull the associated AP or manually created APs */ - if (ap == priv->current_ap) - continue; - g_assert (!nm_ap_get_fake (ap)); /* only the current_ap can be fake */ - - /* Don't cull APs still known to the supplicant. Since the supplicant - * doesn't yet emit property updates for "last seen" we have to rely - * on changing signal strength for updating "last seen". But if the - * AP's strength doesn't change we won't get any updates for the AP, - * and we'll end up here even if the AP was still found by the - * supplicant in the last scan. - */ - if ( nm_ap_get_supplicant_path (ap) - && g_object_get_data (G_OBJECT (ap), WPAS_REMOVED_TAG) == NULL) - continue; - - last_seen = nm_ap_get_last_seen (ap); - if (!last_seen || last_seen + prune_interval_s < now) - outdated_list = g_slist_prepend (outdated_list, ap); - } - - /* Remove outdated APs */ - for (elt = outdated_list; elt; elt = g_slist_next (elt)) { - NMAccessPoint *outdated_ap = NM_AP (elt->data); - const GByteArray *ssid; - - ssid = nm_ap_get_ssid (outdated_ap); - _LOGD (LOGD_WIFI_SCAN, - " removing %s (%s%s%s)", - str_if_set (nm_ap_get_address (outdated_ap), "(none)"), - ssid ? "'" : "", - ssid ? nm_utils_escape_ssid (ssid->data, ssid->len) : "(none)", - ssid ? "'" : ""); - - remove_access_point (self, outdated_ap); - removed++; - } - g_slist_free (outdated_list); - - _LOGD (LOGD_WIFI_SCAN, "removed %d APs (of %d)", - removed, total); - - ap_list_dump (self); - - if(removed > 0) - nm_device_recheck_available_connections (NM_DEVICE (self)); - - return FALSE; -} + if (g_strcmp0 (nm_supplicant_interface_get_current_bss (iface), object_path) == 0) + supplicant_iface_notify_current_bss (priv->sup_iface, NULL, self); -static void -schedule_scanlist_cull (NMDeviceWifi *self) -{ - NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - - /* Cull the scan list after the last request for it has come in */ - if (priv->scanlist_cull_id) - g_source_remove (priv->scanlist_cull_id); - priv->scanlist_cull_id = g_timeout_add_seconds (4, (GSourceFunc) cull_scan_list, self); -} - -static void -supplicant_iface_new_bss_cb (NMSupplicantInterface *iface, - const char *object_path, - GVariant *properties, - NMDeviceWifi *self) -{ - NMDeviceState state; - NMAccessPoint *ap; - - g_return_if_fail (self != NULL); - g_return_if_fail (properties != NULL); - g_return_if_fail (iface != NULL); - - /* Ignore new APs when unavailable, unmanaged, or in AP mode */ - state = nm_device_get_state (NM_DEVICE (self)); - if (state <= NM_DEVICE_STATE_UNAVAILABLE) - return; - if (NM_DEVICE_WIFI_GET_PRIVATE (self)->mode == NM_802_11_MODE_AP) - return; - - ap = nm_ap_new_from_properties (object_path, properties); - if (ap) { - nm_ap_dump (ap, "New AP: "); - - /* Add the AP to the device's AP list */ - merge_scanned_ap (self, ap); - g_object_unref (ap); - } else - _LOGD (LOGD_WIFI_SCAN, "invalid AP properties received for %s", object_path); - - /* Remove outdated access points */ - schedule_scanlist_cull (self); + schedule_ap_list_dump (self); } static void supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface, const char *object_path, - GHashTable *properties, + GVariant *properties, NMDeviceWifi *self) { NMDeviceState state; @@ -1889,18 +1573,17 @@ supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface, g_return_if_fail (object_path != NULL); g_return_if_fail (properties != NULL); - /* Ignore new APs when unavailable or unamnaged */ + /* Ignore new APs when unavailable or unmanaged */ state = nm_device_get_state (NM_DEVICE (self)); if (state <= NM_DEVICE_STATE_UNAVAILABLE) return; - /* Update the AP's last-seen property */ ap = get_ap_by_supplicant_path (self, object_path); - if (ap) - nm_ap_set_last_seen (ap, nm_utils_get_monotonic_timestamp_s ()); - - /* Remove outdated access points */ - schedule_scanlist_cull (self); + if (ap) { + nm_ap_dump (ap, "updated ", nm_device_get_iface (NM_DEVICE (self))); + nm_ap_update_from_properties (ap, object_path, properties); + schedule_ap_list_dump (self); + } } static void @@ -1908,28 +1591,28 @@ supplicant_iface_bss_removed_cb (NMSupplicantInterface *iface, const char *object_path, NMDeviceWifi *self) { + NMDeviceWifiPrivate *priv; NMAccessPoint *ap; g_return_if_fail (self != NULL); g_return_if_fail (object_path != NULL); + priv = NM_DEVICE_WIFI_GET_PRIVATE (self); ap = get_ap_by_supplicant_path (self, object_path); if (ap) { - gint32 now = nm_utils_get_monotonic_timestamp_s (); - gint32 last_seen = nm_ap_get_last_seen (ap); - - /* We don't know when the supplicant last saw the AP's beacons, - * it could be two minutes or it could be 2 seconds. Because the - * supplicant doesn't send property change notifications if the - * AP's other properties don't change, our last-seen time may be - * much older the supplicant's, and the AP would be immediately - * removed from the list on the next cleanup. So update the - * last-seen time to ensure the AP sticks around for at least - * one more periodic scan. - */ - nm_ap_set_last_seen (ap, MAX (last_seen, now - SCAN_INTERVAL_MAX)); - g_object_set_data (G_OBJECT (ap), WPAS_REMOVED_TAG, GUINT_TO_POINTER (TRUE)); -} + if (ap == priv->current_ap) { + /* The current AP cannot be removed (to prevent NM indicating that + * it is connected, but to nothing), but it must be removed later + * when the current AP is changed or cleared. Set 'fake' to + * indicate that this AP is now unknown to the supplicant. + */ + nm_ap_set_fake (ap, TRUE); + } else { + nm_ap_dump (ap, "removed ", nm_device_get_iface (NM_DEVICE (self))); + ap_add_remove (self, ACCESS_POINT_REMOVED, ap, TRUE); + schedule_ap_list_dump (self); + } + } } static void @@ -1937,15 +1620,8 @@ remove_supplicant_timeouts (NMDeviceWifi *self) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - if (priv->sup_timeout_id) { - g_source_remove (priv->sup_timeout_id); - priv->sup_timeout_id = 0; - } - - if (priv->link_timeout_id) { - g_source_remove (priv->link_timeout_id); - priv->link_timeout_id = 0; - } + nm_clear_g_source (&priv->sup_timeout_id); + nm_clear_g_source (&priv->link_timeout_id); } static void @@ -1970,17 +1646,19 @@ cleanup_supplicant_failures (NMDeviceWifi *self) static void wifi_secrets_cb (NMActRequest *req, - guint32 call_id, - NMConnection *connection, + NMActRequestGetSecretsCallId call_id, + NMSettingsConnection *connection, GError *error, gpointer user_data) { NMDevice *device = NM_DEVICE (user_data); NMDeviceWifi *self = NM_DEVICE_WIFI (device); - g_return_if_fail (req == nm_device_get_act_request (device)); + if (req != nm_device_get_act_request (device)) + return; + g_return_if_fail (nm_device_get_state (device) == NM_DEVICE_STATE_NEED_AUTH); - g_return_if_fail (nm_act_request_get_connection (req) == connection); + g_return_if_fail (nm_act_request_get_settings_connection (req) == connection); if (error) { _LOGW (LOGD_WIFI, "%s", error->message); @@ -2015,23 +1693,7 @@ link_timeout_cb (gpointer user_data) if (nm_device_get_state (device) != NM_DEVICE_STATE_ACTIVATED) return FALSE; - /* If the access point failed, and wasn't found by the supplicant when it - * attempted to reconnect, then it's probably out of range or turned off. - */ - if (priv->ssid_found == FALSE && priv->current_ap) { - NMAccessPoint *old_ap = g_object_ref (priv->current_ap); - - set_current_ap (self, NULL, TRUE); - - /* If it was an external entity and the supplicant doesn't know about - * it, remove it from the scan list. If it's still around, it'll get - * found in the next scan. - */ - if ( nm_ap_get_mode (old_ap) == NM_802_11_MODE_INFRA - && g_object_get_data (G_OBJECT (old_ap), WPAS_REMOVED_TAG)) - remove_access_point (self, old_ap); - g_object_unref (old_ap); - } + set_current_ap (self, NULL, TRUE); nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, @@ -2052,7 +1714,7 @@ need_new_8021x_secrets (NMDeviceWifi *self, g_assert (setting_name != NULL); - connection = nm_device_get_connection (NM_DEVICE (self)); + connection = nm_device_get_applied_connection (NM_DEVICE (self)); g_return_val_if_fail (connection != NULL, FALSE); /* 802.1x stuff only happens in the supplicant's ASSOCIATED state when it's @@ -2105,7 +1767,7 @@ need_new_wpa_psk (NMDeviceWifi *self, g_assert (setting_name != NULL); - connection = nm_device_get_connection (NM_DEVICE (self)); + connection = nm_device_get_applied_connection (NM_DEVICE (self)); g_return_val_if_fail (connection != NULL, FALSE); /* A bad PSK will cause the supplicant to disconnect during the 4-way handshake */ @@ -2133,7 +1795,6 @@ handle_8021x_or_psk_auth_fail (NMDeviceWifi *self, { NMDevice *device = NM_DEVICE (self); NMActRequest *req; - NMConnection *connection; const char *setting_name = NULL; gboolean handled = FALSE; @@ -2142,13 +1803,10 @@ handle_8021x_or_psk_auth_fail (NMDeviceWifi *self, req = nm_device_get_act_request (NM_DEVICE (self)); g_return_val_if_fail (req != NULL, FALSE); - connection = nm_act_request_get_connection (req); - g_assert (connection); - if ( need_new_8021x_secrets (self, old_state, &setting_name) || need_new_wpa_psk (self, old_state, &setting_name)) { - nm_connection_clear_secrets (connection); + nm_act_request_clear_secrets (req); _LOGI (LOGD_DEVICE | LOGD_WIFI, "Activation: (wifi) disconnected during association, asking for new key"); @@ -2236,7 +1894,7 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, NMSettingWireless *s_wifi; GBytes *ssid; - connection = nm_device_get_connection (NM_DEVICE (self)); + connection = nm_device_get_applied_connection (NM_DEVICE (self)); g_return_if_fail (connection); s_wifi = nm_connection_get_setting_wireless (connection); @@ -2253,7 +1911,7 @@ supplicant_iface_state_cb (NMSupplicantInterface *iface, g_bytes_get_size (ssid)) : "(none)"); nm_device_activate_schedule_stage3_ip_config_start (device); } else if (devstate == NM_DEVICE_STATE_ACTIVATED) - periodic_update (self, NULL); + periodic_update (self); break; case NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED: if ((devstate == NM_DEVICE_STATE_ACTIVATED) || nm_device_is_activating (device)) { @@ -2359,7 +2017,53 @@ supplicant_iface_notify_scanning_cb (NMSupplicantInterface *iface, /* Run a quick update of current AP when coming out of a scan */ state = nm_device_get_state (NM_DEVICE (self)); if (!scanning && state == NM_DEVICE_STATE_ACTIVATED) - periodic_update (self, NULL); + periodic_update (self); +} + +static void +supplicant_iface_notify_current_bss (NMSupplicantInterface *iface, + GParamSpec *pspec, + NMDeviceWifi *self) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + const char *current_bss; + NMAccessPoint *new_ap = NULL; + + current_bss = nm_supplicant_interface_get_current_bss (iface); + if (current_bss) + new_ap = get_ap_by_supplicant_path (self, current_bss); + + if (new_ap != priv->current_ap) { + const char *new_bssid = NULL; + const GByteArray *new_ssid = NULL; + const char *old_bssid = NULL; + const GByteArray *old_ssid = NULL; + + /* Don't ever replace a "fake" current AP if we don't know about the + * supplicant's current BSS yet. It'll get replaced when we receive + * the current BSS's scan result. + */ + if (new_ap == NULL && nm_ap_get_fake (priv->current_ap)) + return; + + if (new_ap) { + new_bssid = nm_ap_get_address (new_ap); + new_ssid = nm_ap_get_ssid (new_ap); + } + + if (priv->current_ap) { + old_bssid = nm_ap_get_address (priv->current_ap); + old_ssid = nm_ap_get_ssid (priv->current_ap); + } + + _LOGD (LOGD_WIFI, "roamed from BSSID %s (%s) to %s (%s)", + old_bssid ? old_bssid : "(none)", + old_ssid ? nm_utils_escape_ssid (old_ssid->data, old_ssid->len) : "(none)", + new_bssid ? new_bssid : "(none)", + new_ssid ? nm_utils_escape_ssid (new_ssid->data, new_ssid->len) : "(none)"); + + set_current_ap (self, new_ap, TRUE); + } } static NMActStageReturn @@ -2369,7 +2073,7 @@ handle_auth_or_fail (NMDeviceWifi *self, { const char *setting_name; guint32 tries; - NMConnection *connection; + NMConnection *applied_connection; NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; g_return_val_if_fail (NM_IS_DEVICE_WIFI (self), NM_ACT_STAGE_RETURN_FAILURE); @@ -2379,17 +2083,16 @@ handle_auth_or_fail (NMDeviceWifi *self, g_assert (req); } - connection = nm_act_request_get_connection (req); - g_assert (connection); + applied_connection = nm_act_request_get_applied_connection (req); - tries = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES)); + tries = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (applied_connection), WIRELESS_SECRETS_TRIES)); if (tries > 3) return NM_ACT_STAGE_RETURN_FAILURE; nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_NEED_AUTH, NM_DEVICE_STATE_REASON_NONE); - nm_connection_clear_secrets (connection); - setting_name = nm_connection_need_secrets (connection, NULL); + nm_act_request_clear_secrets (req); + setting_name = nm_connection_need_secrets (applied_connection, NULL); if (setting_name) { NMSecretAgentGetSecretsFlags flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION; @@ -2397,7 +2100,7 @@ handle_auth_or_fail (NMDeviceWifi *self, flags |= NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW; nm_act_request_get_secrets (req, setting_name, flags, NULL, wifi_secrets_cb, self); - g_object_set_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES, GUINT_TO_POINTER (++tries)); + g_object_set_data (G_OBJECT (applied_connection), WIRELESS_SECRETS_TRIES, GUINT_TO_POINTER (++tries)); ret = NM_ACT_STAGE_RETURN_POSTPONE; } else _LOGW (LOGD_DEVICE, "Cleared secrets, but setting didn't need any secrets."); @@ -2434,7 +2137,7 @@ supplicant_connection_timeout_cb (gpointer user_data) req = nm_device_get_act_request (device); g_assert (req); - connection = nm_act_request_get_connection (req); + connection = nm_act_request_get_applied_connection (req); g_assert (connection); if ( priv->mode == NM_802_11_MODE_ADHOC @@ -2468,7 +2171,7 @@ supplicant_connection_timeout_cb (gpointer user_data) * dialogs, just retry or fail, and if we never connect the user can * fix the password somewhere else. */ - if (nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (connection), ×tamp)) + if (nm_settings_connection_get_timestamp (nm_act_request_get_settings_connection (req), ×tamp)) new_secrets = !timestamp; if (handle_auth_or_fail (self, req, new_secrets) == NM_ACT_STAGE_RETURN_POSTPONE) @@ -2491,12 +2194,16 @@ supplicant_connection_timeout_cb (gpointer user_data) static NMSupplicantConfig * build_supplicant_config (NMDeviceWifi *self, NMConnection *connection, - guint32 fixed_freq) + guint32 fixed_freq, + GError **error) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); NMSupplicantConfig *config = NULL; NMSettingWireless *s_wireless; NMSettingWirelessSecurity *s_wireless_sec; + NMSupplicantFeature mac_randomization_support; + NMSettingMacRandomization mac_randomization_fallback; + gs_free char *svalue = NULL; g_return_val_if_fail (self != NULL, NULL); @@ -2504,19 +2211,29 @@ build_supplicant_config (NMDeviceWifi *self, g_return_val_if_fail (s_wireless != NULL, NULL); config = nm_supplicant_config_new (); - if (!config) - return NULL; /* Warn if AP mode may not be supported */ if ( g_strcmp0 (nm_setting_wireless_get_mode (s_wireless), NM_SETTING_WIRELESS_MODE_AP) == 0 - && nm_supplicant_interface_get_ap_support (priv->sup_iface) == AP_SUPPORT_UNKNOWN) { + && nm_supplicant_interface_get_ap_support (priv->sup_iface) == NM_SUPPLICANT_FEATURE_UNKNOWN) { _LOGW (LOGD_WIFI, "Supplicant may not support AP mode; connection may time out."); } + mac_randomization_support = nm_supplicant_interface_get_mac_randomization_support (priv->sup_iface); + svalue = nm_config_data_get_connection_default (NM_CONFIG_GET_DATA, + "wifi." NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION, + NM_DEVICE (self)); + mac_randomization_fallback = _nm_utils_ascii_str_to_int64 (svalue, 10, + NM_SETTING_MAC_RANDOMIZATION_DEFAULT, + NM_SETTING_MAC_RANDOMIZATION_ALWAYS, + NM_SETTING_MAC_RANDOMIZATION_DEFAULT); + if (!nm_supplicant_config_add_setting_wireless (config, s_wireless, - fixed_freq)) { - _LOGE (LOGD_WIFI, "Couldn't add 802-11-wireless setting to supplicant config."); + fixed_freq, + mac_randomization_support, + mac_randomization_fallback, + error)) { + g_prefix_error (error, "802-11-wireless: "); goto error; } @@ -2533,13 +2250,14 @@ build_supplicant_config (NMDeviceWifi *self, s_wireless_sec, s_8021x, con_uuid, - mtu)) { - _LOGE (LOGD_WIFI, "Couldn't add 802-11-wireless-security setting to supplicant config."); + mtu, + error)) { + g_prefix_error (error, "802-11-wireless-security: "); goto error; } } else { - if (!nm_supplicant_config_add_no_security (config)) { - _LOGE (LOGD_WIFI, "Couldn't add unsecured option to supplicant config."); + if (!nm_supplicant_config_add_no_security (config, error)) { + g_prefix_error (error, "unsecured-option: "); goto error; } } @@ -2564,7 +2282,6 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) NMConnection *connection; NMSettingWireless *s_wireless; const char *cloned_mac; - GSList *iter; const char *mode; const char *ap_path; @@ -2575,7 +2292,7 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) req = nm_device_get_act_request (NM_DEVICE (self)); g_return_val_if_fail (req != NULL, NM_ACT_STAGE_RETURN_FAILURE); - connection = nm_act_request_get_connection (req); + connection = nm_act_request_get_applied_connection (req); g_return_val_if_fail (connection != NULL, NM_ACT_STAGE_RETURN_FAILURE); s_wireless = nm_connection_get_setting_wireless (connection); @@ -2611,25 +2328,17 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) /* AP mode never uses a specific object or existing scanned AP */ if (priv->mode != NM_802_11_MODE_AP) { - ap_path = nm_active_connection_get_specific_object (NM_ACTIVE_CONNECTION (req)); ap = ap_path ? get_ap_by_path (self, ap_path) : NULL; if (ap) goto done; - /* Find a compatible AP in the scan list */ - for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) { - NMAccessPoint *candidate = NM_AP (iter->data); - - if (nm_ap_check_compatible (candidate, connection)) { - ap = candidate; - break; - } - } + ap = find_first_compatible_ap (self, connection, FALSE); } if (ap) { - nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), nm_ap_get_dbus_path (ap)); + nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), + nm_exported_object_get_path (NM_EXPORTED_OBJECT (ap))); goto done; } @@ -2642,18 +2351,15 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) ap = nm_ap_new_fake_from_connection (connection); g_return_val_if_fail (ap != NULL, NM_ACT_STAGE_RETURN_FAILURE); - if (nm_ap_get_mode (ap) == NM_802_11_MODE_INFRA) - nm_ap_set_broadcast (ap, FALSE); - else if (nm_ap_is_hotspot (ap)) + if (nm_ap_is_hotspot (ap)) nm_ap_set_address (ap, nm_device_get_hw_address (device)); - priv->ap_list = g_slist_prepend (priv->ap_list, ap); - nm_ap_export_to_dbus (ap); g_object_freeze_notify (G_OBJECT (self)); - set_current_ap (self, ap, FALSE); - emit_ap_added_removed (self, ACCESS_POINT_ADDED, ap, TRUE); + ap_add_remove (self, ACCESS_POINT_ADDED, ap, TRUE); g_object_thaw_notify (G_OBJECT (self)); - nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), nm_ap_get_dbus_path (ap)); + set_current_ap (self, ap, FALSE); + nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), + nm_exported_object_get_path (NM_EXPORTED_OBJECT (ap))); return NM_ACT_STAGE_RETURN_SUCCESS; done: @@ -2699,6 +2405,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) NMConnection *connection; const char *setting_name; NMSettingWireless *s_wireless; + GError *error = NULL; g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); @@ -2713,7 +2420,7 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) goto out; } - connection = nm_act_request_get_connection (req); + connection = nm_act_request_get_applied_connection (req); g_assert (connection); s_wireless = nm_connection_get_setting_wireless (connection); @@ -2752,11 +2459,19 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) if ((nm_ap_get_mode (ap) == NM_802_11_MODE_ADHOC) || nm_ap_is_hotspot (ap)) ensure_hotspot_frequency (self, s_wireless, ap); + if (nm_ap_get_mode (ap) == NM_802_11_MODE_INFRA) { + nm_platform_wifi_set_powersave (NM_PLATFORM_GET, + nm_device_get_ifindex (device), + nm_setting_wireless_get_powersave (s_wireless)); + } + /* Build up the supplicant configuration */ - config = build_supplicant_config (self, connection, nm_ap_get_freq (ap)); + config = build_supplicant_config (self, connection, nm_ap_get_freq (ap), &error); if (config == NULL) { _LOGE (LOGD_DEVICE | LOGD_WIFI, - "Activation: (wifi) couldn't build wireless configuration."); + "Activation: (wifi) couldn't build wireless configuration: %s", + error ? error->message : "<BUG>"); + g_clear_error (&error); *reason = NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED; goto out; } @@ -2767,9 +2482,11 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) G_CALLBACK (supplicant_iface_connection_error_cb), self); - if (!nm_supplicant_interface_set_config (priv->sup_iface, config)) { + if (!nm_supplicant_interface_set_config (priv->sup_iface, config, &error)) { _LOGE (LOGD_DEVICE | LOGD_WIFI, - "Activation: (wifi) couldn't send wireless configuration to the supplicant."); + "Activation: (wifi) couldn't send wireless configuration to the supplicant: %s", + error ? error->message : "<BUG>"); + g_clear_error (&error); *reason = NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED; goto out; } @@ -2805,7 +2522,7 @@ act_stage3_ip4_config_start (NMDevice *device, NMSettingIPConfig *s_ip4; const char *method = NM_SETTING_IP4_CONFIG_METHOD_AUTO; - connection = nm_device_get_connection (device); + connection = nm_device_get_applied_connection (device); g_assert (connection); s_ip4 = nm_connection_get_setting_ip4_config (connection); if (s_ip4) @@ -2827,7 +2544,7 @@ act_stage3_ip6_config_start (NMDevice *device, NMSettingIPConfig *s_ip6; const char *method = NM_SETTING_IP6_CONFIG_METHOD_AUTO; - connection = nm_device_get_connection (device); + connection = nm_device_get_applied_connection (device); g_assert (connection); s_ip6 = nm_connection_get_setting_ip6_config (connection); if (s_ip6) @@ -2848,7 +2565,7 @@ ip4_config_pre_commit (NMDevice *device, NMIP4Config *config) NMSettingWireless *s_wifi; guint32 mtu; - connection = nm_device_get_connection (device); + connection = nm_device_get_applied_connection (device); g_assert (connection); s_wifi = nm_connection_get_setting_wireless (connection); g_assert (s_wifi); @@ -2935,7 +2652,7 @@ act_stage4_ip4_config_timeout (NMDevice *device, NMDeviceStateReason *reason) gboolean may_fail = FALSE, chain_up = FALSE; NMActStageReturn ret; - connection = nm_device_get_connection (device); + connection = nm_device_get_applied_connection (device); g_assert (connection); s_ip4 = nm_connection_get_setting_ip4_config (connection); @@ -2956,7 +2673,7 @@ act_stage4_ip6_config_timeout (NMDevice *device, NMDeviceStateReason *reason) gboolean may_fail = FALSE, chain_up = FALSE; NMActStageReturn ret; - connection = nm_device_get_connection (device); + connection = nm_device_get_applied_connection (device); g_assert (connection); s_ip6 = nm_connection_get_setting_ip6_config (connection); @@ -2975,78 +2692,53 @@ activation_success_handler (NMDevice *device) NMDeviceWifi *self = NM_DEVICE_WIFI (device); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); int ifindex = nm_device_get_ifindex (device); - NMAccessPoint *ap; - guint8 bssid[ETH_ALEN] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; - NMAccessPoint *tmp_ap = NULL; NMActRequest *req; - NMConnection *connection; + NMConnection *applied_connection; req = nm_device_get_act_request (device); g_assert (req); - connection = nm_act_request_get_connection (req); - g_assert (connection); + applied_connection = nm_act_request_get_applied_connection (req); /* Clear any critical protocol notification in the wifi stack */ nm_platform_wifi_indicate_addressing_running (NM_PLATFORM_GET, ifindex, FALSE); /* Clear wireless secrets tries on success */ - g_object_set_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES, NULL); - - ap = priv->current_ap; - - /* If the AP isn't fake, it was found in the scan list and all its - * details are known. - */ - if (!ap || !nm_ap_get_fake (ap)){ - ap = NULL; - goto done; - } + g_object_set_data (G_OBJECT (applied_connection), WIRELESS_SECRETS_TRIES, NULL); - /* If the activate AP was fake, it probably won't have a BSSID at all. - * But if activation was successful, the card will know the BSSID. Grab - * the BSSID off the card and fill in the BSSID of the activation AP. + /* There should always be a current AP, either a fake one because we haven't + * seen a scan result for the activated AP yet, or a real one from the + * supplicant's scan list. */ - nm_platform_wifi_get_bssid (NM_PLATFORM_GET, ifindex, bssid); - if (!nm_ap_get_address (ap)) { - char *bssid_str = nm_utils_hwaddr_ntoa (bssid, ETH_ALEN); - nm_ap_set_address (ap, bssid_str); - g_free (bssid_str); - } - if (!nm_ap_get_freq (ap)) - nm_ap_set_freq (ap, nm_platform_wifi_get_frequency (NM_PLATFORM_GET, ifindex)); - if (!nm_ap_get_max_bitrate (ap)) - nm_ap_set_max_bitrate (ap, nm_platform_wifi_get_rate (NM_PLATFORM_GET, ifindex)); - - tmp_ap = find_active_ap (self, ap, TRUE); - if (tmp_ap) { - const GByteArray *ssid = nm_ap_get_ssid (tmp_ap); - - /* Found a better match in the scan list than the fake AP. Use it - * instead. - */ - - /* If the better match was a hidden AP, update its SSID */ - if (!ssid || nm_utils_is_empty_ssid (ssid->data, ssid->len)) { - ssid = nm_ap_get_ssid (ap); - nm_ap_set_ssid (tmp_ap, ssid->data, ssid->len); + g_warn_if_fail (priv->current_ap); + if (priv->current_ap) { + if (nm_ap_get_fake (priv->current_ap)) { + /* If the activation AP hasn't been seen by the supplicant in a scan + * yet, it will be "fake". This usually happens for Ad-Hoc and + * AP-mode connections. Fill in the details from the device itself + * until the supplicant sends the scan result. + */ + if (!nm_ap_get_address (priv->current_ap)) { + guint8 bssid[ETH_ALEN] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; + gs_free char *bssid_str = NULL; + + if ( nm_platform_wifi_get_bssid (NM_PLATFORM_GET, ifindex, bssid) + && nm_ethernet_address_is_valid (bssid, ETH_ALEN)) { + bssid_str = nm_utils_hwaddr_ntoa (bssid, ETH_ALEN); + nm_ap_set_address (priv->current_ap, bssid_str); + } + } + if (!nm_ap_get_freq (priv->current_ap)) + nm_ap_set_freq (priv->current_ap, nm_platform_wifi_get_frequency (NM_PLATFORM_GET, ifindex)); + if (!nm_ap_get_max_bitrate (priv->current_ap)) + nm_ap_set_max_bitrate (priv->current_ap, nm_platform_wifi_get_rate (NM_PLATFORM_GET, ifindex)); } nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req), - nm_ap_get_dbus_path (tmp_ap)); + nm_exported_object_get_path (NM_EXPORTED_OBJECT (priv->current_ap))); } -done: - periodic_update (self, ap); - - /* ap might be already unrefed, because it was a fake_ap. But we don't touch it... */ - if (tmp_ap && ap == priv->current_ap) { - /* Strange, we would expect periodic_update() to find a better AP - * then the fake one and reset it. Reset the fake current_ap to NULL - * now, which will remove the fake ap. - **/ - set_current_ap (self, NULL, TRUE); - } + periodic_update (self); update_seen_bssids_cache (self, priv->current_ap); @@ -3057,13 +2749,13 @@ done: static void activation_failure_handler (NMDevice *device) { - NMConnection *connection; + NMConnection *applied_connection; - connection = nm_device_get_connection (device); - g_assert (connection); + applied_connection = nm_device_get_applied_connection (device); + g_assert (applied_connection); /* Clear wireless secrets tries on failure */ - g_object_set_data (G_OBJECT (connection), WIRELESS_SECRETS_TRIES, NULL); + g_object_set_data (G_OBJECT (applied_connection), WIRELESS_SECRETS_TRIES, NULL); /* Clear any critical protocol notification in the wifi stack */ nm_platform_wifi_indicate_addressing_running (NM_PLATFORM_GET, nm_device_get_ifindex (device), FALSE); @@ -3086,10 +2778,7 @@ device_state_changed (NMDevice *device, if (priv->sup_iface) supplicant_interface_release (self); - if (priv->periodic_source_id) { - g_source_remove (priv->periodic_source_id); - priv->periodic_source_id = 0; - } + nm_clear_g_source (&priv->periodic_source_id); cleanup_association_attempt (self, TRUE); cleanup_supplicant_failures (self); @@ -3196,22 +2885,25 @@ set_enabled (NMDevice *device, gboolean enabled) /********************************************************************/ NMDevice * -nm_device_wifi_new (NMPlatformLink *platform_device) +nm_device_wifi_new (const char *iface, NMDeviceWifiCapabilities capabilities) { - g_return_val_if_fail (platform_device != NULL, NULL); - - return (NMDevice *) g_object_new (NM_TYPE_DEVICE_WIFI, - NM_DEVICE_PLATFORM_DEVICE, platform_device, - NM_DEVICE_TYPE_DESC, "802.11 WiFi", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_WIFI, - NM_DEVICE_RFKILL_TYPE, RFKILL_TYPE_WLAN, - NULL); + return g_object_new (NM_TYPE_DEVICE_WIFI, + NM_DEVICE_IFACE, iface, + NM_DEVICE_TYPE_DESC, "802.11 WiFi", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_WIFI, + NM_DEVICE_LINK_TYPE, NM_LINK_TYPE_WIFI, + NM_DEVICE_RFKILL_TYPE, RFKILL_TYPE_WLAN, + NM_DEVICE_WIFI_CAPABILITIES, (guint) capabilities, + NULL); } static void nm_device_wifi_init (NMDeviceWifi *self) { - NM_DEVICE_WIFI_GET_PRIVATE (self)->mode = NM_802_11_MODE_INFRA; + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + priv->mode = NM_802_11_MODE_INFRA; + priv->aps = g_hash_table_new (g_str_hash, g_str_equal); } static void @@ -3220,17 +2912,7 @@ dispose (GObject *object) NMDeviceWifi *self = NM_DEVICE_WIFI (object); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - if (priv->disposed) { - G_OBJECT_CLASS (nm_device_wifi_parent_class)->dispose (object); - return; - } - - priv->disposed = TRUE; - - if (priv->periodic_source_id) { - g_source_remove (priv->periodic_source_id); - priv->periodic_source_id = 0; - } + nm_clear_g_source (&priv->periodic_source_id); cleanup_association_attempt (self, TRUE); supplicant_interface_release (self); @@ -3246,6 +2928,13 @@ dispose (GObject *object) static void finalize (GObject *object) { + NMDeviceWifi *self = NM_DEVICE_WIFI (object); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + + nm_assert (g_hash_table_size (priv->aps) == 0); + + g_hash_table_unref (priv->aps); + G_OBJECT_CLASS (nm_device_wifi_parent_class)->finalize (object); } @@ -3255,8 +2944,9 @@ get_property (GObject *object, guint prop_id, { NMDeviceWifi *device = NM_DEVICE_WIFI (object); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device); + GHashTableIter iter; + const char *dbus_path; GPtrArray *array; - GSList *iter; switch (prop_id) { case PROP_PERM_HW_ADDRESS: @@ -3272,16 +2962,15 @@ get_property (GObject *object, guint prop_id, g_value_set_uint (value, priv->capabilities); break; case PROP_ACCESS_POINTS: - array = g_ptr_array_sized_new (4); - for (iter = priv->ap_list; iter; iter = g_slist_next (iter)) - g_ptr_array_add (array, g_strdup (nm_ap_get_dbus_path (NM_AP (iter->data)))); - g_value_take_boxed (value, array); + array = g_ptr_array_sized_new (g_hash_table_size (priv->aps) + 1); + g_hash_table_iter_init (&iter, priv->aps); + while (g_hash_table_iter_next (&iter, (gpointer) &dbus_path, NULL)) + g_ptr_array_add (array, g_strdup (dbus_path)); + g_ptr_array_add (array, NULL); + g_value_take_boxed (value, (char **) g_ptr_array_free (array, FALSE)); break; case PROP_ACTIVE_ACCESS_POINT: - if (priv->current_ap) - g_value_set_boxed (value, nm_ap_get_dbus_path (priv->current_ap)); - else - g_value_set_boxed (value, "/"); + nm_utils_g_value_set_object_path (value, priv->current_ap); break; case PROP_SCANNING: g_value_set_boolean (value, nm_supplicant_interface_get_scanning (priv->sup_iface)); @@ -3296,7 +2985,14 @@ static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { + NMDeviceWifi *device = NM_DEVICE_WIFI (object); + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (device); + switch (prop_id) { + case PROP_CAPABILITIES: + /* construct-only */ + priv->capabilities = g_value_get_uint (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -3312,12 +3008,15 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) g_type_class_add_private (object_class, sizeof (NMDeviceWifiPrivate)); - object_class->constructor = constructor; + NM_DEVICE_CLASS_DECLARE_TYPES (klass, NM_SETTING_WIRELESS_SETTING_NAME, NM_LINK_TYPE_WIFI) + + object_class->constructed = constructed; object_class->get_property = get_property; object_class->set_property = set_property; object_class->dispose = dispose; object_class->finalize = finalize; + parent_class->realize_start_notify = realize_start_notify; parent_class->bring_up = bring_up; parent_class->can_auto_connect = can_auto_connect; parent_class->is_available = is_available; @@ -3366,22 +3065,23 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) g_object_class_install_property (object_class, PROP_ACCESS_POINTS, g_param_spec_boxed (NM_DEVICE_WIFI_ACCESS_POINTS, "", "", - DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, + G_TYPE_STRV, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_ACTIVE_ACCESS_POINT, - g_param_spec_boxed (NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT, "", "", - DBUS_TYPE_G_OBJECT_PATH, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + g_param_spec_string (NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT, "", "", + NULL, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_CAPABILITIES, g_param_spec_uint (NM_DEVICE_WIFI_CAPABILITIES, "", "", 0, G_MAXUINT32, NM_WIFI_DEVICE_CAP_NONE, - G_PARAM_READABLE | + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); g_object_class_install_property @@ -3399,7 +3099,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) G_STRUCT_OFFSET (NMDeviceWifiClass, access_point_added), NULL, NULL, NULL, G_TYPE_NONE, 1, - G_TYPE_OBJECT); + NM_TYPE_AP); signals[ACCESS_POINT_REMOVED] = g_signal_new ("access-point-removed", @@ -3408,7 +3108,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) 0, NULL, NULL, NULL, G_TYPE_NONE, 1, - G_TYPE_OBJECT); + NM_TYPE_AP); signals[SCANNING_ALLOWED] = g_signal_new ("scanning-allowed", @@ -3418,9 +3118,12 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) scanning_allowed_accumulator, NULL, NULL, G_TYPE_BOOLEAN, 0); - nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), - G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_wifi_object_info); + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (klass), + NMDBUS_TYPE_DEVICE_WIFI_SKELETON, + "GetAccessPoints", impl_device_wifi_get_access_points, + "GetAllAccessPoints", impl_device_wifi_get_all_access_points, + "RequestScan", impl_device_wifi_request_scan, + NULL); } diff --git a/src/devices/wifi/nm-device-wifi.h b/src/devices/wifi/nm-device-wifi.h index bcba91da..7e0d06f5 100644 --- a/src/devices/wifi/nm-device-wifi.h +++ b/src/devices/wifi/nm-device-wifi.h @@ -22,8 +22,6 @@ #ifndef __NETWORKMANAGER_DEVICE_WIFI_H__ #define __NETWORKMANAGER_DEVICE_WIFI_H__ -#include <glib-object.h> - #include "nm-device.h" #include "nm-wifi-ap.h" @@ -75,7 +73,7 @@ struct _NMDeviceWifiClass GType nm_device_wifi_get_type (void); -NMDevice *nm_device_wifi_new (NMPlatformLink *platform_device); +NMDevice * nm_device_wifi_new (const char *iface, NMDeviceWifiCapabilities capabilities); G_END_DECLS diff --git a/src/devices/wifi/nm-wifi-ap-utils.c b/src/devices/wifi/nm-wifi-ap-utils.c index 1a772fb7..d7916aa0 100644 --- a/src/devices/wifi/nm-wifi-ap-utils.c +++ b/src/devices/wifi/nm-wifi-ap-utils.c @@ -23,8 +23,7 @@ #include <string.h> #include <stdlib.h> -#include <glib/gi18n.h> - +#include "nm-default.h" #include "nm-wifi-ap-utils.h" #include "nm-utils.h" diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c index 72430021..771d6704 100644 --- a/src/devices/wifi/nm-wifi-ap.c +++ b/src/devices/wifi/nm-wifi-ap.c @@ -24,32 +24,29 @@ #include <string.h> #include <stdlib.h> +#include "nm-default.h" #include "nm-wifi-ap.h" #include "nm-wifi-ap-utils.h" #include "NetworkManagerUtils.h" #include "nm-utils.h" -#include "nm-logging.h" -#include "nm-dbus-manager.h" #include "nm-core-internal.h" #include "nm-setting-wireless.h" -#include "nm-glib-compat.h" -#include "nm-access-point-glue.h" +#include "nmdbus-access-point.h" /* * Encapsulates Access Point information */ typedef struct { - char *dbus_path; char *supplicant_path; /* D-Bus object path of this AP from wpa_supplicant */ /* Scanned or cached values */ GByteArray * ssid; char * address; NM80211Mode mode; - gint8 strength; + guint8 strength; guint32 freq; /* Frequency in MHz; ie 2412 (== 2.412 GHz) */ guint32 max_bitrate;/* Maximum bitrate of the AP in Kbit/s (ie 54000 Kb/s == 54Mbit/s) */ @@ -60,13 +57,12 @@ typedef struct /* Non-scanned attributes */ gboolean fake; /* Whether or not the AP is from a scan */ gboolean hotspot; /* Whether the AP is a local device's hotspot network */ - gboolean broadcast; /* Whether or not the AP is broadcasting (hidden) */ gint32 last_seen; /* Timestamp when the AP was seen lastly (obtained via nm_utils_get_monotonic_timestamp_s()) */ } NMAccessPointPrivate; #define NM_AP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_AP, NMAccessPointPrivate)) -G_DEFINE_TYPE (NMAccessPoint, nm_ap, G_TYPE_OBJECT) +G_DEFINE_TYPE (NMAccessPoint, nm_ap, NM_TYPE_EXPORTED_OBJECT) enum { PROP_0, @@ -83,267 +79,267 @@ enum { LAST_PROP }; -static void -nm_ap_init (NMAccessPoint *ap) +/*****************************************************************/ + +const char * +nm_ap_get_supplicant_path (NMAccessPoint *ap) { - NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (ap); + g_return_val_if_fail (NM_IS_AP (ap), NULL); - priv->dbus_path = NULL; - priv->mode = NM_802_11_MODE_INFRA; - priv->flags = NM_802_11_AP_FLAGS_NONE; - priv->wpa_flags = NM_802_11_AP_SEC_NONE; - priv->rsn_flags = NM_802_11_AP_SEC_NONE; - priv->broadcast = TRUE; + return NM_AP_GET_PRIVATE (ap)->supplicant_path; } -static void -finalize (GObject *object) +guint32 +nm_ap_get_id (NMAccessPoint *ap) { - NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (object); + g_return_val_if_fail (NM_IS_AP (ap), 0); + g_return_val_if_fail (nm_exported_object_is_exported (NM_EXPORTED_OBJECT (ap)), 0); - g_free (priv->dbus_path); - g_free (priv->supplicant_path); - if (priv->ssid) + return atoi (strrchr (nm_exported_object_get_path (NM_EXPORTED_OBJECT (ap)), '/') + 1); +} + +const GByteArray * nm_ap_get_ssid (const NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_AP (ap), NULL); + + return NM_AP_GET_PRIVATE (ap)->ssid; +} + +void +nm_ap_set_ssid (NMAccessPoint *ap, const guint8 *ssid, gsize len) +{ + NMAccessPointPrivate *priv; + + g_return_if_fail (NM_IS_AP (ap)); + g_return_if_fail (ssid == NULL || len > 0); + + priv = NM_AP_GET_PRIVATE (ap); + + /* same SSID */ + if ((ssid && priv->ssid) && (len == priv->ssid->len)) { + if (!memcmp (ssid, priv->ssid->data, len)) + return; + } + + if (priv->ssid) { g_byte_array_free (priv->ssid, TRUE); - g_free (priv->address); + priv->ssid = NULL; + } - G_OBJECT_CLASS (nm_ap_parent_class)->finalize (object); + if (ssid) { + priv->ssid = g_byte_array_new (); + g_byte_array_append (priv->ssid, ssid, len); + } + + g_object_notify (G_OBJECT (ap), NM_AP_SSID); } static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) +nm_ap_set_flags (NMAccessPoint *ap, NM80211ApFlags flags) { - NMAccessPoint *ap = NM_AP (object); - GByteArray *ssid; + NMAccessPointPrivate *priv; - switch (prop_id) { - case PROP_FLAGS: - nm_ap_set_flags (ap, g_value_get_uint (value)); - break; - case PROP_WPA_FLAGS: - nm_ap_set_wpa_flags (ap, g_value_get_uint (value)); - break; - case PROP_RSN_FLAGS: - nm_ap_set_rsn_flags (ap, g_value_get_uint (value)); - break; - case PROP_SSID: - ssid = g_value_get_boxed (value); - if (ssid) - nm_ap_set_ssid (ap, ssid->data, ssid->len); - else - nm_ap_set_ssid (ap, NULL, 0); - break; - case PROP_FREQUENCY: - nm_ap_set_freq (ap, g_value_get_uint (value)); - break; - case PROP_MODE: - nm_ap_set_mode (ap, g_value_get_uint (value)); - break; - case PROP_MAX_BITRATE: - nm_ap_set_max_bitrate (ap, g_value_get_uint (value)); - break; - case PROP_STRENGTH: - nm_ap_set_strength (ap, g_value_get_schar (value)); - break; - case PROP_HW_ADDRESS: - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; + g_return_if_fail (NM_IS_AP (ap)); + + priv = NM_AP_GET_PRIVATE (ap); + + if (priv->flags != flags) { + priv->flags = flags; + g_object_notify (G_OBJECT (ap), NM_AP_FLAGS); } } static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) +nm_ap_set_wpa_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags) { - NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (object); - GArray * ssid; - int len; - int i; + NMAccessPointPrivate *priv; - switch (prop_id) { - case PROP_FLAGS: - g_value_set_uint (value, priv->flags); - break; - case PROP_WPA_FLAGS: - g_value_set_uint (value, priv->wpa_flags); - break; - case PROP_RSN_FLAGS: - g_value_set_uint (value, priv->rsn_flags); - break; - case PROP_SSID: - len = priv->ssid ? priv->ssid->len : 0; - ssid = g_array_sized_new (FALSE, TRUE, sizeof (unsigned char), len); - for (i = 0; i < len; i++) - g_array_append_val (ssid, priv->ssid->data[i]); - g_value_set_boxed (value, ssid); - g_array_free (ssid, TRUE); - break; - case PROP_FREQUENCY: - g_value_set_uint (value, priv->freq); - break; - case PROP_HW_ADDRESS: - g_value_set_string (value, priv->address); - break; - case PROP_MODE: - g_value_set_uint (value, priv->mode); - break; - case PROP_MAX_BITRATE: - g_value_set_uint (value, priv->max_bitrate); - break; - case PROP_STRENGTH: - g_value_set_schar (value, priv->strength); - break; - case PROP_LAST_SEEN: - g_value_set_int (value, - priv->last_seen > 0 - ? (gint) nm_utils_monotonic_timestamp_as_boottime (priv->last_seen, NM_UTILS_NS_PER_SECOND) - : -1); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; + g_return_if_fail (NM_IS_AP (ap)); + + priv = NM_AP_GET_PRIVATE (ap); + if (priv->wpa_flags != flags) { + priv->wpa_flags = flags; + g_object_notify (G_OBJECT (ap), NM_AP_WPA_FLAGS); } } static void -nm_ap_class_init (NMAccessPointClass *ap_class) +nm_ap_set_rsn_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags) { - GObjectClass *object_class = G_OBJECT_CLASS (ap_class); - const NM80211ApSecurityFlags all_sec_flags = NM_802_11_AP_SEC_NONE - | NM_802_11_AP_SEC_PAIR_WEP40 - | NM_802_11_AP_SEC_PAIR_WEP104 - | NM_802_11_AP_SEC_PAIR_TKIP - | NM_802_11_AP_SEC_PAIR_CCMP - | NM_802_11_AP_SEC_GROUP_WEP40 - | NM_802_11_AP_SEC_GROUP_WEP104 - | NM_802_11_AP_SEC_GROUP_TKIP - | NM_802_11_AP_SEC_GROUP_CCMP - | NM_802_11_AP_SEC_KEY_MGMT_PSK - | NM_802_11_AP_SEC_KEY_MGMT_802_1X; + NMAccessPointPrivate *priv; - g_type_class_add_private (ap_class, sizeof (NMAccessPointPrivate)); + g_return_if_fail (NM_IS_AP (ap)); - /* virtual methods */ - object_class->set_property = set_property; - object_class->get_property = get_property; - object_class->finalize = finalize; + priv = NM_AP_GET_PRIVATE (ap); + if (priv->rsn_flags != flags) { + priv->rsn_flags = flags; + g_object_notify (G_OBJECT (ap), NM_AP_RSN_FLAGS); + } +} - /* properties */ - g_object_class_install_property - (object_class, PROP_FLAGS, - g_param_spec_uint (NM_AP_FLAGS, "", "", - NM_802_11_AP_FLAGS_NONE, - NM_802_11_AP_FLAGS_PRIVACY, - NM_802_11_AP_FLAGS_NONE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); +const char * +nm_ap_get_address (const NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_AP (ap), NULL); - g_object_class_install_property - (object_class, PROP_WPA_FLAGS, - g_param_spec_uint (NM_AP_WPA_FLAGS, "", "", - NM_802_11_AP_SEC_NONE, - all_sec_flags, - NM_802_11_AP_SEC_NONE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); + return NM_AP_GET_PRIVATE (ap)->address; +} - g_object_class_install_property - (object_class, PROP_RSN_FLAGS, - g_param_spec_uint (NM_AP_RSN_FLAGS, "", "", - NM_802_11_AP_SEC_NONE, - all_sec_flags, - NM_802_11_AP_SEC_NONE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); +void +nm_ap_set_address (NMAccessPoint *ap, const char *addr) +{ + NMAccessPointPrivate *priv; - g_object_class_install_property - (object_class, PROP_SSID, - g_param_spec_boxed (NM_AP_SSID, "", "", - DBUS_TYPE_G_UCHAR_ARRAY, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); + g_return_if_fail (NM_IS_AP (ap)); + g_return_if_fail (addr != NULL); + g_return_if_fail (nm_utils_hwaddr_valid (addr, ETH_ALEN)); - g_object_class_install_property - (object_class, PROP_FREQUENCY, - g_param_spec_uint (NM_AP_FREQUENCY, "", "", - 0, 10000, 0, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); + priv = NM_AP_GET_PRIVATE (ap); - g_object_class_install_property - (object_class, PROP_HW_ADDRESS, - g_param_spec_string (NM_AP_HW_ADDRESS, "", "", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_MODE, - g_param_spec_uint (NM_AP_MODE, "", "", - NM_802_11_MODE_ADHOC, NM_802_11_MODE_INFRA, NM_802_11_MODE_INFRA, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); + if (!priv->address || !nm_utils_hwaddr_matches (addr, -1, priv->address, -1)) { + g_free (priv->address); + priv->address = g_strdup (addr); + g_object_notify (G_OBJECT (ap), NM_AP_HW_ADDRESS); + } +} - g_object_class_install_property - (object_class, PROP_MAX_BITRATE, - g_param_spec_uint (NM_AP_MAX_BITRATE, "", "", - 0, G_MAXUINT16, 0, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); +NM80211Mode +nm_ap_get_mode (NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_AP (ap), NM_802_11_MODE_UNKNOWN); - g_object_class_install_property - (object_class, PROP_STRENGTH, - g_param_spec_char (NM_AP_STRENGTH, "", "", - G_MININT8, G_MAXINT8, 0, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); + return NM_AP_GET_PRIVATE (ap)->mode; +} - g_object_class_install_property - (object_class, PROP_LAST_SEEN, - g_param_spec_int (NM_AP_LAST_SEEN, "", "", - -1, G_MAXINT, -1, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), - G_TYPE_FROM_CLASS (ap_class), - &dbus_glib_nm_access_point_object_info); +static void +nm_ap_set_mode (NMAccessPoint *ap, const NM80211Mode mode) +{ + NMAccessPointPrivate *priv; + + g_return_if_fail (NM_IS_AP (ap)); + g_return_if_fail ( mode == NM_802_11_MODE_ADHOC + || mode == NM_802_11_MODE_INFRA); + + priv = NM_AP_GET_PRIVATE (ap); + + if (priv->mode != mode) { + priv->mode = mode; + g_object_notify (G_OBJECT (ap), NM_AP_MODE); + } +} + +gboolean +nm_ap_is_hotspot (NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_AP (ap), FALSE); + + return NM_AP_GET_PRIVATE (ap)->hotspot; +} + +gint8 +nm_ap_get_strength (NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_AP (ap), 0); + + return NM_AP_GET_PRIVATE (ap)->strength; } void -nm_ap_export_to_dbus (NMAccessPoint *ap) +nm_ap_set_strength (NMAccessPoint *ap, const gint8 strength) { NMAccessPointPrivate *priv; - static guint32 counter = 0; g_return_if_fail (NM_IS_AP (ap)); priv = NM_AP_GET_PRIVATE (ap); - if (priv->dbus_path) { - nm_log_err (LOGD_CORE, "Tried to export AP %s twice.", priv->dbus_path); - return; + if (priv->strength != strength) { + priv->strength = strength; + g_object_notify (G_OBJECT (ap), NM_AP_STRENGTH); } +} + +guint32 +nm_ap_get_freq (NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_AP (ap), 0); - priv->dbus_path = g_strdup_printf (NM_DBUS_PATH_ACCESS_POINT "/%d", counter++); - nm_dbus_manager_register_object (nm_dbus_manager_get (), priv->dbus_path, ap); + return NM_AP_GET_PRIVATE (ap)->freq; } -/* - * nm_ap_new - * - * Create a new, blank user access point info structure - * - */ -static NMAccessPoint * -nm_ap_new (void) +void +nm_ap_set_freq (NMAccessPoint *ap, + const guint32 freq) +{ + NMAccessPointPrivate *priv; + + g_return_if_fail (NM_IS_AP (ap)); + + priv = NM_AP_GET_PRIVATE (ap); + + if (priv->freq != freq) { + priv->freq = freq; + g_object_notify (G_OBJECT (ap), NM_AP_FREQUENCY); + } +} + +guint32 +nm_ap_get_max_bitrate (NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_AP (ap), 0); + g_return_val_if_fail (nm_exported_object_is_exported (NM_EXPORTED_OBJECT (ap)), 0); + + return NM_AP_GET_PRIVATE (ap)->max_bitrate; +} + +void +nm_ap_set_max_bitrate (NMAccessPoint *ap, guint32 bitrate) +{ + NMAccessPointPrivate *priv; + + g_return_if_fail (NM_IS_AP (ap)); + + priv = NM_AP_GET_PRIVATE (ap); + + if (priv->max_bitrate != bitrate) { + priv->max_bitrate = bitrate; + g_object_notify (G_OBJECT (ap), NM_AP_MAX_BITRATE); + } +} + +gboolean +nm_ap_get_fake (const NMAccessPoint *ap) +{ + g_return_val_if_fail (NM_IS_AP (ap), FALSE); + + return NM_AP_GET_PRIVATE (ap)->fake; +} + +void +nm_ap_set_fake (NMAccessPoint *ap, gboolean fake) { - return (NMAccessPoint *) g_object_new (NM_TYPE_AP, NULL); + g_return_if_fail (NM_IS_AP (ap)); + + NM_AP_GET_PRIVATE (ap)->fake = fake; } +static void +nm_ap_set_last_seen (NMAccessPoint *ap, gint32 last_seen) +{ + NMAccessPointPrivate *priv; + + g_return_if_fail (NM_IS_AP (ap)); + + priv = NM_AP_GET_PRIVATE (ap); + + if (priv->last_seen != last_seen) { + priv->last_seen = last_seen; + g_object_notify (G_OBJECT (ap), NM_AP_LAST_SEEN); + } +} + +/*****************************************************************/ + static NM80211ApSecurityFlags security_from_vardict (GVariant *security) { @@ -382,14 +378,14 @@ security_from_vardict (GVariant *security) return flags; } -NMAccessPoint * -nm_ap_new_from_properties (const char *supplicant_path, GVariant *properties) +void +nm_ap_update_from_properties (NMAccessPoint *ap, + const char *supplicant_path, + GVariant *properties) { - const char bad_bssid1[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - const char bad_bssid2[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - const char *addr; + NMAccessPointPrivate *priv; + char *addr; const guint8 *bytes; - NMAccessPoint *ap; GVariant *v; gsize len; gboolean b = FALSE; @@ -397,14 +393,14 @@ nm_ap_new_from_properties (const char *supplicant_path, GVariant *properties) gint16 i16; guint16 u16; - g_return_val_if_fail (properties != NULL, NULL); - - ap = nm_ap_new (); + g_return_if_fail (ap != NULL); + g_return_if_fail (properties != NULL); + priv = NM_AP_GET_PRIVATE (ap); g_object_freeze_notify (G_OBJECT (ap)); if (g_variant_lookup (properties, "Privacy", "b", &b) && b) - nm_ap_set_flags (ap, nm_ap_get_flags (ap) | NM_802_11_AP_FLAGS_PRIVACY); + nm_ap_set_flags (ap, priv->flags | NM_802_11_AP_FLAGS_PRIVACY); if (g_variant_lookup (properties, "Mode", "&s", &s)) { if (!g_strcmp0 (s, "infrastructure")) @@ -437,11 +433,9 @@ nm_ap_new_from_properties (const char *supplicant_path, GVariant *properties) if (v) { bytes = g_variant_get_fixed_array (v, &len, 1); if (len == ETH_ALEN) { - char *a; - - a = nm_utils_hwaddr_ntoa (bytes, len); - nm_ap_set_address (ap, a); - g_free (a); + addr = nm_utils_hwaddr_ntoa (bytes, len); + nm_ap_set_address (ap, addr); + g_free (addr); } g_variant_unref (v); } @@ -464,17 +458,38 @@ nm_ap_new_from_properties (const char *supplicant_path, GVariant *properties) v = g_variant_lookup_value (properties, "WPA", G_VARIANT_TYPE_VARDICT); if (v) { - nm_ap_set_wpa_flags (ap, nm_ap_get_wpa_flags (ap) | security_from_vardict (v)); + nm_ap_set_wpa_flags (ap, priv->wpa_flags | security_from_vardict (v)); g_variant_unref (v); } v = g_variant_lookup_value (properties, "RSN", G_VARIANT_TYPE_VARDICT); if (v) { - nm_ap_set_rsn_flags (ap, nm_ap_get_rsn_flags (ap) | security_from_vardict (v)); + nm_ap_set_rsn_flags (ap, priv->rsn_flags | security_from_vardict (v)); g_variant_unref (v); } - nm_ap_set_supplicant_path (ap, supplicant_path); + if (!priv->supplicant_path) + priv->supplicant_path = g_strdup (supplicant_path); + + nm_ap_set_last_seen (ap, nm_utils_get_monotonic_timestamp_s ()); + priv->fake = FALSE; + + g_object_thaw_notify (G_OBJECT (ap)); +} + +NMAccessPoint * +nm_ap_new_from_properties (const char *supplicant_path, GVariant *properties) +{ + const char bad_bssid1[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + const char bad_bssid2[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + NMAccessPoint *ap; + const char *addr; + + g_return_val_if_fail (supplicant_path != NULL, NULL); + g_return_val_if_fail (properties != NULL, NULL); + + ap = (NMAccessPoint *) g_object_new (NM_TYPE_AP, NULL); + nm_ap_update_from_properties (ap, supplicant_path, properties); /* ignore APs with invalid or missing BSSIDs */ addr = nm_ap_get_address (ap); @@ -485,13 +500,6 @@ nm_ap_new_from_properties (const char *supplicant_path, GVariant *properties) return NULL; } - nm_ap_set_last_seen (ap, nm_utils_get_monotonic_timestamp_s ()); - - if (!nm_ap_get_ssid (ap)) - nm_ap_set_broadcast (ap, FALSE); - - g_object_thaw_notify (G_OBJECT (ap)); - return ap; } @@ -517,6 +525,7 @@ has_proto (NMSettingWirelessSecurity *sec, const char *proto) static void add_pair_ciphers (NMAccessPoint *ap, NMSettingWirelessSecurity *sec) { + NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (ap); guint32 num = nm_setting_wireless_security_get_num_pairwise (sec); NM80211ApSecurityFlags flags = NM_802_11_AP_SEC_NONE; guint32 i; @@ -536,14 +545,15 @@ add_pair_ciphers (NMAccessPoint *ap, NMSettingWirelessSecurity *sec) } if (has_proto (sec, PROTO_WPA)) - nm_ap_set_wpa_flags (ap, nm_ap_get_wpa_flags (ap) | flags); + nm_ap_set_wpa_flags (ap, priv->wpa_flags | flags); if (has_proto (sec, PROTO_RSN)) - nm_ap_set_rsn_flags (ap, nm_ap_get_rsn_flags (ap) | flags); + nm_ap_set_rsn_flags (ap, priv->rsn_flags | flags); } static void add_group_ciphers (NMAccessPoint *ap, NMSettingWirelessSecurity *sec) { + NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (ap); guint32 num = nm_setting_wireless_security_get_num_groups (sec); NM80211ApSecurityFlags flags = NM_802_11_AP_SEC_NONE; guint32 i; @@ -567,15 +577,16 @@ add_group_ciphers (NMAccessPoint *ap, NMSettingWirelessSecurity *sec) } if (has_proto (sec, PROTO_WPA)) - nm_ap_set_wpa_flags (ap, nm_ap_get_wpa_flags (ap) | flags); + nm_ap_set_wpa_flags (ap, priv->wpa_flags | flags); if (has_proto (sec, PROTO_RSN)) - nm_ap_set_rsn_flags (ap, nm_ap_get_rsn_flags (ap) | flags); + nm_ap_set_rsn_flags (ap, priv->rsn_flags | flags); } NMAccessPoint * nm_ap_new_fake_from_connection (NMConnection *connection) { NMAccessPoint *ap; + NMAccessPointPrivate *priv; NMSettingWireless *s_wireless; NMSettingWirelessSecurity *s_wireless_sec; GBytes *ssid; @@ -593,8 +604,9 @@ nm_ap_new_fake_from_connection (NMConnection *connection) g_return_val_if_fail (ssid != NULL, NULL); g_return_val_if_fail (g_bytes_get_size (ssid) > 0, NULL); - ap = nm_ap_new (); - nm_ap_set_fake (ap, TRUE); + ap = (NMAccessPoint *) g_object_new (NM_TYPE_AP, NULL); + priv = NM_AP_GET_PRIVATE (ap); + priv->fake = TRUE; nm_ap_set_ssid (ap, g_bytes_get_data (ssid, NULL), g_bytes_get_size (ssid)); // FIXME: bssid too? @@ -634,7 +646,7 @@ nm_ap_new_fake_from_connection (NMConnection *connection) key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wireless_sec); /* Everything below here uses encryption */ - nm_ap_set_flags (ap, nm_ap_get_flags (ap) | NM_802_11_AP_FLAGS_PRIVACY); + nm_ap_set_flags (ap, priv->flags | NM_802_11_AP_FLAGS_PRIVACY); /* Static & Dynamic WEP */ if (!strcmp (key_mgmt, "none") || !strcmp (key_mgmt, "ieee8021x")) @@ -644,13 +656,11 @@ nm_ap_new_fake_from_connection (NMConnection *connection) eap = !strcmp (key_mgmt, "wpa-eap"); if (psk || eap) { if (has_proto (s_wireless_sec, PROTO_WPA)) { - flags = nm_ap_get_wpa_flags (ap); - flags |= eap ? NM_802_11_AP_SEC_KEY_MGMT_802_1X : NM_802_11_AP_SEC_KEY_MGMT_PSK; + flags = priv->wpa_flags | (eap ? NM_802_11_AP_SEC_KEY_MGMT_802_1X : NM_802_11_AP_SEC_KEY_MGMT_PSK); nm_ap_set_wpa_flags (ap, flags); } if (has_proto (s_wireless_sec, PROTO_RSN)) { - flags = nm_ap_get_rsn_flags (ap); - flags |= eap ? NM_802_11_AP_SEC_KEY_MGMT_802_1X : NM_802_11_AP_SEC_KEY_MGMT_PSK; + flags = priv->rsn_flags | (eap ? NM_802_11_AP_SEC_KEY_MGMT_802_1X : NM_802_11_AP_SEC_KEY_MGMT_PSK); nm_ap_set_rsn_flags (ap, flags); } @@ -663,8 +673,7 @@ nm_ap_new_fake_from_connection (NMConnection *connection) * group=TKIP/CCMP (but not both). */ - flags = nm_ap_get_wpa_flags (ap); - flags |= NM_802_11_AP_SEC_KEY_MGMT_PSK; + flags = priv->wpa_flags | NM_802_11_AP_SEC_KEY_MGMT_PSK; /* Clear ciphers; pairwise must be unset anyway, and group gets set below */ flags &= ~( NM_802_11_AP_SEC_PAIR_WEP40 @@ -701,394 +710,60 @@ error: return NULL; } -void -nm_ap_dump (NMAccessPoint *ap, const char *prefix) -{ - NMAccessPointPrivate *priv; - - g_return_if_fail (NM_IS_AP (ap)); - - priv = NM_AP_GET_PRIVATE (ap); - - nm_log_dbg (LOGD_WIFI_SCAN, "%s'%s' (%p)", - prefix, - priv->ssid ? nm_utils_escape_ssid (priv->ssid->data, priv->ssid->len) : "(none)", - ap); - nm_log_dbg (LOGD_WIFI_SCAN, " BSSID %s", str_if_set (priv->address, "(none)")); - nm_log_dbg (LOGD_WIFI_SCAN, " mode %d", priv->mode); - nm_log_dbg (LOGD_WIFI_SCAN, " flags 0x%X", priv->flags); - nm_log_dbg (LOGD_WIFI_SCAN, " wpa flags 0x%X", priv->wpa_flags); - nm_log_dbg (LOGD_WIFI_SCAN, " rsn flags 0x%X", priv->rsn_flags); - nm_log_dbg (LOGD_WIFI_SCAN, " quality %d", priv->strength); - nm_log_dbg (LOGD_WIFI_SCAN, " frequency %d", priv->freq); - nm_log_dbg (LOGD_WIFI_SCAN, " max rate %d", priv->max_bitrate); - nm_log_dbg (LOGD_WIFI_SCAN, " last-seen %d", (int) priv->last_seen); -} - -const char * -nm_ap_get_dbus_path (NMAccessPoint *ap) -{ - g_return_val_if_fail (NM_IS_AP (ap), NULL); - - return NM_AP_GET_PRIVATE (ap)->dbus_path; -} - -const char * -nm_ap_get_supplicant_path (NMAccessPoint *ap) +static char +mode_to_char (NMAccessPoint *self) { - g_return_val_if_fail (NM_IS_AP (ap), NULL); - - return NM_AP_GET_PRIVATE (ap)->supplicant_path; -} - -void -nm_ap_set_supplicant_path (NMAccessPoint *ap, const char *path) -{ - g_return_if_fail (NM_IS_AP (ap)); - g_return_if_fail (path != NULL); - - g_free (NM_AP_GET_PRIVATE (ap)->supplicant_path); - NM_AP_GET_PRIVATE (ap)->supplicant_path = g_strdup (path); -} - -/* - * Get/set functions for ssid - * - */ -const GByteArray * nm_ap_get_ssid (const NMAccessPoint *ap) -{ - g_return_val_if_fail (NM_IS_AP (ap), NULL); - - return NM_AP_GET_PRIVATE (ap)->ssid; -} - -void -nm_ap_set_ssid (NMAccessPoint *ap, const guint8 *ssid, gsize len) -{ - NMAccessPointPrivate *priv; - - g_return_if_fail (NM_IS_AP (ap)); - g_return_if_fail (ssid == NULL || len > 0); - - priv = NM_AP_GET_PRIVATE (ap); - - /* same SSID */ - if ((ssid && priv->ssid) && (len == priv->ssid->len)) { - if (!memcmp (ssid, priv->ssid->data, len)) - return; - } - - if (priv->ssid) { - g_byte_array_free (priv->ssid, TRUE); - priv->ssid = NULL; - } - - if (ssid) { - priv->ssid = g_byte_array_new (); - g_byte_array_append (priv->ssid, ssid, len); - } - - g_object_notify (G_OBJECT (ap), NM_AP_SSID); -} - - -NM80211ApFlags -nm_ap_get_flags (NMAccessPoint *ap) -{ - g_return_val_if_fail (NM_IS_AP (ap), NM_802_11_AP_FLAGS_NONE); - - return NM_AP_GET_PRIVATE (ap)->flags; -} - - -void -nm_ap_set_flags (NMAccessPoint *ap, NM80211ApFlags flags) -{ - NMAccessPointPrivate *priv; - - g_return_if_fail (NM_IS_AP (ap)); - - priv = NM_AP_GET_PRIVATE (ap); - - if (priv->flags != flags) { - priv->flags = flags; - g_object_notify (G_OBJECT (ap), NM_AP_FLAGS); - } -} - -NM80211ApSecurityFlags -nm_ap_get_wpa_flags (NMAccessPoint *ap) -{ - g_return_val_if_fail (NM_IS_AP (ap), NM_802_11_AP_SEC_NONE); - - return NM_AP_GET_PRIVATE (ap)->wpa_flags; -} - - -void -nm_ap_set_wpa_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags) -{ - NMAccessPointPrivate *priv; - - g_return_if_fail (NM_IS_AP (ap)); - - priv = NM_AP_GET_PRIVATE (ap); - if (priv->wpa_flags != flags) { - priv->wpa_flags = flags; - g_object_notify (G_OBJECT (ap), NM_AP_WPA_FLAGS); - } -} - -NM80211ApSecurityFlags -nm_ap_get_rsn_flags (NMAccessPoint *ap) -{ - g_return_val_if_fail (NM_IS_AP (ap), NM_802_11_AP_SEC_NONE); - - return NM_AP_GET_PRIVATE (ap)->rsn_flags; -} - - -void -nm_ap_set_rsn_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags) -{ - NMAccessPointPrivate *priv; - - g_return_if_fail (NM_IS_AP (ap)); - - priv = NM_AP_GET_PRIVATE (ap); - if (priv->rsn_flags != flags) { - priv->rsn_flags = flags; - g_object_notify (G_OBJECT (ap), NM_AP_RSN_FLAGS); - } -} - -/* - * Get/set functions for address - * - */ -const char * -nm_ap_get_address (const NMAccessPoint *ap) -{ - g_return_val_if_fail (NM_IS_AP (ap), NULL); - - return NM_AP_GET_PRIVATE (ap)->address; -} - -void -nm_ap_set_address (NMAccessPoint *ap, const char *addr) -{ - NMAccessPointPrivate *priv; - - g_return_if_fail (NM_IS_AP (ap)); - g_return_if_fail (addr != NULL); - g_return_if_fail (nm_utils_hwaddr_valid (addr, ETH_ALEN)); - - priv = NM_AP_GET_PRIVATE (ap); - - if (!priv->address || !nm_utils_hwaddr_matches (addr, -1, priv->address, -1)) { - g_free (priv->address); - priv->address = g_strdup (addr); - g_object_notify (G_OBJECT (ap), NM_AP_HW_ADDRESS); - } -} - - -/* - * Get/set functions for mode (ie Ad-Hoc, Infrastructure, etc) - * - */ -NM80211Mode nm_ap_get_mode (NMAccessPoint *ap) -{ - NM80211Mode mode; - - g_return_val_if_fail (NM_IS_AP (ap), -1); - - g_object_get (ap, NM_AP_MODE, &mode, NULL); - - return mode; -} - -void nm_ap_set_mode (NMAccessPoint *ap, const NM80211Mode mode) -{ - NMAccessPointPrivate *priv; - - g_return_if_fail (NM_IS_AP (ap)); - g_return_if_fail ( mode == NM_802_11_MODE_ADHOC - || mode == NM_802_11_MODE_INFRA); - - priv = NM_AP_GET_PRIVATE (ap); - - if (priv->mode != mode) { - priv->mode = mode; - g_object_notify (G_OBJECT (ap), NM_AP_MODE); - } -} - -gboolean -nm_ap_is_hotspot (NMAccessPoint *ap) -{ - g_return_val_if_fail (NM_IS_AP (ap), FALSE); - - return NM_AP_GET_PRIVATE (ap)->hotspot; -} - -/* - * Get/set functions for strength - * - */ -gint8 nm_ap_get_strength (NMAccessPoint *ap) -{ - gint8 strength; - - g_return_val_if_fail (NM_IS_AP (ap), 0); - - g_object_get (ap, NM_AP_STRENGTH, &strength, NULL); - - return strength; -} - -void nm_ap_set_strength (NMAccessPoint *ap, const gint8 strength) -{ - NMAccessPointPrivate *priv; - - g_return_if_fail (NM_IS_AP (ap)); - - priv = NM_AP_GET_PRIVATE (ap); - - if (priv->strength != strength) { - priv->strength = strength; - g_object_notify (G_OBJECT (ap), NM_AP_STRENGTH); - } -} - - -/* - * Get/set functions for frequency - * - */ -guint32 -nm_ap_get_freq (NMAccessPoint *ap) -{ - guint32 freq; - - g_return_val_if_fail (NM_IS_AP (ap), 0); - - g_object_get (ap, NM_AP_FREQUENCY, &freq, NULL); - - return freq; -} - -void -nm_ap_set_freq (NMAccessPoint *ap, - const guint32 freq) -{ - NMAccessPointPrivate *priv; - - g_return_if_fail (NM_IS_AP (ap)); - - priv = NM_AP_GET_PRIVATE (ap); - - if (priv->freq != freq) { - priv->freq = freq; - g_object_notify (G_OBJECT (ap), NM_AP_FREQUENCY); - } -} - - -/* - * Get/set functions for max bitrate (in kbit/s) - * - */ -guint32 nm_ap_get_max_bitrate (NMAccessPoint *ap) -{ - guint32 rate; - - g_return_val_if_fail (NM_IS_AP (ap), 0); - - g_object_get (ap, NM_AP_MAX_BITRATE, &rate, NULL); + NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (self); - return rate; + if (priv->mode == NM_802_11_MODE_ADHOC) + return '*'; + if (priv->hotspot) + return '#'; + if (priv->fake) + return '-'; + return ' '; } void -nm_ap_set_max_bitrate (NMAccessPoint *ap, guint32 bitrate) +nm_ap_dump (NMAccessPoint *self, + const char *prefix, + const char *ifname) { NMAccessPointPrivate *priv; + const char *supplicant_id = "-"; + guint32 chan; - g_return_if_fail (NM_IS_AP (ap)); - - priv = NM_AP_GET_PRIVATE (ap); - - if (priv->max_bitrate != bitrate) { - priv->max_bitrate = bitrate; - g_object_notify (G_OBJECT (ap), NM_AP_MAX_BITRATE); - } -} - -/* - * Get/Set functions to indicate that an access point is 'fake', ie whether - * or not it was created from scan results - */ -gboolean nm_ap_get_fake (const NMAccessPoint *ap) -{ - g_return_val_if_fail (NM_IS_AP (ap), FALSE); - - return NM_AP_GET_PRIVATE (ap)->fake; -} - -void nm_ap_set_fake (NMAccessPoint *ap, gboolean fake) -{ - g_return_if_fail (NM_IS_AP (ap)); - - NM_AP_GET_PRIVATE (ap)->fake = fake; -} - - -/* - * Get/Set functions to indicate whether an AP broadcasts its SSID. - */ -gboolean nm_ap_get_broadcast (NMAccessPoint *ap) -{ - g_return_val_if_fail (NM_IS_AP (ap), TRUE); - - return NM_AP_GET_PRIVATE (ap)->broadcast; -} - - -void nm_ap_set_broadcast (NMAccessPoint *ap, gboolean broadcast) -{ - g_return_if_fail (NM_IS_AP (ap)); - - NM_AP_GET_PRIVATE (ap)->broadcast = broadcast; -} - + g_return_if_fail (NM_IS_AP (self)); -/* - * Get/Set functions for how long ago the AP was last seen in a scan. - * APs older than a certain date are dropped from the list. - * - */ -gint32 -nm_ap_get_last_seen (const NMAccessPoint *ap) -{ - g_return_val_if_fail (NM_IS_AP (ap), 0); + priv = NM_AP_GET_PRIVATE (self); + chan = nm_utils_wifi_freq_to_channel (priv->freq); + if (priv->supplicant_path) + supplicant_id = strrchr (priv->supplicant_path, '/'); - return NM_AP_GET_PRIVATE (ap)->last_seen; + nm_log_dbg (LOGD_WIFI_SCAN, "%s[%s%c] %-32s[%s%u %3u%% %c W:%04X R:%04X] [%3u] %s%s", + prefix, + str_if_set (priv->address, "(none)"), + mode_to_char (self), + priv->ssid ? nm_utils_escape_ssid (priv->ssid->data, priv->ssid->len) : "(none)", + chan > 99 ? "" : (chan > 9 ? " " : " "), + chan, + priv->strength, + priv->flags & NM_802_11_AP_FLAGS_PRIVACY ? 'P' : ' ', + priv->wpa_flags & 0xFFFF, + priv->rsn_flags & 0xFFFF, + priv->last_seen > 0 ? (nm_utils_get_monotonic_timestamp_s () - priv->last_seen) : -1, + ifname, + supplicant_id); } -void -nm_ap_set_last_seen (NMAccessPoint *ap, gint32 last_seen) +static guint +freq_to_band (guint32 freq) { - NMAccessPointPrivate *priv; - - g_return_if_fail (NM_IS_AP (ap)); - - priv = NM_AP_GET_PRIVATE (ap); - - if (priv->last_seen != last_seen) { - priv->last_seen = last_seen; - g_object_notify (G_OBJECT (ap), NM_AP_LAST_SEEN); - } + if (freq >= 4915 && freq <= 5825) + return 5; + else if (freq >= 2412 && freq <= 2484) + return 2; + return 0; } gboolean @@ -1141,13 +816,12 @@ nm_ap_check_compatible (NMAccessPoint *self, band = nm_setting_wireless_get_band (s_wireless); if (band) { - if (!strcmp (band, "a")) { - if (priv->freq < 4915 || priv->freq > 5825) - return FALSE; - } else if (!strcmp (band, "bg")) { - if (priv->freq < 2412 || priv->freq > 2484) - return FALSE; - } + guint ap_band = freq_to_band (priv->freq); + + if (!strcmp (band, "a") && ap_band != 5) + return FALSE; + else if (!strcmp (band, "bg") && ap_band != 2) + return FALSE; } channel = nm_setting_wireless_get_channel (s_wireless); @@ -1162,10 +836,10 @@ nm_ap_check_compatible (NMAccessPoint *self, return nm_setting_wireless_ap_security_compatible (s_wireless, s_wireless_sec, - nm_ap_get_flags (self), - nm_ap_get_wpa_flags (self), - nm_ap_get_rsn_flags (self), - nm_ap_get_mode (self)); + priv->flags, + priv->wpa_flags, + priv->rsn_flags, + priv->mode); } gboolean @@ -1189,96 +863,188 @@ nm_ap_complete_connection (NMAccessPoint *self, error); } -static gboolean -capabilities_compatible (NM80211ApSecurityFlags a_flags, NM80211ApSecurityFlags b_flags) +/*****************************************************************/ + +static void +nm_ap_init (NMAccessPoint *ap) { - if (a_flags == b_flags) - return TRUE; + NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (ap); - /* Make sure there's a common key management method */ - if (!((a_flags & 0x300) & (b_flags & 0x300))) - return FALSE; + priv->mode = NM_802_11_MODE_INFRA; + priv->flags = NM_802_11_AP_FLAGS_NONE; + priv->wpa_flags = NM_802_11_AP_SEC_NONE; + priv->rsn_flags = NM_802_11_AP_SEC_NONE; + priv->last_seen = -1; +} - /* Ensure common pairwise ciphers */ - if (!((a_flags & 0xF) & (b_flags & 0xF))) - return FALSE; +static void +finalize (GObject *object) +{ + NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (object); - /* Ensure common group ciphers */ - if (!((a_flags & 0xF0) & (b_flags & 0xF0))) - return FALSE; + g_free (priv->supplicant_path); + if (priv->ssid) + g_byte_array_free (priv->ssid, TRUE); + g_free (priv->address); - return TRUE; + G_OBJECT_CLASS (nm_ap_parent_class)->finalize (object); } -NMAccessPoint * -nm_ap_match_in_list (NMAccessPoint *find_ap, - GSList *ap_list, - gboolean strict_match) +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) { - GSList *iter; + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); +} - g_return_val_if_fail (find_ap != NULL, NULL); +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMAccessPointPrivate *priv = NM_AP_GET_PRIVATE (object); + GVariant *ssid; - for (iter = ap_list; iter; iter = g_slist_next (iter)) { - NMAccessPoint * list_ap = NM_AP (iter->data); - const GByteArray * list_ssid = nm_ap_get_ssid (list_ap); - const char * list_addr = nm_ap_get_address (list_ap); + switch (prop_id) { + case PROP_FLAGS: + g_value_set_uint (value, priv->flags); + break; + case PROP_WPA_FLAGS: + g_value_set_uint (value, priv->wpa_flags); + break; + case PROP_RSN_FLAGS: + g_value_set_uint (value, priv->rsn_flags); + break; + case PROP_SSID: + if (priv->ssid) { + ssid = g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, + priv->ssid->data, priv->ssid->len, 1); + } else + ssid = g_variant_new_array (G_VARIANT_TYPE_BYTE, NULL, 0); + g_value_take_variant (value, ssid); + break; + case PROP_FREQUENCY: + g_value_set_uint (value, priv->freq); + break; + case PROP_HW_ADDRESS: + g_value_set_string (value, priv->address); + break; + case PROP_MODE: + g_value_set_uint (value, priv->mode); + break; + case PROP_MAX_BITRATE: + g_value_set_uint (value, priv->max_bitrate); + break; + case PROP_STRENGTH: + g_value_set_uchar (value, priv->strength); + break; + case PROP_LAST_SEEN: + g_value_set_int (value, + priv->last_seen > 0 + ? (gint) nm_utils_monotonic_timestamp_as_boottime (priv->last_seen, NM_UTILS_NS_PER_SECOND) + : -1); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} - const GByteArray * find_ssid = nm_ap_get_ssid (find_ap); - const char * find_addr = nm_ap_get_address (find_ap); +static void +nm_ap_class_init (NMAccessPointClass *ap_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (ap_class); + NMExportedObjectClass *exported_object_class = NM_EXPORTED_OBJECT_CLASS (ap_class); + const NM80211ApSecurityFlags all_sec_flags = NM_802_11_AP_SEC_NONE + | NM_802_11_AP_SEC_PAIR_WEP40 + | NM_802_11_AP_SEC_PAIR_WEP104 + | NM_802_11_AP_SEC_PAIR_TKIP + | NM_802_11_AP_SEC_PAIR_CCMP + | NM_802_11_AP_SEC_GROUP_WEP40 + | NM_802_11_AP_SEC_GROUP_WEP104 + | NM_802_11_AP_SEC_GROUP_TKIP + | NM_802_11_AP_SEC_GROUP_CCMP + | NM_802_11_AP_SEC_KEY_MGMT_PSK + | NM_802_11_AP_SEC_KEY_MGMT_802_1X; - /* SSID match; if both APs are hiding their SSIDs, - * let matching continue on BSSID and other properties - */ - if ( (!list_ssid && find_ssid) - || (list_ssid && !find_ssid)) - continue; - if ( list_ssid - && find_ssid - && !nm_utils_same_ssid (list_ssid->data, list_ssid->len, - find_ssid->data, find_ssid->len, - TRUE)) - continue; - - /* BSSID match */ - if ( (strict_match || nm_ethernet_address_is_valid (find_addr, -1)) - && nm_ethernet_address_is_valid (list_addr, -1) - && !nm_utils_hwaddr_matches (list_addr, -1, find_addr, -1)) - continue; - - /* mode match */ - if (nm_ap_get_mode (list_ap) != nm_ap_get_mode (find_ap)) - continue; - - /* Frequency match */ - if (nm_ap_get_freq (list_ap) != nm_ap_get_freq (find_ap)) - continue; - - /* AP flags */ - if (nm_ap_get_flags (list_ap) != nm_ap_get_flags (find_ap)) - continue; - - if (strict_match) { - if (nm_ap_get_wpa_flags (list_ap) != nm_ap_get_wpa_flags (find_ap)) - continue; - - if (nm_ap_get_rsn_flags (list_ap) != nm_ap_get_rsn_flags (find_ap)) - continue; - } else { - NM80211ApSecurityFlags list_wpa_flags = nm_ap_get_wpa_flags (list_ap); - NM80211ApSecurityFlags find_wpa_flags = nm_ap_get_wpa_flags (find_ap); - NM80211ApSecurityFlags list_rsn_flags = nm_ap_get_rsn_flags (list_ap); - NM80211ApSecurityFlags find_rsn_flags = nm_ap_get_rsn_flags (find_ap); - - /* Just ensure that there is overlap in the capabilities */ - if ( !capabilities_compatible (list_wpa_flags, find_wpa_flags) - && !capabilities_compatible (list_rsn_flags, find_rsn_flags)) - continue; - } + g_type_class_add_private (ap_class, sizeof (NMAccessPointPrivate)); - return list_ap; - } + exported_object_class->export_path = NM_DBUS_PATH_ACCESS_POINT "/%u"; - return NULL; + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->finalize = finalize; + + /* properties */ + g_object_class_install_property + (object_class, PROP_FLAGS, + g_param_spec_uint (NM_AP_FLAGS, "", "", + NM_802_11_AP_FLAGS_NONE, + NM_802_11_AP_FLAGS_PRIVACY, + NM_802_11_AP_FLAGS_NONE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_WPA_FLAGS, + g_param_spec_uint (NM_AP_WPA_FLAGS, "", "", + NM_802_11_AP_SEC_NONE, + all_sec_flags, + NM_802_11_AP_SEC_NONE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_RSN_FLAGS, + g_param_spec_uint (NM_AP_RSN_FLAGS, "", "", + NM_802_11_AP_SEC_NONE, + all_sec_flags, + NM_802_11_AP_SEC_NONE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_SSID, + g_param_spec_variant (NM_AP_SSID, "", "", + G_VARIANT_TYPE ("ay"), + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_FREQUENCY, + g_param_spec_uint (NM_AP_FREQUENCY, "", "", + 0, 10000, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_HW_ADDRESS, + g_param_spec_string (NM_AP_HW_ADDRESS, "", "", + NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_MODE, + g_param_spec_uint (NM_AP_MODE, "", "", + NM_802_11_MODE_ADHOC, NM_802_11_MODE_INFRA, NM_802_11_MODE_INFRA, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_MAX_BITRATE, + g_param_spec_uint (NM_AP_MAX_BITRATE, "", "", + 0, G_MAXUINT16, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_STRENGTH, + g_param_spec_uchar (NM_AP_STRENGTH, "", "", + 0, G_MAXINT8, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property + (object_class, PROP_LAST_SEEN, + g_param_spec_int (NM_AP_LAST_SEEN, "", "", + -1, G_MAXINT, -1, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (ap_class), + NMDBUS_TYPE_ACCESS_POINT_SKELETON, + NULL); } diff --git a/src/devices/wifi/nm-wifi-ap.h b/src/devices/wifi/nm-wifi-ap.h index 67d30769..84aff983 100644 --- a/src/devices/wifi/nm-wifi-ap.h +++ b/src/devices/wifi/nm-wifi-ap.h @@ -22,8 +22,7 @@ #ifndef __NETWORKMANAGER_ACCESS_POINT_H__ #define __NETWORKMANAGER_ACCESS_POINT_H__ -#include <glib.h> -#include <glib-object.h> +#include "nm-exported-object.h" #include "nm-dbus-interface.h" #include "nm-connection.h" @@ -46,77 +45,58 @@ #define NM_AP_LAST_SEEN "last-seen" typedef struct { - GObject parent; + NMExportedObject parent; } NMAccessPoint; typedef struct { - GObjectClass parent; + NMExportedObjectClass parent; } NMAccessPointClass; GType nm_ap_get_type (void); -NMAccessPoint * nm_ap_new_from_properties (const char *supplicant_path, - GVariant *properties); -NMAccessPoint * nm_ap_new_fake_from_connection (NMConnection *connection); -void nm_ap_export_to_dbus (NMAccessPoint *ap); - -const char *nm_ap_get_dbus_path (NMAccessPoint *ap); - -const char *nm_ap_get_supplicant_path (NMAccessPoint *ap); -void nm_ap_set_supplicant_path (NMAccessPoint *ap, - const char *path); - -const GByteArray *nm_ap_get_ssid (const NMAccessPoint * ap); -void nm_ap_set_ssid (NMAccessPoint * ap, const guint8 * ssid, gsize len); - -NM80211ApFlags nm_ap_get_flags (NMAccessPoint *ap); -void nm_ap_set_flags (NMAccessPoint *ap, NM80211ApFlags flags); - -NM80211ApSecurityFlags nm_ap_get_wpa_flags (NMAccessPoint *ap); -void nm_ap_set_wpa_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags); - -NM80211ApSecurityFlags nm_ap_get_rsn_flags (NMAccessPoint *ap); -void nm_ap_set_rsn_flags (NMAccessPoint *ap, NM80211ApSecurityFlags flags); - -const char *nm_ap_get_address (const NMAccessPoint *ap); -void nm_ap_set_address (NMAccessPoint *ap, const char *addr); - -NM80211Mode nm_ap_get_mode (NMAccessPoint *ap); -void nm_ap_set_mode (NMAccessPoint *ap, const NM80211Mode mode); - -gboolean nm_ap_is_hotspot (NMAccessPoint *ap); - -gint8 nm_ap_get_strength (NMAccessPoint *ap); -void nm_ap_set_strength (NMAccessPoint *ap, gint8 strength); - -guint32 nm_ap_get_freq (NMAccessPoint *ap); -void nm_ap_set_freq (NMAccessPoint *ap, guint32 freq); - -guint32 nm_ap_get_max_bitrate (NMAccessPoint *ap); -void nm_ap_set_max_bitrate (NMAccessPoint *ap, guint32 bitrate); - -gboolean nm_ap_get_fake (const NMAccessPoint *ap); -void nm_ap_set_fake (NMAccessPoint *ap, gboolean fake); - -gboolean nm_ap_get_broadcast (NMAccessPoint *ap); -void nm_ap_set_broadcast (NMAccessPoint *ap, gboolean broadcast); - -gint32 nm_ap_get_last_seen (const NMAccessPoint *ap); -void nm_ap_set_last_seen (NMAccessPoint *ap, gint32 last_seen); - -gboolean nm_ap_check_compatible (NMAccessPoint *self, - NMConnection *connection); - -gboolean nm_ap_complete_connection (NMAccessPoint *self, - NMConnection *connection, - gboolean lock_bssid, - GError **error); - -NMAccessPoint * nm_ap_match_in_list (NMAccessPoint *find_ap, - GSList *ap_list, - gboolean strict_match); - -void nm_ap_dump (NMAccessPoint *ap, const char *prefix); +NMAccessPoint * nm_ap_new_from_properties (const char *supplicant_path, + GVariant *properties); +NMAccessPoint * nm_ap_new_fake_from_connection (NMConnection *connection); + +void nm_ap_update_from_properties (NMAccessPoint *ap, + const char *supplicant_path, + GVariant *properties); + +gboolean nm_ap_check_compatible (NMAccessPoint *self, + NMConnection *connection); + +gboolean nm_ap_complete_connection (NMAccessPoint *self, + NMConnection *connection, + gboolean lock_bssid, + GError **error); + +const char * nm_ap_get_supplicant_path (NMAccessPoint *ap); +guint32 nm_ap_get_id (NMAccessPoint *ap); +const GByteArray *nm_ap_get_ssid (const NMAccessPoint *ap); +void nm_ap_set_ssid (NMAccessPoint *ap, + const guint8 *ssid, + gsize len); +const char * nm_ap_get_address (const NMAccessPoint *ap); +void nm_ap_set_address (NMAccessPoint *ap, + const char *addr); +NM80211Mode nm_ap_get_mode (NMAccessPoint *ap); +gboolean nm_ap_is_hotspot (NMAccessPoint *ap); +gint8 nm_ap_get_strength (NMAccessPoint *ap); +void nm_ap_set_strength (NMAccessPoint *ap, + gint8 strength); +guint32 nm_ap_get_freq (NMAccessPoint *ap); +void nm_ap_set_freq (NMAccessPoint *ap, + guint32 freq); +guint32 nm_ap_get_max_bitrate (NMAccessPoint *ap); +void nm_ap_set_max_bitrate (NMAccessPoint *ap, + guint32 bitrate); +gboolean nm_ap_get_fake (const NMAccessPoint *ap); +void nm_ap_set_fake (NMAccessPoint *ap, + gboolean fake); + +void nm_ap_dump (NMAccessPoint *self, + const char *prefix, + const char *ifname); #endif /* __NETWORKMANAGER_ACCESS_POINT_H__ */ diff --git a/src/devices/wifi/nm-wifi-enum-types.c b/src/devices/wifi/nm-wifi-enum-types.c deleted file mode 100644 index 7cce51cd..00000000 --- a/src/devices/wifi/nm-wifi-enum-types.c +++ /dev/null @@ -1,14 +0,0 @@ - - - -/* Generated by glib-mkenums. Do not edit */ - -#include "nm-wifi-enum-types.h" - -#include "nm-device-wifi.h" -#include "nm-wifi-ap.h" -#include "nm-device-olpc-mesh.h" - - - - diff --git a/src/devices/wifi/nm-wifi-enum-types.h b/src/devices/wifi/nm-wifi-enum-types.h deleted file mode 100644 index 7fc64cd1..00000000 --- a/src/devices/wifi/nm-wifi-enum-types.h +++ /dev/null @@ -1,17 +0,0 @@ - - - -/* Generated by glib-mkenums. Do not edit */ - -#ifndef __NM_WIFI_ENUM_TYPES_H__ -#define __NM_WIFI_ENUM_TYPES_H__ - -#include <glib-object.h> - -G_BEGIN_DECLS -G_END_DECLS - -#endif /* __NM_WIFI_ENUM_TYPES_H__ */ - - - diff --git a/src/devices/wifi/nm-wifi-factory.c b/src/devices/wifi/nm-wifi-factory.c index c4b4042e..7f56dc74 100644 --- a/src/devices/wifi/nm-wifi-factory.c +++ b/src/devices/wifi/nm-wifi-factory.c @@ -43,7 +43,7 @@ typedef struct { static GType nm_wifi_factory_get_type (void); -static void device_factory_interface_init (NMDeviceFactory *factory_iface); +static void device_factory_interface_init (NMDeviceFactoryInterface *factory_iface); G_DEFINE_TYPE_EXTENDED (NMWifiFactory, nm_wifi_factory, G_TYPE_OBJECT, 0, G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_FACTORY, device_factory_interface_init)) @@ -59,13 +59,30 @@ nm_device_factory_create (GError **error) /**************************************************************************/ static NMDevice * -new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error) +create_device (NMDeviceFactory *factory, + const char *iface, + const NMPlatformLink *plink, + NMConnection *connection, + gboolean *out_ignore) { + NMDeviceWifiCapabilities capabilities; + + g_return_val_if_fail (iface != NULL, NULL); + g_return_val_if_fail (plink != NULL, NULL); + g_return_val_if_fail (g_strcmp0 (iface, plink->name) == 0, NULL); + g_return_val_if_fail (NM_IN_SET (plink->type, NM_LINK_TYPE_WIFI, NM_LINK_TYPE_OLPC_MESH), NULL); + + if (!nm_platform_wifi_get_capabilities (NM_PLATFORM_GET, + plink->ifindex, + &capabilities)) { + nm_log_warn (LOGD_HW | LOGD_WIFI, "(%s) failed to initialize Wi-Fi driver for ifindex %d", iface, plink->ifindex); + return NULL; + } + if (plink->type == NM_LINK_TYPE_WIFI) - return nm_device_wifi_new (plink); - else if (plink->type == NM_LINK_TYPE_OLPC_MESH) - return nm_device_olpc_mesh_new (plink); - g_assert_not_reached (); + return nm_device_wifi_new (iface, capabilities); + else + return nm_device_olpc_mesh_new (iface); } NM_DEVICE_FACTORY_DECLARE_TYPES ( @@ -74,9 +91,9 @@ NM_DEVICE_FACTORY_DECLARE_TYPES ( ) static void -device_factory_interface_init (NMDeviceFactory *factory_iface) +device_factory_interface_init (NMDeviceFactoryInterface *factory_iface) { - factory_iface->new_link = new_link; + factory_iface->create_device = create_device; factory_iface->get_supported_types = get_supported_types; } diff --git a/src/devices/wifi/tests/Makefile.am b/src/devices/wifi/tests/Makefile.am index f76bdbf5..dee8e799 100644 --- a/src/devices/wifi/tests/Makefile.am +++ b/src/devices/wifi/tests/Makefile.am @@ -1,6 +1,7 @@ AM_CPPFLAGS = \ - -I$(top_srcdir)/include \ - -I$(top_builddir)/include \ + -I$(top_builddir)/introspection \ + -I$(top_srcdir)/shared \ + -I$(top_builddir)/shared \ -I$(top_srcdir)/libnm-core \ -I$(top_builddir)/libnm-core \ -I${top_srcdir}/src/platform \ @@ -8,10 +9,9 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/devices/wifi \ -I$(top_builddir)/src \ -DG_LOG_DOMAIN=\""NetworkManager-wifi"\" \ - -DNETWORKMANAGER_COMPILATION \ + -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ - $(GLIB_CFLAGS) \ - $(DBUS_CFLAGS) + $(GLIB_CFLAGS) noinst_PROGRAMS = test-wifi-ap-utils diff --git a/src/devices/wifi/tests/Makefile.in b/src/devices/wifi/tests/Makefile.in index f2488c7d..90900f00 100644 --- a/src/devices/wifi/tests/Makefile.in +++ b/src/devices/wifi/tests/Makefile.in @@ -404,7 +404,6 @@ BLUEZ5_LIBS = @BLUEZ5_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ -CKDB_PATH = @CKDB_PATH@ CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ @@ -416,8 +415,6 @@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DBUS_CFLAGS = @DBUS_CFLAGS@ -DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@ -DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@ DBUS_LIBS = @DBUS_LIBS@ DBUS_SYS_DIR = @DBUS_SYS_DIR@ DEFS = @DEFS@ @@ -427,6 +424,7 @@ DHCPCD_PATH = @DHCPCD_PATH@ DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ DLLTOOL = @DLLTOOL@ DNSMASQ_PATH = @DNSMASQ_PATH@ +DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ @@ -481,16 +479,13 @@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ IPTABLES_PATH = @IPTABLES_PATH@ -IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ -IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ +LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@ +LIBAUDIT_LIBS = @LIBAUDIT_LIBS@ LIBDL = @LIBDL@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ @@ -527,6 +522,8 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ +NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ NM_MICRO_VERSION = @NM_MICRO_VERSION@ NM_MINOR_VERSION = @NM_MINOR_VERSION@ @@ -555,7 +552,6 @@ POLKIT_LIBS = @POLKIT_LIBS@ POSUB = @POSUB@ PPPD_PATH = @PPPD_PATH@ PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ -PPPOE_PATH = @PPPOE_PATH@ QT_CFLAGS = @QT_CFLAGS@ QT_LIBS = @QT_LIBS@ RANLIB = @RANLIB@ @@ -570,6 +566,8 @@ SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ +SYSTEMD_JOURNAL_CFLAGS = @SYSTEMD_JOURNAL_CFLAGS@ +SYSTEMD_JOURNAL_LIBS = @SYSTEMD_JOURNAL_LIBS@ SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ @@ -630,6 +628,7 @@ mkdir_p = @mkdir_p@ nmbinary = @nmbinary@ nmconfdir = @nmconfdir@ nmdatadir = @nmdatadir@ +nmlibdir = @nmlibdir@ nmrundir = @nmrundir@ nmstatedir = @nmstatedir@ oldincludedir = @oldincludedir@ @@ -637,6 +636,7 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -653,8 +653,9 @@ with_netconfig = @with_netconfig@ with_resolvconf = @with_resolvconf@ with_valgrind = @with_valgrind@ AM_CPPFLAGS = \ - -I$(top_srcdir)/include \ - -I$(top_builddir)/include \ + -I$(top_builddir)/introspection \ + -I$(top_srcdir)/shared \ + -I$(top_builddir)/shared \ -I$(top_srcdir)/libnm-core \ -I$(top_builddir)/libnm-core \ -I${top_srcdir}/src/platform \ @@ -662,10 +663,9 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/devices/wifi \ -I$(top_builddir)/src \ -DG_LOG_DOMAIN=\""NetworkManager-wifi"\" \ - -DNETWORKMANAGER_COMPILATION \ + -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ - $(GLIB_CFLAGS) \ - $(DBUS_CFLAGS) + $(GLIB_CFLAGS) test_wifi_ap_utils_SOURCES = \ test-wifi-ap-utils.c \ diff --git a/src/devices/wifi/tests/test-wifi-ap-utils.c b/src/devices/wifi/tests/test-wifi-ap-utils.c index 26e130c4..b5642fe2 100644 --- a/src/devices/wifi/tests/test-wifi-ap-utils.c +++ b/src/devices/wifi/tests/test-wifi-ap-utils.c @@ -20,14 +20,15 @@ #include "config.h" -#include <glib.h> #include <string.h> +#include "nm-default.h" #include "nm-wifi-ap-utils.h" -#include "nm-dbus-glib-types.h" #include "nm-core-internal.h" +#include "nm-test-utils.h" + #define DEBUG 1 /*******************************************/ @@ -1336,16 +1337,14 @@ test_strength_wext (void) /*******************************************/ +NMTST_DEFINE (); + int main (int argc, char **argv) { gsize i; -#if !GLIB_CHECK_VERSION (2, 35, 0) - g_type_init (); -#endif - - g_test_init (&argc, &argv, NULL); + nmtst_init_assert_logging (&argc, &argv, "INFO", "DEFAULT"); g_test_add_func ("/wifi/lock_bssid", test_lock_bssid); diff --git a/src/devices/wimax/Makefile.am b/src/devices/wimax/Makefile.am deleted file mode 100644 index 0ecd1158..00000000 --- a/src/devices/wimax/Makefile.am +++ /dev/null @@ -1,60 +0,0 @@ -AM_CPPFLAGS = \ - -I${top_srcdir}/src \ - -I${top_builddir}/src \ - -I${top_srcdir}/src/devices \ - -I${top_srcdir}/src/platform \ - -I${top_srcdir}/include \ - -I${top_builddir}/include \ - -I${top_builddir}/libnm-core \ - -I${top_srcdir}/libnm-core \ - -DG_LOG_DOMAIN=\""NetworkManager-wimax"\" \ - -DNETWORKMANAGER_COMPILATION \ - -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ - $(DBUS_CFLAGS) \ - $(IWMX_SDK_CFLAGS) - -pkglib_LTLIBRARIES = libnm-device-plugin-wimax.la - -SYMBOL_VIS_FILE=$(srcdir)/exports.ver - -libnm_device_plugin_wimax_la_SOURCES = \ - nm-wimax-factory.c \ - nm-device-wimax.c \ - nm-device-wimax.h \ - nm-wimax-nsp.c \ - nm-wimax-nsp.h \ - nm-wimax-types.h \ - nm-wimax-util.c \ - nm-wimax-util.h \ - iwmxsdk.c \ - iwmxsdk.h - -libnm_device_plugin_wimax_la_LDFLAGS = \ - -module -avoid-version \ - -Wl,--version-script=$(SYMBOL_VIS_FILE) - -libnm_device_plugin_wimax_la_LIBADD = \ - $(DBUS_LIBS) \ - $(IWMX_SDK_LIBS) \ - $(GUDEV_LIBS) - -nm-wimax-nsp-glue.h: $(top_srcdir)/introspection/nm-wimax-nsp.xml - dbus-binding-tool --prefix=nm_wimax_nsp --mode=glib-server --output=$@ $< - -nm-device-wimax-glue.h: $(top_srcdir)/introspection/nm-device-wimax.xml - dbus-binding-tool --prefix=nm_device_wimax --mode=glib-server --output=$@ $< - -BUILT_SOURCES = \ - nm-wimax-nsp-glue.h \ - nm-device-wimax-glue.h - -CLEANFILES = $(BUILT_SOURCES) -EXTRA_DIST = $(SYMBOL_VIS_FILE) - -if ENABLE_TESTS - -check-local: - $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-wimax.so $(SYMBOL_VIS_FILE) - -endif - diff --git a/src/devices/wimax/exports.ver b/src/devices/wimax/exports.ver deleted file mode 100644 index 24cd848c..00000000 --- a/src/devices/wimax/exports.ver +++ /dev/null @@ -1,6 +0,0 @@ -{ -global: - nm_device_factory_create; -local: - *; -}; diff --git a/src/devices/wimax/iwmxsdk.c b/src/devices/wimax/iwmxsdk.c deleted file mode 100644 index 1c2c6821..00000000 --- a/src/devices/wimax/iwmxsdk.c +++ /dev/null @@ -1,1515 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* - * - * Copyright (C) 2011 Red Hat, Inc. All rights reserved. - * Copyright (C) 2007-2010 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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 St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#include "config.h" - -#include <stdio.h> -#include <stdlib.h> -#include <errno.h> -#include <string.h> -#include <sys/socket.h> - -#include <glib.h> - -#include "nm-wimax-util.h" - -#include <WiMaxAPI.h> -#include <WiMaxAPIEx.h> - -#include "nm-logging.h" -#include "iwmxsdk.h" - -static WIMAX_API_DEVICE_ID g_api; -static GMutex add_remove_mutex; - -/* Misc utilities */ -#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) - -/* Misc values */ -enum { - /* - * WARNING!!!!! - * - * ONLY ONE DEVICE SUPPORTED - * - * - on removal, there is no way to know which device was - * removed (the removed device is removed from the list and - * the callback doesn't have any more information than the - * index in the list that getlistdevice would return -- racy - * as hell). - * - * - on insertion, there is not enough information provided. - */ - IWMX_SDK_DEV_MAX = 1, -}; - -/* Yes, this is dirty; see above on IWMX_SDK_DEV_MAX */ -static struct wmxsdk *g_iwmx_sdk_devs[IWMX_SDK_DEV_MAX]; - -static struct wmxsdk *deviceid_to_wmxsdk(WIMAX_API_DEVICE_ID *device_id) -{ - unsigned cnt; - for (cnt = 0; cnt < IWMX_SDK_DEV_MAX; cnt++) { - struct wmxsdk *wmxsdk = g_iwmx_sdk_devs[cnt]; - if (wmxsdk && - wmxsdk->device_id.deviceIndex == device_id->deviceIndex) - return wmxsdk; - } - return NULL; -} - -static int deviceid_to_index(WIMAX_API_DEVICE_ID *device_id) -{ - unsigned cnt; - - for (cnt = 0; cnt < IWMX_SDK_DEV_MAX; cnt++) { - struct wmxsdk *wmxsdk = g_iwmx_sdk_devs[cnt]; - if (wmxsdk && wmxsdk->device_id.deviceIndex == device_id->deviceIndex) - return cnt; - } - return -1; -} - -struct wmxsdk *iwmx_sdk_get_wmxsdk_for_iface(const char *iface) -{ - unsigned cnt; - - for (cnt = 0; cnt < IWMX_SDK_DEV_MAX; cnt++) { - struct wmxsdk *wmxsdk = g_iwmx_sdk_devs[cnt]; - if (wmxsdk && !strcmp(wmxsdk->ifname, iface)) - return wmxsdk; - } - return NULL; -} - -/* - * FIXME: pulled it it out of some hole - * - * the cinr to percentage computation comes from the L3/L4 doc - * - * But some other places (L4 code) have a more complex, seemingly - * logarithmical computation. - * - * Oh well... - * - */ -static int cinr_to_percentage(int cinr) -{ - int strength; - if (cinr <= -5) - strength = 0; - else if (cinr >= 25) - strength = 100; - else /* Calc percentage on the value from -5 to 25 */ - strength = ((100UL * (cinr - -5)) / (25 - -5)); - return strength; -} - -/**************************************************************/ - -typedef struct { - WimaxNewWmxsdkFunc callback; - void *user_data; -} NewSdkCallback; - -static GMutex new_callbacks_mutex; -static GSList *new_callbacks = NULL; - -void iwmx_sdk_new_callback_register(WimaxNewWmxsdkFunc callback, void *user_data) -{ - NewSdkCallback *cb; - - cb = g_malloc0 (sizeof (NewSdkCallback)); - g_assert (cb); - cb->callback = callback; - cb->user_data = user_data; - - g_mutex_lock (&new_callbacks_mutex); - new_callbacks = g_slist_append (new_callbacks, cb); - g_mutex_unlock (&new_callbacks_mutex); -} - -void iwmx_sdk_new_callback_unregister(WimaxNewWmxsdkFunc callback, void *user_data) -{ - GSList *iter; - NewSdkCallback *found = NULL; - - g_mutex_lock (&new_callbacks_mutex); - for (iter = new_callbacks; iter; iter = g_slist_next (iter)) { - NewSdkCallback *cb = iter->data; - - if (cb->callback == callback && cb->user_data == user_data) { - found = cb; - break; - } - } - - if (found) { - new_callbacks = g_slist_remove (new_callbacks, found); - g_free (found); - } - g_mutex_unlock (&new_callbacks_mutex); -} - -static void iwmx_sdk_call_new_callbacks(struct wmxsdk *wmxsdk) -{ - GSList *iter; - - g_mutex_lock (&new_callbacks_mutex); - for (iter = new_callbacks; iter; iter = g_slist_next (iter)) { - NewSdkCallback *cb = iter->data; - - cb->callback (wmxsdk, cb->user_data); - } - g_mutex_unlock (&new_callbacks_mutex); -} - -/****************************************************************/ - -typedef struct { - struct wmxsdk *wmxsdk; - WIMAX_API_DEVICE_STATUS new_status; - WIMAX_API_DEVICE_STATUS old_status; - WIMAX_API_STATUS_REASON reason; - WIMAX_API_CONNECTION_PROGRESS_INFO progress; -} StateChangeInfo; - -static gboolean -state_change_handler(gpointer user_data) -{ - StateChangeInfo *info = user_data; - - if (info->wmxsdk->state_change_cb) { - info->wmxsdk->state_change_cb(info->wmxsdk, - info->new_status, - info->old_status, - info->reason, - info->progress, - info->wmxsdk->callback_data); - } - wmxsdk_unref(info->wmxsdk); - memset(info, 0, sizeof(*info)); - free(info); - return FALSE; -} - -static void -_schedule_state_change(struct wmxsdk *wmxsdk, - WIMAX_API_DEVICE_STATUS new_status, - WIMAX_API_DEVICE_STATUS old_status, - WIMAX_API_STATUS_REASON reason, - WIMAX_API_CONNECTION_PROGRESS_INFO progress) -{ - StateChangeInfo *info; - - info = malloc(sizeof (*info)); - if (!info) - return; - - memset(info, 0, sizeof(*info)); - info->wmxsdk = wmxsdk; - info->new_status = new_status; - info->old_status = old_status; - info->reason = reason; - info->progress = progress; - - wmxsdk_ref(wmxsdk); - g_idle_add(state_change_handler, info); -} - -typedef struct { - struct wmxsdk *wmxsdk; - WIMAX_API_MEDIA_STATUS media_status; -} MediaStatusInfo; - -static gboolean -media_status_change_handler(gpointer user_data) -{ - MediaStatusInfo *info = user_data; - - if (info->wmxsdk->media_status_cb) { - info->wmxsdk->media_status_cb(info->wmxsdk, - info->media_status, - info->wmxsdk->callback_data); - } - wmxsdk_unref(info->wmxsdk); - memset(info, 0, sizeof(*info)); - free(info); - return FALSE; -} - -static void -_schedule_media_status_change(struct wmxsdk *wmxsdk, - WIMAX_API_MEDIA_STATUS media_status) -{ - MediaStatusInfo *info; - - info = malloc(sizeof (*info)); - if (!info) - return; - - memset(info, 0, sizeof(*info)); - info->wmxsdk = wmxsdk; - info->media_status = media_status; - - wmxsdk_ref(wmxsdk); - g_idle_add(media_status_change_handler, info); -} - -typedef struct { - struct wmxsdk *wmxsdk; - WIMAX_API_NETWORK_CONNECTION_RESP result; -} ConnectResultInfo; - -static gboolean -connect_result_handler(gpointer user_data) -{ - ConnectResultInfo *info = user_data; - - if (info->wmxsdk->connect_result_cb) { - info->wmxsdk->connect_result_cb(info->wmxsdk, - info->result, - info->wmxsdk->callback_data); - } - wmxsdk_unref(info->wmxsdk); - memset(info, 0, sizeof(*info)); - free(info); - return FALSE; -} - -static void -_schedule_connect_result(struct wmxsdk *wmxsdk, - WIMAX_API_NETWORK_CONNECTION_RESP resp) -{ - ConnectResultInfo *info; - - info = malloc(sizeof (*info)); - if (!info) - return; - - memset(info, 0, sizeof(*info)); - info->wmxsdk = wmxsdk; - info->result = resp; - - wmxsdk_ref(wmxsdk); - g_idle_add(connect_result_handler, info); -} - -typedef struct { - struct wmxsdk *wmxsdk; - WIMAX_API_NSP_INFO_EX *nsps; - guint num_nsps; -} ScanResultInfo; - -static gboolean -scan_result_handler(gpointer user_data) -{ - ScanResultInfo *info = user_data; - - if (info->wmxsdk->scan_result_cb) { - info->wmxsdk->scan_result_cb(info->wmxsdk, - info->nsps, - info->num_nsps, - info->wmxsdk->callback_data); - } - wmxsdk_unref(info->wmxsdk); - free(info->nsps); - memset(info, 0, sizeof(*info)); - free(info); - return FALSE; -} - -static void -_schedule_scan_result(struct wmxsdk *wmxsdk, - WIMAX_API_NSP_INFO_EX *nsps, - guint num_nsps) -{ - ScanResultInfo *info; - size_t nsps_size; - int i, tmp; - - info = malloc(sizeof (*info)); - if (!info) - return; - - memset(info, 0, sizeof(*info)); - info->wmxsdk = wmxsdk; - - nsps_size = num_nsps * sizeof (WIMAX_API_NSP_INFO_EX); - info->nsps = malloc(nsps_size); - memcpy(info->nsps, nsps, nsps_size); - info->num_nsps = num_nsps; - - /* CAPI may report link quality as zero -- if it does check if it is a bug - * by computing it based on CINR. If it is different, use the computed one. - */ - for (i = 0; i < num_nsps; i++) { - WIMAX_API_NSP_INFO_EX *nsp = &info->nsps[i]; - - if (nsp->linkQuality == 0) { - tmp = cinr_to_percentage(nsp->CINR - 10); - if (tmp != nsp->linkQuality) - nsp->linkQuality = tmp; - } - } - - wmxsdk_ref(wmxsdk); - g_idle_add(scan_result_handler, info); -} - -static gboolean -removed_handler(gpointer user_data) -{ - struct wmxsdk *wmxsdk = user_data; - - if (wmxsdk->removed_cb) - wmxsdk->removed_cb(wmxsdk, wmxsdk->callback_data); - wmxsdk_unref(wmxsdk); - return FALSE; -} - -static void -_schedule_removed(struct wmxsdk *wmxsdk) -{ - wmxsdk_ref(wmxsdk); - g_idle_add(removed_handler, wmxsdk); -} - -/****************************************************************/ - -/* - * Convert a WiMAX API status to an string. - */ -const char *iwmx_sdk_dev_status_to_str(WIMAX_API_DEVICE_STATUS status) -{ - switch (status) { - case WIMAX_API_DEVICE_STATUS_UnInitialized: - return "uninitialized"; - case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW: - return "rf off"; - case WIMAX_API_DEVICE_STATUS_RF_OFF_HW: - return "rf off (hard-block)"; - case WIMAX_API_DEVICE_STATUS_RF_OFF_SW: - return "rf off (soft-block)"; - case WIMAX_API_DEVICE_STATUS_Ready: - return "ready"; - case WIMAX_API_DEVICE_STATUS_Scanning: - return "scanning"; - case WIMAX_API_DEVICE_STATUS_Connecting: - return "connecting"; - case WIMAX_API_DEVICE_STATUS_Data_Connected: - return "connected"; - default: - return "unknown"; - } -} - -const char *iwmx_sdk_reason_to_str(WIMAX_API_STATUS_REASON reason) -{ - switch (reason) { - case WIMAX_API_STATUS_REASON_Normal: - return "normal"; - - /**< Failed to complete NW entry with the selected operator (unspecified reason). */ - case WIMAX_API_STATUS_REASON_Fail_to_connect_to_NW: - return "unspecified failure"; - - /**< Failed to complete ranging */ - case WIMAX_API_STATUS_REASON_Fail_to_connect_Ranging: - return "ranging failed"; - - /**< SBC phase failed */ - case WIMAX_API_STATUS_REASON_Fail_to_connect_SBC: - return "sbc failed"; - - /**< Security error. EAP authentication failed device level */ - case WIMAX_API_STATUS_REASON_Fail_to_connect_EAP_AUTH_Device: - return "EAP device auth failed"; - - /**< Security error. EAP authentication failed user level */ - case WIMAX_API_STATUS_REASON_Fail_to_connect_EAP_AUTH_user: - return "EAP user auth failed"; - - /**< Security error. Handshake failed */ - case WIMAX_API_STATUS_REASON_Fail_to_connect_3_Way_Handshake: - return "3 way handshake failed"; - - /**< Registration failed */ - case WIMAX_API_STATUS_REASON_Fail_to_connect_REG: - return "registration failed"; - - /**< Failed to initialize the data path (failed to perform DSA to one UL and one DL SFs). */ - case WIMAX_API_STATUS_REASON_Fail_to_connect_datapath: - return "datapath failed"; - - default: - return "unknown"; - } -} - -const char *iwmx_sdk_media_status_to_str(WIMAX_API_MEDIA_STATUS status) -{ - switch (status) { - case WIMAX_API_MEDIA_STATUS_LINK_UP: - return "link-up"; - case WIMAX_API_MEDIA_STATUS_LINK_DOWN: - return "link-down"; - case WIMAX_API_MEDIA_STATUS_LINK_RENEW: - return "link-renew"; - default: - return "unknown"; - } -} - -const char * -iwmx_sdk_con_progress_to_str(WIMAX_API_CONNECTION_PROGRESS_INFO progress) -{ - switch (progress) { - - /**< Device is in Ranging */ - case WIMAX_API_DEVICE_CONNECTION_PROGRESS_Ranging: - return "ranging"; - - /**< Device is in SBC */ - case WIMAX_API_DEVICE_CONNECTION_PROGRESS_SBC: - return "sbc"; - - /**< Device is in EAP authentication Device */ - case WIMAX_API_DEVICE_CONNECTION_PROGRESS_EAP_authentication_Device: - return "eap-auth-device"; - - /**< Device is in EAP authentication User */ - case WIMAX_API_DEVICE_CONNECTION_PROGRESS_EAP_authentication_User: - return "eap-auth-user"; - - /**< Device is in 3-way-handshake */ - case WIMAX_API_DEVICE_CONNECTION_PROGRESS_3_way_handshake: - return "3way-handshake"; - - /**< Device is in Registration */ - case WIMAX_API_DEVICE_CONNECTION_PROGRESS_Registration: - return "registration"; - - /**< Device is in De-registration */ - case WIMAX_API_DEVICE_CONNECTION_PROGRESS_De_registration: - return "deregistration"; - - /**< Device is registered (operational) */ - case WIMAX_API_DEVICE_CONNECTION_PROGRESS_Registered: - return "registered"; - - default: - return "unknown"; - } -} - -/* - * Get the device's status from the device - * - * Does NOT cache the result - * Does NOT trigger a state change in NetworkManager - * - * Returns < 0 errno code on error, status code if ok. - */ -static WIMAX_API_DEVICE_STATUS iwmx_sdk_get_device_status(struct wmxsdk *wmxsdk) -{ - WIMAX_API_RET r; - char errstr[512]; - UINT32 errstr_size = sizeof(errstr); - - WIMAX_API_DEVICE_STATUS dev_status; - WIMAX_API_CONNECTION_PROGRESS_INFO pi; - - r = GetDeviceStatus(&wmxsdk->device_id, &dev_status, &pi); - if (r != WIMAX_API_RET_SUCCESS) { - GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); - nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot read device state: %d (%s)", r, errstr); - dev_status = -EIO; - } - return dev_status; -} - -/* - * Get the device's status from the device but return a string describing it - * - * Same conditions as iwmx_sdk_get_device_status(). - */ -static const char *iwmx_sdk_get_device_status_str(struct wmxsdk *wmxsdk) -{ - const char *result; - WIMAX_API_DEVICE_STATUS dev_status; - - dev_status = iwmx_sdk_get_device_status(wmxsdk); - if ((int) dev_status < 0) - result = "cannot read device state"; - else - result = iwmx_sdk_dev_status_to_str(dev_status); - return result; -} - -/* - * If the device is connected but we don't know about the network, - * create the knowledge of it. - * - * Asks the WiMAX API to report which NSP we are connected to and we - * create/update a network_el in the device's network list. Then - * return it. - * - * Returns NULL on error. - * - */ -WIMAX_API_CONNECTED_NSP_INFO_EX *iwmx_sdk_get_connected_network(struct wmxsdk *wmxsdk) -{ - WIMAX_API_CONNECTED_NSP_INFO_EX *nsp_info = NULL; - WIMAX_API_RET r; - char errstr[512]; - UINT32 errstr_size = sizeof(errstr); - - nsp_info = malloc(sizeof (*nsp_info)); - if (!nsp_info) { - nm_log_err(LOGD_WIMAX, "wmxsdk: cannot allocate NSP info"); - return NULL; - } - - r = GetConnectedNSPEx(&wmxsdk->device_id, nsp_info); - if (r != WIMAX_API_RET_SUCCESS) { - GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); - nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot get connected NSP info: %d (%s)", r, errstr); - free (nsp_info); - nsp_info = NULL; - } else { - /* Migth be 0 sometimes; fix that up */ - if (nsp_info->linkQuality == 0) { - int linkq_expected = cinr_to_percentage(nsp_info->CINR - 10); - if (linkq_expected != nsp_info->linkQuality) - nsp_info->linkQuality = linkq_expected; - } - } - - return nsp_info; -} - -/* - * Asks the WiMAX API to report current link statistics. - * - * Returns NULL on error. - * - */ -WIMAX_API_LINK_STATUS_INFO_EX *iwmx_sdk_get_link_status_info(struct wmxsdk *wmxsdk) -{ - WIMAX_API_LINK_STATUS_INFO_EX *stats = NULL; - WIMAX_API_RET r; - char errstr[512]; - UINT32 errstr_size = sizeof(errstr); - - /* Only report if connected */ - if (iwmxsdk_status_get(wmxsdk) < WIMAX_API_DEVICE_STATUS_Connecting) { - nm_log_err(LOGD_WIMAX, "wmxsdk: cannot get link status info unless connected"); - return NULL; - } - - stats = malloc(sizeof (*stats)); - if (!stats) { - nm_log_err(LOGD_WIMAX, "wmxsdk: cannot allocate links status info"); - return NULL; - } - - r = GetLinkStatusEx(&wmxsdk->device_id, stats); - if (r != WIMAX_API_RET_SUCCESS) { - GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); - nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot get link status info: %d (%s)", r, errstr); - free (stats); - stats = NULL; - } - - return stats; -} - -/* - * Callback for a RF State command - * - * Called by the WiMAX API when a command sent to change the RF state - * is completed. This is just a confirmation of what happened with the - * command. - * - * We don't do anything, as when the device changes state, the state - * change callback is called and that will fiddle with the NetworkManager - * internals. - */ -static void __iwmx_sdk_rf_state_cb(WIMAX_API_DEVICE_ID *device_id, - WIMAX_API_RF_STATE rf_state) -{ - nm_log_dbg(LOGD_WIMAX, "rf_state changed to %d", rf_state); -} - -/* - * Turn the radio on or off - * - * First it checks that we are in the right state before doing - * anything; there might be no need to do anything. - * - * Issue a command to the WiMAX API, wait for a callback confirming it - * is done. Sometimes the callback is missed -- in that case, do force - * a state change evaluation. - * - * Frustration note: - * - * Geezoos efing Xist, they make difficult even the most simple - * of the operations - * - * This thing is definitely a pain. If the radio is ON already - * and you switch it on again...well, there is no way to tell - * because you don't get a callback saying it basically - * suceeded. But on the other hand, if the thing was in a - * different state and action needs to be taken, you have to wait - * for a callback to confirm it's done. However, there is also an - * state change callback, which is almost the same, so now you - * have to handle things in two "unrelated" threads of execution. - * - * How the shpx are you expected to tell the difference? Check - * status first? On timeout? Nice gap (eighteen wheeler size) for - * race conditions. - */ -int iwmx_sdk_rf_state_set(struct wmxsdk *wmxsdk, WIMAX_API_RF_STATE rf_state) -{ - int result; - - WIMAX_API_RET r; - char errstr[512]; - UINT32 errstr_size = sizeof(errstr); - WIMAX_API_DEVICE_STATUS dev_status; - - g_assert(rf_state == WIMAX_API_RF_ON || rf_state == WIMAX_API_RF_OFF); - - /* Guess what the current radio state is; if it is ON - * already, don't redo it. */ - dev_status = iwmx_sdk_get_device_status(wmxsdk); - if ((int) dev_status < 0) { - result = dev_status; - goto error_get_status; - } - switch (dev_status) { - case WIMAX_API_DEVICE_STATUS_UnInitialized: - result = -EINVAL; - goto error_cant_do; - case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW: - case WIMAX_API_DEVICE_STATUS_RF_OFF_HW: - nm_log_err(LOGD_WIMAX, "wmxsdk: cannot turn on radio: hw switch is off"); - result = -EPERM; - goto error_cant_do; - break; - case WIMAX_API_DEVICE_STATUS_RF_OFF_SW: - if (rf_state == WIMAX_API_RF_OFF) { - result = 0; - nm_log_dbg(LOGD_WIMAX, "radio is already off"); - goto out_done; - } - break; - case WIMAX_API_DEVICE_STATUS_Ready: - case WIMAX_API_DEVICE_STATUS_Scanning: - case WIMAX_API_DEVICE_STATUS_Connecting: - case WIMAX_API_DEVICE_STATUS_Data_Connected: - if (rf_state == WIMAX_API_RF_ON) { - result = 0; - nm_log_dbg(LOGD_WIMAX, "radio is already on"); - goto out_done; - } - break; - default: - g_assert(1); - } - /* Ok, flip the radio */ - r = CmdControlPowerManagement(&wmxsdk->device_id, rf_state); - if (r != WIMAX_API_RET_SUCCESS) { - GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); - nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot flip radio to %d: %d (%s) [device is in state %s]", - rf_state, r, errstr, iwmx_sdk_get_device_status_str(wmxsdk)); - result = -EIO; - } else - result = -EINPROGRESS; -out_done: -error_cant_do: -error_get_status: - return result; -} - -/* - * Read the cached device status - */ -WIMAX_API_DEVICE_STATUS iwmxsdk_status_get(struct wmxsdk *wmxsdk) -{ - WIMAX_API_DEVICE_STATUS status; - - g_mutex_lock(&wmxsdk->status_mutex); - status = wmxsdk->status; - g_mutex_unlock(&wmxsdk->status_mutex); - return status; -} - -/* - * Callback for a Connect command - * - * Called by the WiMAX API when a command sent to connect is - * completed. This is just a confirmation of what happened with the - * command. - * - * WE DON'T DO MUCH HERE -- the real meat happens when a state change - * callback is sent, where we detect we move to connected state (or - * from disconnecting to something else); the state change callback is - * called and that will fiddle with the NetworkManager internals. - */ -static void __iwmx_sdk_connect_cb(WIMAX_API_DEVICE_ID *device_id, - WIMAX_API_NETWORK_CONNECTION_RESP resp) -{ - WIMAX_API_DEVICE_STATUS status; - struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id); - - status = iwmxsdk_status_get(wmxsdk); - if (resp == WIMAX_API_CONNECTION_SUCCESS) { - if (status != WIMAX_API_DEVICE_STATUS_Data_Connected) { - nm_log_err(LOGD_WIMAX, "wmxsdk: error: connect worked, but state" - " didn't change (now it is %d [%s])", - status, - iwmx_sdk_dev_status_to_str(status)); - } - } else { - nm_log_err(LOGD_WIMAX, "wmxsdk: failed to connect (status %d: %s)", - status, iwmx_sdk_dev_status_to_str(status)); - } - - _schedule_connect_result(wmxsdk, resp); -} - -/* - * Connect to a network - * - * This function starts the connection process to a given network; - * when the device changes status, the status change callback will - * tell NetworkManager if the network is finally connected or not. - * - * One of the reasons it is done like that is to allow external tools - * to control the device and the plugin just passing the status so - * NetworkManager displays the right info. - */ -int iwmx_sdk_connect(struct wmxsdk *wmxsdk, const char *nsp_name) -{ - int result = 0; - - WIMAX_API_RET r; - char errstr[512]; - UINT32 errstr_size = sizeof(errstr); - WIMAX_API_DEVICE_STATUS dev_status; - char sdk_name[MAX_SIZE_OF_NSP_NAME]; - - g_mutex_lock(&wmxsdk->connect_mutex); - /* Guess what the current radio state is; if it is ON - * already, don't redo it. */ - dev_status = iwmxsdk_status_get(wmxsdk); - if ((int) dev_status < 0) { - result = dev_status; - goto error_get_status; - } - switch (dev_status) { - case WIMAX_API_DEVICE_STATUS_UnInitialized: - nm_log_err(LOGD_WIMAX, "wmxsdk: SW BUG? HW is uninitialized"); - result = -EINVAL; - goto error_cant_do; - case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW: - case WIMAX_API_DEVICE_STATUS_RF_OFF_HW: - case WIMAX_API_DEVICE_STATUS_RF_OFF_SW: - nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot connect: radio is off"); - result = -EPERM; - goto error_cant_do; - case WIMAX_API_DEVICE_STATUS_Ready: - case WIMAX_API_DEVICE_STATUS_Scanning: - break; - case WIMAX_API_DEVICE_STATUS_Connecting: - nm_log_dbg(LOGD_WIMAX, "Connect already pending, waiting for it"); - result = -EINPROGRESS; - goto error_cant_do; - case WIMAX_API_DEVICE_STATUS_Data_Connected: - nm_log_err(LOGD_WIMAX, "wmxsdk: BUG? need to disconnect?"); - result = -EINVAL; - goto error_cant_do; - default: - g_assert(1); - } - - /* The SDK treats the network name as wchar_t* while the contents are - * actually just UTF-8... WTF? Hand it a full buffer to work around - * boundary cases where the NSP name contains an odd # of characters. - */ - memset(sdk_name, 0, sizeof (sdk_name)); - memcpy(sdk_name, nsp_name, strlen (nsp_name)); - - /* Ok, do the connection, wait for a callback */ - r = CmdConnectToNetwork(&wmxsdk->device_id, &sdk_name[0], 0, 0); - if (r != WIMAX_API_RET_SUCCESS) { - GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); - nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot connect to network %s: %d (%s) - device is in state '%s'", - nsp_name, r, errstr, - iwmx_sdk_get_device_status_str(wmxsdk)); - result = -EIO; - } - -error_cant_do: -error_get_status: - g_mutex_unlock(&wmxsdk->connect_mutex); - return result; -} - -/* - * Callback for a Disconnect command - * - * Called by the WiMAX API when a command sent to connect is - * completed. This is just a confirmation of what happened with the - * command. - * - * When the device changes state, the state change callback is called - * and that will fiddle with the NetworkManager internals. - * - * We just update the result of the command and wake up anybody who is - * waiting for this conditional variable. - */ -static void __iwmx_sdk_disconnect_cb(WIMAX_API_DEVICE_ID *device_id, - WIMAX_API_NETWORK_CONNECTION_RESP resp) -{ - struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id); - WIMAX_API_DEVICE_STATUS status; - - status = iwmxsdk_status_get(wmxsdk); - if (resp == WIMAX_API_CONNECTION_SUCCESS) { - if (status == WIMAX_API_DEVICE_STATUS_Data_Connected) { - nm_log_err(LOGD_WIMAX, "wmxsdk: error: disconnect worked, " - "but state didn't change (now it is %d [%s])", status, - iwmx_sdk_dev_status_to_str(status)); - } - } else - nm_log_err(LOGD_WIMAX, "wmxsdk: failed to disconnect (status %d: %s)", - status, iwmx_sdk_dev_status_to_str(status)); -} - -/* - * Disconnect from a network - * - * This function tells the device to disconnect; the state change - * callback will take care of inform NetworkManager's internals. - */ -int iwmx_sdk_disconnect(struct wmxsdk *wmxsdk) -{ - int result; - - WIMAX_API_RET r; - char errstr[512]; - UINT32 errstr_size = sizeof(errstr); - WIMAX_API_DEVICE_STATUS dev_status; - - g_mutex_lock(&wmxsdk->connect_mutex); - /* Guess what the current radio state is; if it is ON - * already, don't redo it. */ - dev_status = iwmx_sdk_get_device_status(wmxsdk); - if ((int) dev_status < 0) { - result = dev_status; - goto error_get_status; - } - switch (dev_status) { - case WIMAX_API_DEVICE_STATUS_UnInitialized: - nm_log_err(LOGD_WIMAX, "wmxsdk: SW BUG? HW is uninitialized"); - result = -EINVAL; - goto error_cant_do; - case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW: - case WIMAX_API_DEVICE_STATUS_RF_OFF_HW: - case WIMAX_API_DEVICE_STATUS_RF_OFF_SW: - nm_log_dbg(LOGD_WIMAX, "Cannot disconnect, radio is off; ignoring"); - result = 0; - goto error_cant_do; - case WIMAX_API_DEVICE_STATUS_Ready: - case WIMAX_API_DEVICE_STATUS_Scanning: - nm_log_dbg(LOGD_WIMAX, "Cannot disconnect, already disconnected; ignoring"); - result = 0; - goto error_cant_do; - case WIMAX_API_DEVICE_STATUS_Connecting: - case WIMAX_API_DEVICE_STATUS_Data_Connected: - break; - default: - g_assert(1); - } - /* Ok, flip the radio */ - r = CmdDisconnectFromNetwork(&wmxsdk->device_id); - if (r != WIMAX_API_RET_SUCCESS) { - GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); - nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot disconnect from network: %d (%s)", r, errstr); - result = -EIO; - } else - result = -EINPROGRESS; -error_cant_do: -error_get_status: - g_mutex_unlock(&wmxsdk->connect_mutex); - return result; -} - -/* - * Turn fast reconnect capability on/off - * - * This function tells wimaxd to turn fast reconnect on or off. - */ -int iwmx_sdk_set_fast_reconnect_enabled(struct wmxsdk *wmxsdk, int enabled) -{ - WIMAX_API_RET r; - char errstr[512]; - UINT32 errstr_size = sizeof(errstr); - - r = SetFastReconnectCapabilityStatus(&wmxsdk->device_id, !!enabled); - if (r != WIMAX_API_RET_SUCCESS) { - GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); - nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot set fast reconnect to %d: %d (%s)", - enabled, r, errstr); - return -EIO; - } - return 0; -} - -static void __iwmx_sdk_media_status_update_cb (WIMAX_API_DEVICE_ID_P device_id, - WIMAX_API_MEDIA_STATUS mediaStatus) -{ - struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id); - - /* Ignore redundant LINK_UP events */ - if ( mediaStatus == WIMAX_API_MEDIA_STATUS_LINK_UP - && wmxsdk->media_status == WIMAX_API_MEDIA_STATUS_LINK_UP) - return; - - wmxsdk->media_status = mediaStatus; - - nm_log_dbg(LOGD_WIMAX, "wmxsdk: media status change to (%d) %s", - mediaStatus, iwmx_sdk_media_status_to_str (mediaStatus)); - - _schedule_media_status_change(wmxsdk, mediaStatus); -} - -/* - * Callback for state change messages - * - * Just pass them to the state transition handler - */ -static void __iwmx_sdk_state_change_cb(WIMAX_API_DEVICE_ID *device_id, - WIMAX_API_DEVICE_STATUS status, - WIMAX_API_STATUS_REASON reason, - WIMAX_API_CONNECTION_PROGRESS_INFO pi) -{ - struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id); - WIMAX_API_DEVICE_STATUS old_status; - - nm_log_dbg(LOGD_WIMAX, "wmxsdk: state change to (%d) %s reason (%d) %s", - status, iwmx_sdk_dev_status_to_str (status), - reason, iwmx_sdk_reason_to_str (reason)); - - g_mutex_lock(&wmxsdk->status_mutex); - old_status = wmxsdk->status; - wmxsdk->status = status; - g_mutex_unlock(&wmxsdk->status_mutex); - - _schedule_state_change(wmxsdk, status, old_status, reason, pi); -} - -/* - * Called by _iwmx_sdk_*scan_cb() when [wide or preferred] scan results - * are available. - * - * From here we update NetworkManager's idea of which networks are available. - */ -static void __iwmx_sdk_scan_common_cb(WIMAX_API_DEVICE_ID *device_id, - WIMAX_API_NSP_INFO_EX *nsp_list, - UINT32 nsp_list_size) -{ - struct wmxsdk *wmxsdk = deviceid_to_wmxsdk(device_id); - - g_mutex_lock(&wmxsdk->network_mutex); - _schedule_scan_result(wmxsdk, nsp_list, nsp_list_size); - g_mutex_unlock(&wmxsdk->network_mutex); -} - -/* - * Called by the WiMAX API when we get a wide scan result - * - * We treat them same as wide, so we just call that. - */ -static void __iwmx_sdk_wide_scan_cb(WIMAX_API_DEVICE_ID *device_id, - WIMAX_API_NSP_INFO_EX *nsp_list, - UINT32 nsp_list_size) -{ - __iwmx_sdk_scan_common_cb(device_id, nsp_list, nsp_list_size); -} - -/* - * Called by the WiMAX API when we get a normal (non wide) scan result - * - * We treat them same as wide, so we just call that. - */ -static void __iwmx_sdk_scan_cb(WIMAX_API_DEVICE_ID *device_id, - WIMAX_API_NSP_INFO_EX *nsp_list, - UINT32 nsp_list_size, UINT32 searchProgress) -{ - __iwmx_sdk_scan_common_cb(device_id, nsp_list, nsp_list_size); -} - -/* - * Called to ask the device to scan for networks - * - * We don't really scan as the WiMAX SDK daemon scans in the - * background for us. We just get the results and hand them back via - * the scan_result_cb callback. - */ -int iwmx_sdk_get_networks(struct wmxsdk *wmxsdk) -{ - int result; - - UINT32 nsp_list_length = 10; - WIMAX_API_NSP_INFO_EX nsp_list[10]; /* FIXME: up to 32? */ - - WIMAX_API_RET r; - char errstr[512]; - UINT32 errstr_size = sizeof(errstr); - - r = GetNetworkListEx(&wmxsdk->device_id, nsp_list, &nsp_list_length); - if (r != WIMAX_API_RET_SUCCESS) { - GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); - nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot get network list: %d (%s)", r, errstr); - result = -EIO; - goto error_scan; - } - - if (nsp_list_length == 0) { - nm_log_dbg(LOGD_WIMAX, "no networks"); - } else - __iwmx_sdk_scan_common_cb(&wmxsdk->device_id, nsp_list, - nsp_list_length); - result = 0; -error_scan: - return result; -} - -/* - * Initialize the WiMAX API, register with it, setup callbacks - * - */ -static int iwmx_sdk_setup(struct wmxsdk *wmxsdk) -{ - int result, status; - - WIMAX_API_RET r; - - char errstr[512]; - UINT32 errstr_size = sizeof(errstr); - - result = -ENFILE; - - /* device_id initialized by iwmx_sdk_dev_add */ - - r = WiMaxDeviceOpen(&wmxsdk->device_id); - if (r != WIMAX_API_RET_SUCCESS) { - GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); - nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot open device: %d (%s)", r, errstr); - goto error_wimaxdeviceopen; - } - - /* - * We scan in auto mode (in the background) - * - * Otherwise is messy -- if we have NetworkManager triggering a scan - * when we call iwmx_nm_scan() -> iwmx_sdk_scan(), most of the - * times that causes a race condition when the UI asks for a - * scan right before displaying the network menu. As there is - * no way to cancel an ongoing scan before connecting, we are - * stuck. So we do auto bg and have iwmx_sdk_scan() just return - * the current network list. - */ - r = SetConnectionMode(&wmxsdk->device_id, - WIMAX_API_CONNECTION_AUTO_SCAN_MANUAL_CONNECT); - if (r != WIMAX_API_RET_SUCCESS) { - GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); - nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot set connectin mode to manual: %d (%s)", r, errstr); - goto error_connection_mode; - } - - r = SubscribeControlPowerManagement(&wmxsdk->device_id, - __iwmx_sdk_rf_state_cb); - if (r != WIMAX_API_RET_SUCCESS) { - GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); - nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to radio change events: %u (%s)", r, errstr); - result = -EIO; - goto error_subscribe_rf_state; - } - - r = SubscribeDeviceStatusChange(&wmxsdk->device_id, - __iwmx_sdk_state_change_cb); - if (r != WIMAX_API_RET_SUCCESS) { - GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); - nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to state chaneg events: %d (%s)", r, errstr); - goto error_subscribe_state_change; - } - - r = SubscribeNetworkSearchWideScanEx(&wmxsdk->device_id, - __iwmx_sdk_wide_scan_cb); - if (r != WIMAX_API_RET_SUCCESS) { - GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); - nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to wide scan events: %d (%s)", r, errstr); - goto error_subscribe_wide_scan; - } - r = SubscribeNetworkSearchEx(&wmxsdk->device_id, __iwmx_sdk_scan_cb); - if (r != WIMAX_API_RET_SUCCESS) { - GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); - nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to scan events: %d (%s)", r, errstr); - goto error_subscribe_scan; - } - - r = SubscribeConnectToNetwork(&wmxsdk->device_id, - __iwmx_sdk_connect_cb); - if (r != WIMAX_API_RET_SUCCESS) { - GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); - nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to connect events: %d (%s)", r, errstr); - goto error_subscribe_connect; - } - - r = SubscribeDisconnectToNetwork(&wmxsdk->device_id, - __iwmx_sdk_disconnect_cb); - if (r != WIMAX_API_RET_SUCCESS) { - GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); - nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to disconnect events: %d (%s)", r, errstr); - goto error_subscribe_disconnect; - } - - r = SubscribeMediaStatusUpdate(&wmxsdk->device_id, __iwmx_sdk_media_status_update_cb); - if (r != WIMAX_API_RET_SUCCESS) { - GetErrorString(&wmxsdk->device_id, r, errstr, &errstr_size); - nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot subscribe to media status events: %d (%s)", r, errstr); - goto error_subscribe_media_status; - } - - status = iwmx_sdk_get_device_status(wmxsdk); - if ((int) status < 0) - status = WIMAX_API_DEVICE_STATUS_UnInitialized; - - g_mutex_lock(&wmxsdk->status_mutex); - wmxsdk->status = status; - g_mutex_unlock(&wmxsdk->status_mutex); - - _schedule_state_change(wmxsdk, - status, - WIMAX_API_DEVICE_STATUS_UnInitialized, - WIMAX_API_STATUS_REASON_Normal, - WIMAX_API_DEVICE_CONNECTION_PROGRESS_Ranging); - - return 0; - - UnsubscribeMediaStatusUpdate(&wmxsdk->device_id); -error_subscribe_media_status: - UnsubscribeDisconnectToNetwork(&wmxsdk->device_id); -error_subscribe_disconnect: - UnsubscribeConnectToNetwork(&wmxsdk->device_id); -error_subscribe_connect: - UnsubscribeNetworkSearchEx(&wmxsdk->device_id); -error_subscribe_scan: - UnsubscribeNetworkSearchWideScanEx(&wmxsdk->device_id); -error_subscribe_wide_scan: - UnsubscribeDeviceStatusChange(&wmxsdk->device_id); -error_subscribe_state_change: - UnsubscribeControlPowerManagement(&wmxsdk->device_id); -error_subscribe_rf_state: -error_connection_mode: - WiMaxDeviceClose(&wmxsdk->device_id); -error_wimaxdeviceopen: - return result; -} - -/* - * Called when a device is torn down - * - * Cleanup all that is done in iwmx_sdk_setup(). Remove callbacks, - * unregister from the WiMAX API. - */ -static void iwmx_sdk_remove(struct wmxsdk *wmxsdk) -{ - UnsubscribeMediaStatusUpdate(&wmxsdk->device_id); - UnsubscribeDisconnectToNetwork(&wmxsdk->device_id); - UnsubscribeConnectToNetwork(&wmxsdk->device_id); - UnsubscribeNetworkSearchEx(&wmxsdk->device_id); - UnsubscribeNetworkSearchWideScanEx(&wmxsdk->device_id); - UnsubscribeDeviceStatusChange(&wmxsdk->device_id); - UnsubscribeControlPowerManagement(&wmxsdk->device_id); - WiMaxDeviceClose(&wmxsdk->device_id); -} - -void iwmx_sdk_set_callbacks(struct wmxsdk *wmxsdk, - WimaxStateChangeFunc state_change_cb, - WimaxMediaStatusFunc media_status_cb, - WimaxConnectResultFunc connect_result_cb, - WimaxScanResultFunc scan_result_cb, - WimaxRemovedFunc removed_cb, - void *user_data) -{ - wmxsdk->state_change_cb = state_change_cb; - wmxsdk->media_status_cb = media_status_cb; - wmxsdk->connect_result_cb = connect_result_cb; - wmxsdk->scan_result_cb = scan_result_cb; - wmxsdk->removed_cb = removed_cb; - wmxsdk->callback_data = user_data; -} - -/* Initialize a [zeroed] struct wmxsdk */ -static struct wmxsdk *wmxsdk_new(void) -{ - struct wmxsdk *wmxsdk; - - wmxsdk = malloc(sizeof(*wmxsdk)); - if (wmxsdk) { - memset(wmxsdk, 0, sizeof(*wmxsdk)); - - wmxsdk->refcount = 1; - g_mutex_init(&wmxsdk->network_mutex); - - wmxsdk->status = WIMAX_API_DEVICE_STATUS_UnInitialized; - g_mutex_init(&wmxsdk->status_mutex); - - g_mutex_init(&wmxsdk->connect_mutex); - } - return wmxsdk; -} - -struct wmxsdk *wmxsdk_ref(struct wmxsdk *wmxsdk) -{ - g_atomic_int_add(&wmxsdk->refcount, 1); - return wmxsdk; -} - -void wmxsdk_unref(struct wmxsdk *wmxsdk) -{ - if (g_atomic_int_dec_and_test(&wmxsdk->refcount)) { - g_mutex_clear(&wmxsdk->status_mutex); - g_mutex_clear(&wmxsdk->connect_mutex); - memset(wmxsdk, 0, sizeof(*wmxsdk)); - free(wmxsdk); - } -} - -static void iwmx_sdk_dev_add(unsigned idx, unsigned api_idx, const char *name) -{ - struct wmxsdk *wmxsdk; - const char *s; - - if (idx >= IWMX_SDK_DEV_MAX) { - nm_log_err(LOGD_WIMAX, "BUG! idx (%u) >= IWMX_SDK_DEV_MAX (%u)", idx, IWMX_SDK_DEV_MAX); - return; - } - if (g_iwmx_sdk_devs[idx] != NULL) { - nm_log_err(LOGD_WIMAX, "BUG! device index %u already enumerated?", idx); - return; - } - - wmxsdk = wmxsdk_new(); - if (wmxsdk == NULL) { - nm_log_err(LOGD_WIMAX, "Can't allocate %zu bytes", sizeof(*wmxsdk)); - return; - } - - /* - * This depends on a hack in the WiMAX Network Service; it has - * to return, as part of the device name, a string "if:IFNAME" - * where the OS's device name is stored. - */ - s = strstr(name, "if:"); - if (s == NULL - || sscanf(s, "if:%15[^ \f\n\r\t\v]", wmxsdk->ifname) != 1) { - nm_log_err(LOGD_WIMAX, "Cannot extract network interface name off '%s'", - name); - goto error; - } - nm_log_dbg(LOGD_WIMAX, "network interface name: '%s'", wmxsdk->ifname); - - strncpy(wmxsdk->name, name, sizeof(wmxsdk->name)); - wmxsdk->device_id.privilege = WIMAX_API_PRIVILEGE_READ_WRITE; - wmxsdk->device_id.deviceIndex = api_idx; - - if (iwmx_sdk_setup(wmxsdk) != 0) { - nm_log_err(LOGD_WIMAX, "wxmsdk: %s: cannot set up interface", wmxsdk->ifname); - goto error; - } - - g_iwmx_sdk_devs[idx] = wmxsdk; - - /* Notify listeners of new devices */ - iwmx_sdk_call_new_callbacks (wmxsdk); - return; - -error: - wmxsdk_unref(wmxsdk); - return; -} - -static void iwmx_sdk_dev_rm(unsigned idx) -{ - struct wmxsdk *wmxsdk; - - if (idx >= IWMX_SDK_DEV_MAX) { - nm_log_err(LOGD_WIMAX, "BUG! idx (%u) >= IWMX_SDK_DEV_MAX (%u)", idx, IWMX_SDK_DEV_MAX); - return; - } - - wmxsdk = g_iwmx_sdk_devs[idx]; - _schedule_removed(wmxsdk); - iwmx_sdk_remove(wmxsdk); - wmxsdk_unref(wmxsdk); - g_iwmx_sdk_devs[idx] = NULL; -} - -static void iwmx_sdk_addremove_cb(WIMAX_API_DEVICE_ID *devid, - BOOL presence) -{ - unsigned int cnt; - WIMAX_API_RET r; - WIMAX_API_HW_DEVICE_ID device_id_list[5]; - UINT32 device_id_list_size = ARRAY_SIZE(device_id_list); - char errstr[512]; - UINT32 errstr_size = sizeof(errstr); - - g_mutex_lock(&add_remove_mutex); - - nm_log_dbg(LOGD_WIMAX, "cb: handle %u index #%u is %d", devid->sdkHandle, - devid->deviceIndex, presence); - - r = GetListDevice(devid, device_id_list, &device_id_list_size); - if (r != WIMAX_API_RET_SUCCESS) { - GetErrorString(devid, r, errstr, &errstr_size); - nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot obtain list of devices: %d (%s)", r, errstr); - goto out; - } - - if (device_id_list_size == 0) { - nm_log_dbg(LOGD_WIMAX, "No WiMAX devices reported"); - } else { - for (cnt = 0; cnt < device_id_list_size; cnt++) { - WIMAX_API_HW_DEVICE_ID *dev = - device_id_list + cnt; - nm_log_dbg(LOGD_WIMAX, "#%u index #%u device %s", cnt, - dev->deviceIndex, dev->deviceName); - } - } - - if (presence) { - WIMAX_API_HW_DEVICE_ID *dev; - - /* Make sure the wimax NS isn't lying to us */ - if (device_id_list_size < devid->deviceIndex) { - nm_log_err(LOGD_WIMAX, "wmxsdk: changed device (%u) not in the list? (%u items)", - devid->deviceIndex, device_id_list_size); - goto out; - } - - /* Add the device to our internal list */ - dev = device_id_list + devid->deviceIndex; - iwmx_sdk_dev_add(devid->deviceIndex, dev->deviceIndex, dev->deviceName); - } else { - /* Remove the device from our internal list */ - int idx = deviceid_to_index(devid); - - if (idx >= 0) - iwmx_sdk_dev_rm(idx); - } - -out: - g_mutex_unlock(&add_remove_mutex); -} - -/* - * Initialize the WiMAX API, register with it, setup callbacks for - * device coming up / dissapearing - */ -int iwmx_sdk_api_init(void) -{ - int result; - unsigned int cnt; - WIMAX_API_RET r; - char errstr[512]; - UINT32 errstr_size = sizeof(errstr); - - WIMAX_API_HW_DEVICE_ID device_id_list[5]; - UINT32 device_id_list_size = ARRAY_SIZE(device_id_list); - - memset(&g_api, 0, sizeof(g_api)); - g_api.privilege = WIMAX_API_PRIVILEGE_READ_WRITE; - - result = -EIO; - r = WiMaxAPIOpen(&g_api); - if (r != WIMAX_API_RET_SUCCESS) { - GetErrorString(&g_api, r, errstr, &errstr_size); - nm_log_err(LOGD_WIMAX, "wmxsdk: WiMaxAPIOpen failed with %d (%s)", r, errstr); - goto error_wimaxapiopen; - } - - r = SubscribeDeviceInsertRemove(&g_api, iwmx_sdk_addremove_cb); - if (r != WIMAX_API_RET_SUCCESS) { - GetErrorString(&g_api, r, errstr, &errstr_size); - nm_log_err(LOGD_WIMAX, "wmxsdk: insert/remove subscribe failed with %d (%s)", r, errstr); - goto error_close; - } - - r = GetListDevice(&g_api, device_id_list, &device_id_list_size); - if (r != WIMAX_API_RET_SUCCESS) { - GetErrorString(&g_api, r, errstr, &errstr_size); - nm_log_err(LOGD_WIMAX, "wmxsdk: Cannot obtain list of devices: %d (%s)", r, errstr); - goto error_close; - } - if (device_id_list_size < g_api.deviceIndex) { - nm_log_err(LOGD_WIMAX, "wmxsdk: changed device (%u) not in the list? (%u items)", - g_api.deviceIndex, device_id_list_size); - } - - if (device_id_list_size == 0) { - nm_log_dbg(LOGD_WIMAX, "No WiMAX devices reported"); - } else { - for (cnt = 0; cnt < device_id_list_size; cnt++) { - WIMAX_API_HW_DEVICE_ID *dev = device_id_list + cnt; - nm_log_dbg(LOGD_WIMAX, "#%u index #%u device %s", cnt, dev->deviceIndex, dev->deviceName); - iwmx_sdk_dev_add(cnt, dev->deviceIndex, dev->deviceName); - } - } - return 0; - -error_close: - WiMaxAPIClose(&g_api); -error_wimaxapiopen: - return result; -} - -void iwmx_sdk_api_exit(void) -{ - WIMAX_API_RET r; - - char errstr[512]; - UINT32 errstr_size = sizeof(errstr); - - r = WiMaxAPIClose(&g_api); - if (r != WIMAX_API_RET_SUCCESS) { - GetErrorString(&g_api, r, errstr, &errstr_size); - nm_log_err(LOGD_WIMAX, "wmxsdk: WiMaxAPIClose failed with %d (%s)", r, errstr); - } - return; -} diff --git a/src/devices/wimax/iwmxsdk.h b/src/devices/wimax/iwmxsdk.h deleted file mode 100644 index c8e76696..00000000 --- a/src/devices/wimax/iwmxsdk.h +++ /dev/null @@ -1,112 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* - * - * Copyright (C) 2011 Red Hat, Inc. All rights reserved. - * Copyright (C) 2007-2010 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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 St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifndef __IWMXSDK_H__ -#define __IWMXSDK_H__ - -#include "nm-wimax-util.h" - -#include <wimax/WiMaxTypesEx.h> -#include <wimax/WiMaxAPIEx.h> - -struct wmxsdk; - -typedef void (*WimaxNewWmxsdkFunc) (struct wmxsdk *wmxsdk, void *user_data); - -typedef void (*WimaxStateChangeFunc) (struct wmxsdk *wmxsdk, - WIMAX_API_DEVICE_STATUS new_status, - WIMAX_API_DEVICE_STATUS old_status, - WIMAX_API_STATUS_REASON reason, - WIMAX_API_CONNECTION_PROGRESS_INFO info, - void *user_data); - -typedef void (*WimaxMediaStatusFunc) (struct wmxsdk *wmxsdk, - WIMAX_API_MEDIA_STATUS media_status, - void *user_data); - -typedef void (*WimaxConnectResultFunc) (struct wmxsdk *wmxsdk, - WIMAX_API_NETWORK_CONNECTION_RESP resp, - void *user_data); - -typedef void (*WimaxScanResultFunc) (struct wmxsdk *wmxsdk, - WIMAX_API_NSP_INFO_EX *nsps, - guint num_nsps, - void *user_data); - -typedef void (*WimaxRemovedFunc) (struct wmxsdk *wmxsdk, void *user_data); - -struct wmxsdk { - gint refcount; - - WIMAX_API_DEVICE_ID device_id; - - WimaxStateChangeFunc state_change_cb; - WimaxMediaStatusFunc media_status_cb; - WimaxConnectResultFunc connect_result_cb; - WimaxScanResultFunc scan_result_cb; - WimaxRemovedFunc removed_cb; - void *callback_data; - - GMutex network_mutex; - - WIMAX_API_DEVICE_STATUS status; - WIMAX_API_MEDIA_STATUS media_status; - GMutex status_mutex; - - GMutex connect_mutex; - - char name[100]; - char ifname[16]; -}; - -struct wmxsdk *iwmx_sdk_get_wmxsdk_for_iface(const char *iface); - -struct wmxsdk *wmxsdk_ref(struct wmxsdk *wmxsdk); -void wmxsdk_unref(struct wmxsdk *wmxsdk); - -/* Register/unregister callbacks when a new wmxsdk is set up */ -void iwmx_sdk_new_callback_register(WimaxNewWmxsdkFunc callback, void *user_data); -void iwmx_sdk_new_callback_unregister(WimaxNewWmxsdkFunc callback, void *user_data); - -void iwmx_sdk_set_callbacks(struct wmxsdk *wmxsdk, - WimaxStateChangeFunc state_change_cb, - WimaxMediaStatusFunc media_status_func, - WimaxConnectResultFunc connect_result_cb, - WimaxScanResultFunc scan_result_cb, - WimaxRemovedFunc removed_cb, - void *user_data); - -WIMAX_API_DEVICE_STATUS iwmxsdk_status_get(struct wmxsdk *wmxsdk); -int iwmx_sdk_connect(struct wmxsdk *wmxsdk, const char *nsp_name); -int iwmx_sdk_disconnect(struct wmxsdk *wmxsdk); -int iwmx_sdk_set_fast_reconnect_enabled(struct wmxsdk *wmxsdk, int enabled); -WIMAX_API_CONNECTED_NSP_INFO_EX *iwmx_sdk_get_connected_network(struct wmxsdk *wmxsdk); -WIMAX_API_LINK_STATUS_INFO_EX *iwmx_sdk_get_link_status_info(struct wmxsdk *wmxsdk); -const char *iwmx_sdk_dev_status_to_str(WIMAX_API_DEVICE_STATUS status); -const char *iwmx_sdk_reason_to_str(WIMAX_API_STATUS_REASON reason); -const char *iwmx_sdk_media_status_to_str(WIMAX_API_MEDIA_STATUS status); -const char *iwmx_sdk_con_progress_to_str(WIMAX_API_CONNECTION_PROGRESS_INFO progress); -int iwmx_sdk_rf_state_set(struct wmxsdk *wmxsdk, WIMAX_API_RF_STATE rf_state); -int iwmx_sdk_get_networks(struct wmxsdk *wmxsdk); -int iwmx_sdk_api_init(void); -void iwmx_sdk_api_exit(void); - -#endif /* __IWMXSDK_H__ */ diff --git a/src/devices/wimax/nm-device-wimax.c b/src/devices/wimax/nm-device-wimax.c deleted file mode 100644 index 0c8f1cbb..00000000 --- a/src/devices/wimax/nm-device-wimax.c +++ /dev/null @@ -1,1416 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2010 - 2011 Red Hat, Inc. - * Copyright (C) 2009 Novell, Inc. - */ - -#include "config.h" - -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <sys/ioctl.h> -#include <sys/socket.h> - -#include <glib/gi18n.h> - -#include "nm-wimax-util.h" - -#include <WiMaxAPI.h> -#include <WiMaxAPIEx.h> - -#include "nm-device-wimax.h" -#include "nm-wimax-util.h" -#include "nm-logging.h" -#include "nm-device-private.h" -#include "NetworkManagerUtils.h" -#include "nm-active-connection.h" -#include "nm-dbus-manager.h" -#include "nm-connection.h" -#include "nm-platform.h" -#include "nm-setting-connection.h" -#include "nm-setting-wimax.h" -#include "nm-utils.h" -#include "nm-rfkill-manager.h" -#include "iwmxsdk.h" -#include "nm-enum-types.h" -#include "nm-dbus-glib-types.h" - -static gboolean impl_device_get_nsp_list (NMDeviceWimax *device, GPtrArray **list, GError **error); - -#include "nm-device-wimax-glue.h" - -G_DEFINE_TYPE (NMDeviceWimax, nm_device_wimax, NM_TYPE_DEVICE) - -enum { - PROP_0, - PROP_NSPS, - PROP_ACTIVE_NSP, - PROP_CENTER_FREQ, - PROP_RSSI, - PROP_CINR, - PROP_TX_POWER, - PROP_BSID, - - LAST_PROP -}; - -enum { - NSP_ADDED, - NSP_REMOVED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -#define NM_DEVICE_WIMAX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ - NM_TYPE_DEVICE_WIMAX, \ - NMDeviceWimaxPrivate)) - -typedef struct { - gboolean disposed; - - struct wmxsdk *sdk; - WIMAX_API_DEVICE_STATUS status; - gboolean connect_failed; - - gboolean enabled; - gboolean wimaxd_enabled; - guint activation_timeout_id; - - /* Track whether stage1 (Prepare) is completed yet or not */ - gboolean prepare_done; - - guint sdk_action_defer_id; - - guint link_timeout_id; - guint poll_id; - - GSList *nsp_list; - NMWimaxNsp *current_nsp; - - /* interesting stuff when connected */ - guint center_freq; - gint rssi; - gint cinr; - gint tx_power; - char *bsid; -} NMDeviceWimaxPrivate; - -/***********************************************************/ - -static gboolean -impl_device_get_nsp_list (NMDeviceWimax *self, GPtrArray **nsps, GError **error) -{ - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - GSList *iter; - - *nsps = g_ptr_array_sized_new (4); - for (iter = priv->nsp_list; iter; iter = iter->next) - g_ptr_array_add (*nsps, g_strdup (nm_wimax_nsp_get_dbus_path (NM_WIMAX_NSP (iter->data)))); - - return TRUE; -} - -static void -set_current_nsp (NMDeviceWimax *self, NMWimaxNsp *new_nsp) -{ - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - NMWimaxNsp *old_nsp; - gboolean path_changed = FALSE; - - old_nsp = priv->current_nsp; - priv->current_nsp = NULL; - - if (new_nsp) - priv->current_nsp = g_object_ref (new_nsp); - - if (old_nsp && new_nsp) { - path_changed = (g_strcmp0 (nm_wimax_nsp_get_dbus_path (old_nsp), - nm_wimax_nsp_get_dbus_path (new_nsp)) != 0); - } - - /* Only notify if it's really changed */ - if (old_nsp != new_nsp || path_changed) - g_object_notify (G_OBJECT (self), NM_DEVICE_WIMAX_ACTIVE_NSP); - - if (old_nsp) - g_object_unref (old_nsp); -} - -static gboolean -activation_timed_out (gpointer data) -{ - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (data); - - priv->activation_timeout_id = 0; - nm_device_state_changed (NM_DEVICE (data), NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_CONFIG_FAILED); - - return FALSE; -} - -static void -emit_nsp_added_removed (NMDeviceWimax *self, - guint signum, - NMWimaxNsp *nsp, - gboolean recheck_available_connections) -{ - g_signal_emit (self, signals[signum], 0, nsp); - g_object_notify (G_OBJECT (self), NM_DEVICE_WIMAX_NSPS); - nm_device_emit_recheck_auto_activate (NM_DEVICE (self)); - if (recheck_available_connections) - nm_device_recheck_available_connections (NM_DEVICE (self)); -} - -static void -remove_all_nsps (NMDeviceWimax *self) -{ - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - - set_current_nsp (self, NULL); - - while (priv->nsp_list) { - NMWimaxNsp *nsp = NM_WIMAX_NSP (priv->nsp_list->data); - - priv->nsp_list = g_slist_remove (priv->nsp_list, nsp); - emit_nsp_added_removed (self, NSP_REMOVED, nsp, FALSE); - g_object_unref (nsp); - } - - nm_device_recheck_available_connections (NM_DEVICE (self)); -} - -static NMWimaxNsp * -get_nsp_by_name (NMDeviceWimax *self, const char *name) -{ - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - GSList *iter; - - g_return_val_if_fail (name, NULL); - - for (iter = priv->nsp_list; iter; iter = iter->next) { - NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data); - - if (!g_strcmp0 (nm_wimax_nsp_get_name (nsp), name)) - return nsp; - } - - return NULL; -} - -static NMWimaxNsp * -get_nsp_by_path (NMDeviceWimax *self, const char *path) -{ - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - GSList *iter; - - g_return_val_if_fail (path, NULL); - - for (iter = priv->nsp_list; iter; iter = iter->next) { - NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data); - - if (!strcmp (nm_wimax_nsp_get_dbus_path (nsp), path)) - return nsp; - } - - return NULL; -} - -static gboolean -update_availability (NMDeviceWimax *self, gboolean old_available) -{ - NMDevice *device = NM_DEVICE (self); - NMDeviceState state; - gboolean new_available, changed = FALSE; - - new_available = nm_device_is_available (device, NM_DEVICE_CHECK_DEV_AVAILABLE_NONE); - if (new_available == old_available) - return FALSE; - - state = nm_device_get_state (device); - if (state == NM_DEVICE_STATE_UNAVAILABLE) { - if (new_available == TRUE) { - nm_device_state_changed (device, - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_NONE); - changed = TRUE; - } - } else if (state >= NM_DEVICE_STATE_DISCONNECTED) { - if (new_available == FALSE) { - nm_device_state_changed (device, - NM_DEVICE_STATE_UNAVAILABLE, - NM_DEVICE_STATE_REASON_NONE); - changed = TRUE; - } - } - - return changed; -} - -/* NMDeviceInterface interface */ - -static void -set_enabled (NMDevice *device, gboolean enabled) -{ - NMDeviceWimax *self = NM_DEVICE_WIMAX (device); - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - gboolean old_available; - int ret; - const char *iface; - - iface = nm_device_get_iface (NM_DEVICE (self)); - - nm_log_dbg (LOGD_WIMAX, "(%s): setting radio enabled %d -> %d", - iface, priv->enabled, enabled); - if (priv->enabled == enabled) - return; - - old_available = nm_device_is_available (NM_DEVICE (device), NM_DEVICE_CHECK_DEV_AVAILABLE_NONE); - priv->enabled = enabled; - - nm_log_dbg (LOGD_WIMAX, "(%s): radio now %s", - iface, priv->enabled ? "enabled" : "disabled"); - - /* Set the WiMAX device RF state to the current user-specified enabled state */ - if (priv->sdk) { - ret = iwmx_sdk_rf_state_set (priv->sdk, - enabled ? WIMAX_API_RF_ON : WIMAX_API_RF_OFF); - if (ret < 0 && ret != -EINPROGRESS) { - nm_log_warn (LOGD_WIMAX, "(%s): failed to %s radio", - iface, priv->enabled ? "enable" : "disable"); - } - } - - update_availability (self, old_available); -} - -/* NMDevice methods */ - -static gboolean -check_connection_compatible (NMDevice *device, NMConnection *connection) -{ - NMSettingConnection *s_con; - NMSettingWimax *s_wimax; - const char *connection_type; - const char *mac; - - if (!NM_DEVICE_CLASS (nm_device_wimax_parent_class)->check_connection_compatible (device, connection)) - return FALSE; - - s_con = nm_connection_get_setting_connection (connection); - g_assert (s_con); - - connection_type = nm_setting_connection_get_connection_type (s_con); - if (strcmp (connection_type, NM_SETTING_WIMAX_SETTING_NAME)) - return FALSE; - - s_wimax = nm_connection_get_setting_wimax (connection); - if (!s_wimax) - return FALSE; - - mac = nm_setting_wimax_get_mac_address (s_wimax); - if (mac && !nm_utils_hwaddr_matches (mac, -1, nm_device_get_hw_address (device), -1)) - return FALSE; - - return TRUE; -} - -static gboolean -check_connection_available (NMDevice *device, - NMConnection *connection, - NMDeviceCheckConAvailableFlags flags, - const char *specific_object) -{ - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device); - const GSList *ns_iter = NULL; - NMWimaxNsp *nsp; - - /* a connection that is available for a certain @specific_object, MUST - * also be available in general (without @specific_object). */ - - if (specific_object) { - nsp = get_nsp_by_path (NM_DEVICE_WIMAX (device), specific_object); - return nsp ? nm_wimax_nsp_check_compatible (nsp, connection) : FALSE; - } - - /* Ensure the connection applies to an NSP in the scan list */ - for (ns_iter = priv->nsp_list; ns_iter; ns_iter = ns_iter->next) { - if (nm_wimax_nsp_check_compatible (NM_WIMAX_NSP (ns_iter->data), connection)) - return TRUE; - } - - return FALSE; -} - -static gboolean -complete_connection (NMDevice *device, - NMConnection *connection, - const char *specific_object, - const GSList *existing_connections, - GError **error) -{ - NMDeviceWimax *self = NM_DEVICE_WIMAX (device); - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - NMSettingWimax *s_wimax; - const char *setting_mac; - const char *hw_address; - const char *nsp_name = NULL; - NMWimaxNsp *nsp = NULL; - GSList *iter; - - s_wimax = nm_connection_get_setting_wimax (connection); - - if (!specific_object) { - /* If not given a specific object, we need at minimum an NSP name */ - if (!s_wimax) { - g_set_error_literal (error, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "A 'wimax' setting is required if no NSP path was given."); - return FALSE; - } - - nsp_name = nm_setting_wimax_get_network_name (s_wimax); - if (!nsp_name || !strlen (nsp_name)) { - g_set_error_literal (error, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "A 'wimax' setting with a valid network name is required if no NSP path was given."); - return FALSE; - } - - /* Find a compatible NSP in the list */ - nsp = get_nsp_by_name (self, nsp_name); - - /* If we still don't have an NSP, then the WiMAX settings needs to be - * fully specified by the client. Might not be able to find the NSP - * if the scan didn't find the NSP yet. - */ - if (!nsp) { - if (!nm_setting_verify (NM_SETTING (s_wimax), NULL, error)) - return FALSE; - } - } else { - /* Find a compatible NSP in the list */ - for (iter = priv->nsp_list; iter; iter = g_slist_next (iter)) { - if (!strcmp (specific_object, nm_wimax_nsp_get_dbus_path (NM_WIMAX_NSP (iter->data)))) { - nsp = NM_WIMAX_NSP (iter->data); - break; - } - } - - if (!nsp) { - g_set_error (error, - NM_DEVICE_ERROR, - NM_DEVICE_ERROR_SPECIFIC_OBJECT_NOT_FOUND, - "The NSP %s was not in the scan list.", - specific_object); - return FALSE; - } - - nsp_name = nm_wimax_nsp_get_name (nsp); - } - - /* Add a WiMAX setting if one doesn't exist */ - if (!s_wimax) { - s_wimax = (NMSettingWimax *) nm_setting_wimax_new (); - nm_connection_add_setting (connection, NM_SETTING (s_wimax)); - } - - g_assert (nsp_name); - nm_utils_complete_generic (connection, - NM_SETTING_WIMAX_SETTING_NAME, - existing_connections, - nsp_name, - nsp_name, - NULL, - TRUE); - g_object_set (G_OBJECT (s_wimax), NM_SETTING_WIMAX_NETWORK_NAME, nsp_name, NULL); - - setting_mac = nm_setting_wimax_get_mac_address (s_wimax); - hw_address = nm_device_get_hw_address (device); - if (setting_mac) { - /* Make sure the setting MAC (if any) matches the device's permanent MAC */ - if (!nm_utils_hwaddr_matches (setting_mac, -1, hw_address, -1)) { - g_set_error_literal (error, - NM_CONNECTION_ERROR, - NM_CONNECTION_ERROR_INVALID_PROPERTY, - _("connection does not match device")); - g_prefix_error (error, "%s.%s: ", NM_SETTING_WIMAX_SETTING_NAME, NM_SETTING_WIMAX_MAC_ADDRESS); - return FALSE; - } - } else { - /* Lock the connection to this device by default */ - if (!nm_utils_hwaddr_matches (hw_address, -1, NULL, ETH_ALEN)) - g_object_set (G_OBJECT (s_wimax), NM_SETTING_WIMAX_MAC_ADDRESS, hw_address, NULL); - } - - return TRUE; -} - -static gboolean -can_auto_connect (NMDevice *device, - NMConnection *connection, - char **specific_object) -{ - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device); - GSList *iter; - - if (!NM_DEVICE_CLASS (nm_device_wimax_parent_class)->can_auto_connect (device, connection, specific_object)) - return FALSE; - - for (iter = priv->nsp_list; iter; iter = iter->next) { - NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data); - - if (nm_wimax_nsp_check_compatible (nsp, connection)) { - *specific_object = (char *) nm_wimax_nsp_get_dbus_path (nsp); - return TRUE; - } - } - - return FALSE; -} - -static gboolean -is_available (NMDevice *device, NMDeviceCheckDevAvailableFlags flags) -{ - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device); - - if (!priv->enabled) - return FALSE; - - if (!priv->wimaxd_enabled) - return FALSE; - - if (!nm_wimax_util_sdk_is_initialized ()) - return FALSE; - - if (!priv->sdk) - return FALSE; - - return iwmxsdk_status_get (priv->sdk) >= WIMAX_API_DEVICE_STATUS_Ready; -} - -static void -clear_activation_timeout (NMDeviceWimax *self) -{ - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - - if (priv->activation_timeout_id) { - g_source_remove (priv->activation_timeout_id); - priv->activation_timeout_id = 0; - } - - priv->connect_failed = FALSE; -} - -static void -clear_link_timeout (NMDeviceWimax *self) -{ - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - - if (priv->link_timeout_id) { - g_source_remove (priv->link_timeout_id); - priv->link_timeout_id = 0; - } -} - -static void -clear_connected_poll (NMDeviceWimax *self) -{ - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - - if (priv->poll_id) { - g_source_remove (priv->poll_id); - priv->poll_id = 0; - } -} - -static NMActStageReturn -act_stage1_prepare (NMDevice *device, NMDeviceStateReason *reason) -{ - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device); - NMActRequest *req; - GSList *iter; - const char *path; - NMWimaxNsp *nsp = NULL; - - clear_link_timeout (NM_DEVICE_WIMAX (device)); - - *reason = NM_DEVICE_STATE_REASON_NONE; - - req = nm_device_get_act_request (device); - if (!req) - return NM_ACT_STAGE_RETURN_FAILURE; - - path = nm_active_connection_get_specific_object (NM_ACTIVE_CONNECTION (req)); - if (!path) - return NM_ACT_STAGE_RETURN_FAILURE; - - /* Find the NSP in the scan list */ - for (iter = priv->nsp_list; iter; iter = iter->next) { - NMWimaxNsp *candidate = NM_WIMAX_NSP (iter->data); - - if (!strcmp (path, nm_wimax_nsp_get_dbus_path (candidate))) { - nsp = candidate; - break; - } - } - - /* Couldn't find the NSP for some reason */ - if (nsp == NULL) - return NM_ACT_STAGE_RETURN_FAILURE; - - set_current_nsp (NM_DEVICE_WIMAX (device), nsp); - - priv->prepare_done = TRUE; - - /* If the device is scanning, it won't connect, so we have to wait until - * it's not scanning to proceed to stage 2. - */ - if (priv->status == WIMAX_API_DEVICE_STATUS_Scanning) - return NM_ACT_STAGE_RETURN_POSTPONE; - - return NM_ACT_STAGE_RETURN_SUCCESS; -} - -static NMActStageReturn -act_stage2_config (NMDevice *device, NMDeviceStateReason *reason) -{ - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (device); - NMConnection *connection; - NMSettingWimax *s_wimax; - const char *nsp_name, *iface; - int ret; - - iface = nm_device_get_iface (device); - g_assert (iface); - - connection = nm_device_get_connection (device); - g_assert (connection); - - s_wimax = nm_connection_get_setting_wimax (connection); - g_assert (s_wimax); - - nsp_name = nm_setting_wimax_get_network_name (s_wimax); - g_assert (nsp_name); - - nm_log_info (LOGD_WIMAX, "(%s): connecting to NSP '%s'", - iface, nsp_name); - - priv->connect_failed = FALSE; - ret = iwmx_sdk_connect (priv->sdk, nsp_name); - if (ret < 0 && ret != -EINPROGRESS) { - nm_log_err (LOGD_WIMAX, "(%s): failed to connect to NSP '%s'", - iface, nsp_name); - *reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED; - return NM_ACT_STAGE_RETURN_FAILURE; - } - - /* FIXME: Is 40 seconds good estimation? I have no idea */ - priv->activation_timeout_id = g_timeout_add_seconds (40, activation_timed_out, device); - - return NM_ACT_STAGE_RETURN_POSTPONE; -} - -static void -force_disconnect (NMDeviceWimax *self, struct wmxsdk *sdk) -{ - WIMAX_API_DEVICE_STATUS status; - int ret; - const char *iface; - - g_return_if_fail (sdk != NULL); - - iface = nm_device_get_iface (NM_DEVICE (self)); - - status = iwmxsdk_status_get (sdk); - if ((int) status < 0) { - nm_log_err (LOGD_WIMAX, "(%s): failed to read WiMAX device status: %d", - iface, status); - return; - } - - if ( status == WIMAX_API_DEVICE_STATUS_Connecting - || status == WIMAX_API_DEVICE_STATUS_Data_Connected) { - nm_log_dbg (LOGD_WIMAX, "(%s): requesting disconnect", iface); - ret = iwmx_sdk_disconnect (sdk); - if (ret < 0 && ret != -EINPROGRESS) { - nm_log_err (LOGD_WIMAX, "(%s): failed to disconnect WiMAX device: %d", - iface, ret); - } - } -} - -static void -deactivate (NMDevice *device) -{ - NMDeviceWimax *self = NM_DEVICE_WIMAX (device); - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - - clear_activation_timeout (self); - clear_link_timeout (self); - clear_connected_poll (self); - - set_current_nsp (self, NULL); - - if (priv->sdk) { - /* Read explicit status here just to make sure we have the most - * up-to-date status and to ensure we disconnect if needed. - */ - force_disconnect (self, priv->sdk); - } -} - -/*************************************************************************/ - -static void -wmx_state_change_cb (struct wmxsdk *wmxsdk, - WIMAX_API_DEVICE_STATUS new_status, - WIMAX_API_DEVICE_STATUS old_status, - WIMAX_API_STATUS_REASON reason, - WIMAX_API_CONNECTION_PROGRESS_INFO progress, - void *user_data) -{ - NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - NMDeviceState state; - const char *iface; - gboolean old_available = FALSE; - const char *nsp_name = NULL; - - iface = nm_device_get_iface (NM_DEVICE (self)); - nm_log_info (LOGD_WIMAX, "(%s): wimax state change %s -> %s (%s (%d))", - iface, - iwmx_sdk_dev_status_to_str (old_status), - iwmx_sdk_dev_status_to_str (new_status), - iwmx_sdk_con_progress_to_str (progress), - progress); - - if (new_status == old_status) - return; - - state = nm_device_get_state (NM_DEVICE (self)); - old_available = nm_device_is_available (NM_DEVICE (self), NM_DEVICE_CHECK_DEV_AVAILABLE_NONE); - - priv->status = new_status; - if (priv->current_nsp) - nsp_name = nm_wimax_nsp_get_name (priv->current_nsp); - - switch (new_status) { - case WIMAX_API_DEVICE_STATUS_UnInitialized: - case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW: - case WIMAX_API_DEVICE_STATUS_RF_OFF_HW: - case WIMAX_API_DEVICE_STATUS_RF_OFF_SW: - if (priv->wimaxd_enabled) { - priv->wimaxd_enabled = FALSE; - if (update_availability (self, old_available)) - return; - } - break; - case WIMAX_API_DEVICE_STATUS_Connecting: - case WIMAX_API_DEVICE_STATUS_Data_Connected: - /* If for some reason we're initially connected, force a disconnect here */ - if (state < NM_DEVICE_STATE_DISCONNECTED) - force_disconnect (self, wmxsdk); - /* Fall through */ - case WIMAX_API_DEVICE_STATUS_Ready: - case WIMAX_API_DEVICE_STATUS_Scanning: - if (priv->wimaxd_enabled == FALSE) { - priv->wimaxd_enabled = TRUE; - if (update_availability (self, old_available)) - return; - } - break; - default: - nm_log_warn (LOGD_WIMAX, "(%s): unhandled WiMAX device state %d", - iface, new_status); - break; - } - - /* Handle activation success and failure */ - if (nm_device_is_activating (NM_DEVICE (self))) { - if (new_status == WIMAX_API_DEVICE_STATUS_Data_Connected) { - /* Success */ - clear_activation_timeout (self); - - nm_log_info (LOGD_WIMAX, "(%s): connected to '%s'", - iface, nsp_name); - nm_device_activate_schedule_stage3_ip_config_start (NM_DEVICE (self)); - return; - } - - if (priv->connect_failed) { - /* Connection attempt failed */ - nm_log_info (LOGD_WIMAX, "(%s): connection to '%s' failed: (%d) %s", - iface, nsp_name, reason, iwmx_sdk_reason_to_str (reason)); - nm_device_state_changed (NM_DEVICE (self), - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_CONFIG_FAILED); - return; - } - - /* If stage2 was postponed because the device was scanning or something, - * then check if we need to move to stage2 now that the device might be - * ready. - */ - if (state == NM_DEVICE_STATE_PREPARE && priv->prepare_done) { - if ( new_status == WIMAX_API_DEVICE_STATUS_Ready - || new_status == WIMAX_API_DEVICE_STATUS_Connecting) { - nm_device_activate_schedule_stage2_device_config (NM_DEVICE (self)); - return; - } - } - } - - /* Handle disconnection */ - if (state == NM_DEVICE_STATE_ACTIVATED) { - if ( old_status == WIMAX_API_DEVICE_STATUS_Data_Connected - && new_status < WIMAX_API_DEVICE_STATUS_Connecting) { - - nm_log_info (LOGD_WIMAX, "(%s): disconnected from '%s': (%d) %s", - iface, nsp_name, reason, iwmx_sdk_reason_to_str (reason)); - - nm_device_state_changed (NM_DEVICE (self), - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_CONFIG_FAILED); - } - } -} - -static gboolean -link_timeout_cb (gpointer user_data) -{ - NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - - priv->link_timeout_id = 0; - - nm_log_dbg (LOGD_WIMAX, "(%s): link timed out", nm_device_get_iface (NM_DEVICE (self))); - nm_device_state_changed (NM_DEVICE (self), - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_CARRIER); - - return FALSE; -} - -static void -wmx_media_status_cb (struct wmxsdk *wmxsdk, - WIMAX_API_MEDIA_STATUS new_status, - void *user_data) -{ - NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - NMDeviceState state; - const char *iface; - - iface = nm_device_get_iface (NM_DEVICE (self)); - state = nm_device_get_state (NM_DEVICE (self)); - - nm_log_dbg (LOGD_WIMAX, "(%s): media status change to %s", - iface, iwmx_sdk_media_status_to_str (new_status)); - - /* We only care about media events while activated */ - if (state != NM_DEVICE_STATE_ACTIVATED) - return; - - clear_link_timeout (self); - - switch (new_status) { - case WIMAX_API_MEDIA_STATUS_LINK_UP: - break; - case WIMAX_API_MEDIA_STATUS_LINK_DOWN: - nm_log_dbg (LOGD_WIMAX, "(%s): starting link timeout", iface); - priv->link_timeout_id = g_timeout_add_seconds (15, link_timeout_cb, self); - break; - case WIMAX_API_MEDIA_STATUS_LINK_RENEW: - nm_log_dbg (LOGD_WIMAX, "(%s): renewing DHCP lease", iface); - if (!nm_device_dhcp4_renew (NM_DEVICE (self), TRUE)) { - nm_device_state_changed (NM_DEVICE (self), - NM_DEVICE_STATE_FAILED, - NM_DEVICE_STATE_REASON_DHCP_FAILED); - } - break; - default: - nm_log_err (LOGD_WIMAX, "(%s): unhandled media status %d", iface, new_status); - break; - } -} - -static void -wmx_connect_result_cb (struct wmxsdk *wmxsdk, - WIMAX_API_NETWORK_CONNECTION_RESP result, - void *user_data) -{ - NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - - if (nm_device_is_activating (NM_DEVICE (self))) { - priv->connect_failed = (result == WIMAX_API_CONNECTION_SUCCESS); - /* Wait for the state change so we can get the reason code; we - * cache the connect failure so we don't have to wait for the - * activation timeout. - */ - } -} - -static void -remove_outdated_nsps (NMDeviceWimax *self, - WIMAX_API_NSP_INFO_EX *nsp_list, - guint32 list_size) -{ - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - GSList *iter; - GSList *to_remove = NULL; - - for (iter = priv->nsp_list; iter; iter = iter->next) { - NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data); - gboolean found = FALSE; - int i; - - for (i = 0; i < list_size; i++) { - WIMAX_API_NSP_INFO_EX *info = &nsp_list[i]; - - if (!g_strcmp0 (nm_wimax_nsp_get_name (nsp), (char *) info->NSPName)) { - found = TRUE; - break; - } - } - - if (!found) - to_remove = g_slist_prepend (to_remove, nsp); - } - - for (iter = to_remove; iter; iter = iter->next) { - NMWimaxNsp *nsp = NM_WIMAX_NSP (iter->data); - - emit_nsp_added_removed (self, NSP_REMOVED, nsp, FALSE); - priv->nsp_list = g_slist_remove (priv->nsp_list, nsp); - g_object_unref (nsp); - } - - if (g_slist_length(to_remove) > 0) - nm_device_recheck_available_connections (NM_DEVICE (self)); - - g_slist_free (to_remove); -} - -static void -wmx_scan_result_cb (struct wmxsdk *wmxsdk, - WIMAX_API_NSP_INFO_EX *nsps, - guint num_nsps, - void *user_data) -{ - NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - const char *iface = nm_device_get_iface (NM_DEVICE (self)); - int i; - - remove_outdated_nsps (self, nsps, num_nsps); - - /* Add new NSPs and update existing ones */ - for (i = 0; i < num_nsps; i++) { - WIMAX_API_NSP_INFO_EX *sdk_nsp = &nsps[i]; - const char *nsp_name = (const char *) sdk_nsp->NSPName; - NMWimaxNspNetworkType net_type; - guint signalq; - NMWimaxNsp *nsp; - gboolean new_nsp; - - nsp = get_nsp_by_name (self, nsp_name); - new_nsp = (nsp == NULL); - if (new_nsp) { - nsp = nm_wimax_nsp_new (nsp_name); - nm_log_dbg (LOGD_WIMAX, "(%s): new WiMAX NSP '%s'", iface, nsp_name); - } - - net_type = nm_wimax_util_convert_network_type (sdk_nsp->networkType); - if (net_type != nm_wimax_nsp_get_network_type (nsp)) - g_object_set (nsp, NM_WIMAX_NSP_NETWORK_TYPE, net_type, NULL); - - signalq = CLAMP (sdk_nsp->linkQuality, 0, 100); - if (signalq != nm_wimax_nsp_get_signal_quality (nsp)) - g_object_set (nsp, NM_WIMAX_NSP_SIGNAL_QUALITY, signalq, NULL); - - nm_log_dbg (LOGD_WIMAX, "(%s): WiMAX NSP '%s' quality %d%% type %d", - iface, nsp_name, sdk_nsp->linkQuality, net_type); - - if (new_nsp) { - priv->nsp_list = g_slist_append (priv->nsp_list, nsp); - nm_wimax_nsp_export_to_dbus (nsp); - emit_nsp_added_removed (self, NSP_ADDED, nsp, TRUE); - } - } -} - -static void -wmx_removed_cb (struct wmxsdk *wmxsdk, void *user_data) -{ - NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - - if (!priv->sdk) { - nm_log_dbg (LOGD_WIMAX, "(%s): removed unhandled WiMAX interface", wmxsdk->ifname); - return; - } - - nm_log_dbg (LOGD_WIMAX, "(%s): removed WiMAX interface", wmxsdk->ifname); - - /* Clear callbacks just in case we don't hold the last reference */ - iwmx_sdk_set_callbacks (priv->sdk, NULL, NULL, NULL, NULL, NULL, NULL); - wmxsdk_unref (priv->sdk); - priv->sdk = NULL; - - priv->status = WIMAX_API_DEVICE_STATUS_UnInitialized; - nm_device_state_changed (NM_DEVICE (self), - NM_DEVICE_STATE_UNAVAILABLE, - NM_DEVICE_STATE_REASON_NONE); -} - -/*************************************************************************/ - -static inline gint -sdk_rssi_to_dbm (guint raw_rssi) -{ - /* Values range from 0x00 to 0x53, where -123dBm is encoded as 0x00 and - * -40dBm encoded as 0x53 in 1dB increments. - */ - return raw_rssi - 123; -} - -static inline gint -sdk_cinr_to_db (guint raw_cinr) -{ - /* Values range from 0x00 to 0x3F, where -10dB is encoded as 0x00 and - * 53dB encoded as 0x3F in 1dB increments. - */ - return raw_cinr - 10; -} - -static inline gint -sdk_tx_pow_to_dbm (guint raw_tx_pow) -{ - /* Values range from 0x00 to 0xFF, where -84dBm is encoded as 0x00 and - * 43.5dBm is encoded as 0xFF in 0.5dB increments. Normalize so that - * 0 dBm == 0. - */ - return (int) (((double) raw_tx_pow / 2.0) - 84) * 2; -} - -static void -set_link_status (NMDeviceWimax *self, WIMAX_API_LINK_STATUS_INFO_EX *link_status) -{ - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - guint center_freq = 0; - gint conv_rssi = 0, conv_cinr = 0, conv_tx_pow = 0; - char *new_bsid = NULL; - - if (link_status) { - center_freq = link_status->centerFrequency; - conv_rssi = sdk_rssi_to_dbm (link_status->RSSI); - conv_cinr = sdk_cinr_to_db (link_status->CINR); - conv_tx_pow = sdk_tx_pow_to_dbm (link_status->txPWR); - new_bsid = nm_utils_hwaddr_ntoa (link_status->bsId, 6); - } - - if (priv->center_freq != center_freq) { - priv->center_freq = center_freq; - g_object_notify (G_OBJECT (self), NM_DEVICE_WIMAX_CENTER_FREQUENCY); - } - - if (priv->rssi != conv_rssi) { - priv->rssi = conv_rssi; - g_object_notify (G_OBJECT (self), NM_DEVICE_WIMAX_RSSI); - } - - if (priv->cinr != conv_cinr) { - priv->cinr = conv_cinr; - g_object_notify (G_OBJECT (self), NM_DEVICE_WIMAX_CINR); - } - - if (priv->tx_power != conv_tx_pow) { - priv->tx_power = conv_tx_pow; - g_object_notify (G_OBJECT (self), NM_DEVICE_WIMAX_TX_POWER); - } - - if (g_strcmp0 (priv->bsid, new_bsid) != 0) { - g_free (priv->bsid); - priv->bsid = new_bsid; - g_object_notify (G_OBJECT (self), NM_DEVICE_WIMAX_BSID); - } else - g_free (new_bsid); -} - -static gboolean -connected_poll_cb (gpointer user_data) -{ - NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - WIMAX_API_CONNECTED_NSP_INFO_EX *sdk_nsp; - WIMAX_API_LINK_STATUS_INFO_EX *link_status; - - g_return_val_if_fail (priv->sdk != NULL, FALSE); - - /* Get details of the connected NSP */ - sdk_nsp = iwmx_sdk_get_connected_network (priv->sdk); - if (sdk_nsp) { - const char *nsp_name = (const char *) sdk_nsp->NSPName; - NMWimaxNsp *nsp; - - nsp = get_nsp_by_name (self, nsp_name); - if (nsp) { - NMWimaxNspNetworkType net_type; - guint signalq; - - net_type = nm_wimax_util_convert_network_type (sdk_nsp->networkType); - if (net_type != nm_wimax_nsp_get_network_type (nsp)) - g_object_set (nsp, NM_WIMAX_NSP_NETWORK_TYPE, net_type, NULL); - - signalq = sdk_nsp->linkQuality; - if (signalq != nm_wimax_nsp_get_signal_quality (nsp)) - g_object_set (nsp, NM_WIMAX_NSP_SIGNAL_QUALITY, signalq, NULL); - - nm_log_dbg (LOGD_WIMAX, "(%s): WiMAX NSP '%s' quality %d%% type %d", - nm_device_get_iface (NM_DEVICE (self)), - nsp_name, sdk_nsp->linkQuality, net_type); - } - free (sdk_nsp); - } - - /* Get details of the current radio link */ - link_status = iwmx_sdk_get_link_status_info (priv->sdk); - if (link_status) { - set_link_status (self, link_status); - free (link_status); - } - - return TRUE; /* reschedule */ -} - -static void -device_state_changed (NMDevice *device, - NMDeviceState new_state, - NMDeviceState old_state, - NMDeviceStateReason reason) -{ - NMDeviceWimax *self = NM_DEVICE_WIMAX (device); - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - - /* Reset our stage1 (Prepare) done marker since it's only valid while in stage1 */ - priv->prepare_done = FALSE; - - if (new_state < NM_DEVICE_STATE_DISCONNECTED) - remove_all_nsps (self); - - /* Request initial NSP list when device is first started */ - if ( new_state == NM_DEVICE_STATE_DISCONNECTED - && old_state < NM_DEVICE_STATE_DISCONNECTED) { - if (priv->sdk) - iwmx_sdk_get_networks (priv->sdk); - } - - if (new_state == NM_DEVICE_STATE_FAILED || new_state <= NM_DEVICE_STATE_DISCONNECTED) { - set_current_nsp (self, NULL); - clear_activation_timeout (self); - } - - if (new_state == NM_DEVICE_STATE_ACTIVATED) { - /* poll link quality and BSID */ - clear_connected_poll (self); - priv->poll_id = g_timeout_add_seconds (10, connected_poll_cb, self); - connected_poll_cb (self); - } else { - clear_link_timeout (self); - clear_connected_poll (self); - set_link_status (self, NULL); - } -} - -/*************************************************************************/ - -static gboolean -sdk_action_defer_cb (gpointer user_data) -{ - NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); - gboolean old_available = nm_device_is_available (NM_DEVICE (self), NM_DEVICE_CHECK_DEV_AVAILABLE_NONE); - - NM_DEVICE_WIMAX_GET_PRIVATE (self)->sdk_action_defer_id = 0; - update_availability (self, old_available); - return FALSE; -} - -static void -wmx_new_sdk_cb (struct wmxsdk *sdk, void *user_data) -{ - NMDeviceWimax *self = NM_DEVICE_WIMAX (user_data); - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - - /* We only track one wmxsdk at a time because the WiMAX SDK is pretty stupid */ - if (priv->sdk) { - nm_log_dbg (LOGD_WIMAX, "(%s): WiMAX interface already known", sdk->ifname); - return; - } - - nm_log_dbg (LOGD_WIMAX, "(%s): new WiMAX interface (%s)", sdk->ifname, sdk->name); - - /* Now that we have an SDK, schedule an idle handler to start the device up */ - priv->sdk = wmxsdk_ref (sdk); - iwmx_sdk_set_callbacks(priv->sdk, - wmx_state_change_cb, - wmx_media_status_cb, - wmx_connect_result_cb, - wmx_scan_result_cb, - wmx_removed_cb, - self); - iwmx_sdk_set_fast_reconnect_enabled (priv->sdk, 0); - - if (!priv->sdk_action_defer_id) - priv->sdk_action_defer_id = g_idle_add (sdk_action_defer_cb, self); -} - -/*************************************************************************/ - -NMDevice * -nm_device_wimax_new (NMPlatformLink *platform_device) -{ - NMDevice *device; - - g_return_val_if_fail (platform_device != NULL, NULL); - - device = (NMDevice *) g_object_new (NM_TYPE_DEVICE_WIMAX, - NM_DEVICE_PLATFORM_DEVICE, platform_device, - NM_DEVICE_TYPE_DESC, "WiMAX", - NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_WIMAX, - NM_DEVICE_RFKILL_TYPE, RFKILL_TYPE_WIMAX, - NULL); - if (device) { - struct wmxsdk *sdk; - - nm_wimax_util_sdk_ref (); - - /* See if the SDK already knows about this interface */ - sdk = iwmx_sdk_get_wmxsdk_for_iface (platform_device->name); - if (sdk) - wmx_new_sdk_cb (sdk, device); - - /* If it doesn't, we want to be notified when it does */ - iwmx_sdk_new_callback_register (wmx_new_sdk_cb, device); - } - - return device; -} - -static void -nm_device_wimax_init (NMDeviceWimax *self) -{ - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - - priv->status = WIMAX_API_DEVICE_STATUS_UnInitialized; -} - -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMDeviceWimax *self = NM_DEVICE_WIMAX (object); - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - GPtrArray *array; - GSList *iter; - - switch (prop_id) { - case PROP_NSPS: - array = g_ptr_array_sized_new (4); - for (iter = priv->nsp_list; iter; iter = g_slist_next (iter)) - g_ptr_array_add (array, g_strdup (nm_wimax_nsp_get_dbus_path (NM_WIMAX_NSP (iter->data)))); - g_value_take_boxed (value, array); - break; - case PROP_ACTIVE_NSP: - if (priv->current_nsp) - g_value_set_boxed (value, nm_wimax_nsp_get_dbus_path (priv->current_nsp)); - else - g_value_set_boxed (value, "/"); - break; - case PROP_CENTER_FREQ: - g_value_set_uint (value, priv->center_freq); - break; - case PROP_RSSI: - g_value_set_int (value, priv->rssi); - break; - case PROP_CINR: - g_value_set_int (value, priv->cinr); - break; - case PROP_TX_POWER: - g_value_set_int (value, priv->tx_power); - break; - case PROP_BSID: - g_value_set_string (value, priv->bsid); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -dispose (GObject *object) -{ - NMDeviceWimax *self = NM_DEVICE_WIMAX (object); - NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (self); - - if (priv->disposed) - goto done; - - priv->disposed = TRUE; - - clear_activation_timeout (self); - clear_link_timeout (self); - clear_connected_poll (self); - - if (priv->sdk_action_defer_id) - g_source_remove (priv->sdk_action_defer_id); - - if (priv->sdk) { - iwmx_sdk_set_callbacks (priv->sdk, NULL, NULL, NULL, NULL, NULL, NULL); - wmxsdk_unref (priv->sdk); - } - - g_free (priv->bsid); - - set_current_nsp (self, NULL); - - g_slist_free_full (priv->nsp_list, g_object_unref); - - iwmx_sdk_new_callback_unregister (wmx_new_sdk_cb, self); - nm_wimax_util_sdk_unref (); - -done: - G_OBJECT_CLASS (nm_device_wimax_parent_class)->dispose (object); -} - -static void -nm_device_wimax_class_init (NMDeviceWimaxClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMDeviceClass *device_class = NM_DEVICE_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMDeviceWimaxPrivate)); - - /* Virtual methods */ - object_class->set_property = set_property; - object_class->get_property = get_property; - object_class->dispose = dispose; - - device_class->check_connection_compatible = check_connection_compatible; - device_class->check_connection_available = check_connection_available; - device_class->complete_connection = complete_connection; - device_class->can_auto_connect = can_auto_connect; - device_class->is_available = is_available; - device_class->act_stage1_prepare = act_stage1_prepare; - device_class->act_stage2_config = act_stage2_config; - device_class->deactivate = deactivate; - device_class->set_enabled = set_enabled; - - device_class->state_changed = device_state_changed; - - /* Properties */ - g_object_class_install_property - (object_class, PROP_NSPS, - g_param_spec_boxed (NM_DEVICE_WIMAX_NSPS, "", "", - DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_ACTIVE_NSP, - g_param_spec_boxed (NM_DEVICE_WIMAX_ACTIVE_NSP, "", "", - DBUS_TYPE_G_OBJECT_PATH, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_CENTER_FREQ, - g_param_spec_uint (NM_DEVICE_WIMAX_CENTER_FREQUENCY, "", "", - 0, G_MAXUINT, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_RSSI, - g_param_spec_int (NM_DEVICE_WIMAX_RSSI, "", "", - G_MININT, G_MAXINT, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_CINR, - g_param_spec_int (NM_DEVICE_WIMAX_CINR, "", "", - G_MININT, G_MAXINT, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_TX_POWER, - g_param_spec_int (NM_DEVICE_WIMAX_TX_POWER, "", "", - G_MININT, G_MAXINT, 0, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_BSID, - g_param_spec_string (NM_DEVICE_WIMAX_BSID, "", "", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - /* Signals */ - signals[NSP_ADDED] = - g_signal_new ("nsp-added", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMDeviceWimaxClass, nsp_added), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); - - signals[NSP_REMOVED] = - g_signal_new ("nsp-removed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMDeviceWimaxClass, nsp_removed), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); - - nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), - G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_device_wimax_object_info); -} diff --git a/src/devices/wimax/nm-device-wimax.h b/src/devices/wimax/nm-device-wimax.h deleted file mode 100644 index 30b2481f..00000000 --- a/src/devices/wimax/nm-device-wimax.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2010 - 2011 Red Hat, Inc. - * Copyright (C) 2009 Novell, Inc. - */ - -#ifndef __NETWORKMANAGER_DEVICE_WIMAX_H__ -#define __NETWORKMANAGER_DEVICE_WIMAX_H__ - -#include "nm-device.h" -#include "nm-wimax-nsp.h" - -G_BEGIN_DECLS - -#define NM_TYPE_DEVICE_WIMAX (nm_device_wimax_get_type ()) -#define NM_DEVICE_WIMAX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_WIMAX, NMDeviceWimax)) -#define NM_DEVICE_WIMAX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_WIMAX, NMDeviceWimaxClass)) -#define NM_IS_DEVICE_WIMAX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_WIMAX)) -#define NM_IS_DEVICE_WIMAX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_WIMAX)) -#define NM_DEVICE_WIMAX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_WIMAX, NMDeviceWimaxClass)) - -#define NM_DEVICE_WIMAX_NSPS "nsps" -#define NM_DEVICE_WIMAX_ACTIVE_NSP "active-nsp" -#define NM_DEVICE_WIMAX_CENTER_FREQUENCY "center-frequency" -#define NM_DEVICE_WIMAX_RSSI "rssi" -#define NM_DEVICE_WIMAX_CINR "cinr" -#define NM_DEVICE_WIMAX_TX_POWER "tx-power" -#define NM_DEVICE_WIMAX_BSID "bsid" - -typedef struct { - NMDevice parent; -} NMDeviceWimax; - -typedef struct { - NMDeviceClass parent; - - /* Signals */ - void (*nsp_added) (NMDeviceWimax *wimax, NMWimaxNsp *nsp); - void (*nsp_removed) (NMDeviceWimax *wimax, NMWimaxNsp *nsp); - void (*properties_changed) (NMDeviceWimax *wimax, GHashTable *properties); -} NMDeviceWimaxClass; - -GType nm_device_wimax_get_type (void); - -NMDevice *nm_device_wimax_new (NMPlatformLink *platform_device); - -G_END_DECLS - -#endif /* NM_DEVICE_WIMAX_H */ diff --git a/src/devices/wimax/nm-wimax-factory.c b/src/devices/wimax/nm-wimax-factory.c deleted file mode 100644 index 7dc580fc..00000000 --- a/src/devices/wimax/nm-wimax-factory.c +++ /dev/null @@ -1,91 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2011 - 2014 Red Hat, Inc. - */ - -#include "config.h" - -#include <gmodule.h> - -#include "nm-device-factory.h" -#include "nm-device-wimax.h" -#include "nm-platform.h" -#include "nm-setting-wimax.h" - -#define NM_TYPE_WIMAX_FACTORY (nm_wimax_factory_get_type ()) -#define NM_WIMAX_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_WIMAX_FACTORY, NMWimaxFactory)) - -typedef struct { - GObject parent; -} NMWimaxFactory; - -typedef struct { - GObjectClass parent; -} NMWimaxFactoryClass; - -static GType nm_wimax_factory_get_type (void); - -static void device_factory_interface_init (NMDeviceFactory *factory_iface); - -G_DEFINE_TYPE_EXTENDED (NMWimaxFactory, nm_wimax_factory, G_TYPE_OBJECT, 0, - G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_FACTORY, device_factory_interface_init)) - -/**************************************************************************/ - -G_MODULE_EXPORT NMDeviceFactory * -nm_device_factory_create (GError **error) -{ - return (NMDeviceFactory *) g_object_new (NM_TYPE_WIMAX_FACTORY, NULL); -} - -/**************************************************************************/ - -static NMDevice * -new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error) -{ - /* FIXME: check udev 'DEVTYPE' instead; but since we only support Intel - * WiMAX devices for now this is appropriate. - */ - if (g_strcmp0 (plink->driver, "i2400m_usb") != 0) - return NULL; /* unsupported */ - - return (NMDevice *) nm_device_wimax_new (plink); -} - -NM_DEVICE_FACTORY_DECLARE_TYPES ( - NM_DEVICE_FACTORY_DECLARE_LINK_TYPES (NM_LINK_TYPE_WIMAX) - NM_DEVICE_FACTORY_DECLARE_SETTING_TYPES (NM_SETTING_WIMAX_SETTING_NAME) -) - -static void -device_factory_interface_init (NMDeviceFactory *factory_iface) -{ - factory_iface->new_link = new_link; - factory_iface->get_supported_types = get_supported_types; -} - -static void -nm_wimax_factory_init (NMWimaxFactory *factory) -{ -} - -static void -nm_wimax_factory_class_init (NMWimaxFactoryClass *wf_class) -{ -} - diff --git a/src/devices/wimax/nm-wimax-nsp.c b/src/devices/wimax/nm-wimax-nsp.c deleted file mode 100644 index f4db63f0..00000000 --- a/src/devices/wimax/nm-wimax-nsp.c +++ /dev/null @@ -1,241 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2010 - 2012 Red Hat, Inc. - * Copyright (C) 2009 Novell, Inc. - */ - -#include "config.h" - -#include "nm-wimax-nsp.h" -#include "nm-dbus-interface.h" -#include "nm-dbus-manager.h" -#include "nm-setting-wimax.h" -#include "nm-wimax-nsp-glue.h" -#include "nm-utils.h" - -G_DEFINE_TYPE (NMWimaxNsp, nm_wimax_nsp, G_TYPE_OBJECT) - -enum { - PROP_0, - - PROP_NAME, - PROP_SIGNAL_QUALITY, - PROP_NETWORK_TYPE, - - LAST_PROP -}; - -#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_WIMAX_NSP, NMWimaxNspPrivate)) - -typedef struct { - char *dbus_path; - - char *name; - guint32 signal_quality; - NMWimaxNspNetworkType network_type; -} NMWimaxNspPrivate; - -NMWimaxNsp * -nm_wimax_nsp_new (const char *name) -{ - g_return_val_if_fail (name != NULL, NULL); - - return NM_WIMAX_NSP (g_object_new (NM_TYPE_WIMAX_NSP, - NM_WIMAX_NSP_NAME, name, - NULL)); -} - -const char * -nm_wimax_nsp_get_name (NMWimaxNsp *self) -{ - g_return_val_if_fail (NM_IS_WIMAX_NSP (self), NULL); - - return GET_PRIVATE (self)->name; -} - -guint32 -nm_wimax_nsp_get_signal_quality (NMWimaxNsp *self) -{ - g_return_val_if_fail (NM_IS_WIMAX_NSP (self), 0); - - return GET_PRIVATE (self)->signal_quality; -} - -NMWimaxNspNetworkType -nm_wimax_nsp_get_network_type (NMWimaxNsp *self) -{ - g_return_val_if_fail (NM_IS_WIMAX_NSP (self), 0); - - return GET_PRIVATE (self)->network_type; -} - -void -nm_wimax_nsp_export_to_dbus (NMWimaxNsp *self) -{ - NMWimaxNspPrivate *priv; - static guint32 counter = 0; - - g_return_if_fail (NM_IS_WIMAX_NSP (self)); - - priv = GET_PRIVATE (self); - - g_return_if_fail (priv->dbus_path == NULL); - - priv->dbus_path = g_strdup_printf (NM_DBUS_PATH_WIMAX_NSP "/%d", counter++); - nm_dbus_manager_register_object (nm_dbus_manager_get (), priv->dbus_path, self); -} - -const char * -nm_wimax_nsp_get_dbus_path (NMWimaxNsp *self) -{ - g_return_val_if_fail (NM_IS_WIMAX_NSP (self), NULL); - - return GET_PRIVATE (self)->dbus_path; -} - -gboolean -nm_wimax_nsp_check_compatible (NMWimaxNsp *self, - NMConnection *connection) -{ - NMWimaxNspPrivate *priv; - NMSettingWimax *s_wimax; - - g_return_val_if_fail (NM_IS_WIMAX_NSP (self), FALSE); - g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); - - priv = GET_PRIVATE (self); - - s_wimax = nm_connection_get_setting_wimax (connection); - if (!s_wimax) - return FALSE; - - return g_strcmp0 (nm_wimax_nsp_get_name (self), nm_setting_wimax_get_network_name (s_wimax)) == 0; -} - -static void -nm_wimax_nsp_init (NMWimaxNsp *self) -{ -} - -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - NMWimaxNspPrivate *priv = GET_PRIVATE (object); - guint32 quality; - guint network_type; - - switch (prop_id) { - case PROP_NAME: - /* Construct only */ - priv->name = g_value_dup_string (value); - break; - case PROP_SIGNAL_QUALITY: - quality = g_value_get_uint (value); - if (quality != priv->signal_quality) { - priv->signal_quality = CLAMP (quality, 0, 100); - g_object_notify (object, NM_WIMAX_NSP_SIGNAL_QUALITY); - } - break; - case PROP_NETWORK_TYPE: - network_type = g_value_get_uint (value); - if (network_type != priv->network_type) { - priv->network_type = network_type; - g_object_notify (object, NM_WIMAX_NSP_NETWORK_TYPE); - } - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMWimaxNsp *self = NM_WIMAX_NSP (object); - - switch (prop_id) { - case PROP_NAME: - g_value_set_string (value, nm_wimax_nsp_get_name (self)); - break; - case PROP_SIGNAL_QUALITY: - g_value_set_uint (value, nm_wimax_nsp_get_signal_quality (self)); - break; - case PROP_NETWORK_TYPE: - g_value_set_uint (value, nm_wimax_nsp_get_network_type (self)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -finalize (GObject *object) -{ - NMWimaxNspPrivate *priv = GET_PRIVATE (object); - - g_free (priv->name); - g_free (priv->dbus_path); - - G_OBJECT_CLASS (nm_wimax_nsp_parent_class)->finalize (object); -} - -static void -nm_wimax_nsp_class_init (NMWimaxNspClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (object_class, sizeof (NMWimaxNspPrivate)); - - /* Virtual methods */ - object_class->set_property = set_property; - object_class->get_property = get_property; - object_class->finalize = finalize; - - g_object_class_install_property - (object_class, PROP_NAME, - g_param_spec_string (NM_WIMAX_NSP_NAME, "", "", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_SIGNAL_QUALITY, - g_param_spec_uint (NM_WIMAX_NSP_SIGNAL_QUALITY, "", "", - 0, - 100, - 0, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property - (object_class, PROP_NETWORK_TYPE, - g_param_spec_uint (NM_WIMAX_NSP_NETWORK_TYPE, "", "", - NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN, - NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER, - NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), - G_TYPE_FROM_CLASS (klass), - &dbus_glib_nm_wimax_nsp_object_info); -} diff --git a/src/devices/wimax/nm-wimax-nsp.h b/src/devices/wimax/nm-wimax-nsp.h deleted file mode 100644 index 8d0a6a14..00000000 --- a/src/devices/wimax/nm-wimax-nsp.h +++ /dev/null @@ -1,63 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 Novell, Inc. - */ - -#ifndef __NETWORKMANAGER_WIMAX_NSP_H__ -#define __NETWORKMANAGER_WIMAX_NSP_H__ - -#include <glib-object.h> -#include "nm-wimax-types.h" -#include "nm-connection.h" - -#define NM_TYPE_WIMAX_NSP (nm_wimax_nsp_get_type ()) -#define NM_WIMAX_NSP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_WIMAX_NSP, NMWimaxNsp)) -#define NM_WIMAX_NSP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_WIMAX_NSP, NMWimaxNspClass)) -#define NM_IS_WIMAX_NSP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_WIMAX_NSP)) -#define NM_IS_WIMAX_NSP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_WIMAX_NSP)) -#define NM_WIMAX_NSP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_WIMAX_NSP, NMWimaxNspClass)) - -#define NM_WIMAX_NSP_NAME "name" -#define NM_WIMAX_NSP_SIGNAL_QUALITY "signal-quality" -#define NM_WIMAX_NSP_NETWORK_TYPE "network-type" - -typedef struct { - GObject parent; -} NMWimaxNsp; - -typedef struct { - GObjectClass parent; - - /* Signals */ - void (*properties_changed) (NMWimaxNsp *nsp, GHashTable *properties); -} NMWimaxNspClass; - -GType nm_wimax_nsp_get_type (void); - -NMWimaxNsp *nm_wimax_nsp_new (const char *name); -const char *nm_wimax_nsp_get_name (NMWimaxNsp *self); -guint32 nm_wimax_nsp_get_signal_quality (NMWimaxNsp *self); -NMWimaxNspNetworkType nm_wimax_nsp_get_network_type (NMWimaxNsp *self); - -void nm_wimax_nsp_export_to_dbus (NMWimaxNsp *self); -const char *nm_wimax_nsp_get_dbus_path (NMWimaxNsp *self); - -gboolean nm_wimax_nsp_check_compatible (NMWimaxNsp *self, - NMConnection *connection); - -#endif /* NM_WIMAX_NSP_H */ diff --git a/src/devices/wimax/nm-wimax-types.h b/src/devices/wimax/nm-wimax-types.h deleted file mode 100644 index 207d2477..00000000 --- a/src/devices/wimax/nm-wimax-types.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 Novell, Inc. - */ - -#ifndef __NETWORKMANAGER_WIMAX_TYPES_H__ -#define __NETWORKMANAGER_WIMAX_TYPES_H__ - -typedef enum { - NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN, - NM_WIMAX_NSP_NETWORK_TYPE_HOME, - NM_WIMAX_NSP_NETWORK_TYPE_PARTNER, - NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER -} NMWimaxNspNetworkType; - -#endif /* NM_WIMAX_TYPES_H */ diff --git a/src/devices/wimax/nm-wimax-util.c b/src/devices/wimax/nm-wimax-util.c deleted file mode 100644 index 0ae285ae..00000000 --- a/src/devices/wimax/nm-wimax-util.c +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 Novell, Inc. - */ - -#include "config.h" - -#include "nm-wimax-util.h" -#include "nm-utils.h" -#include "iwmxsdk.h" -#include "nm-logging.h" - -static guint sdk_refcount = 0; - -void -nm_wimax_util_sdk_ref (void) -{ - int ret = 0; - - if (sdk_refcount == 0) { - ret = iwmx_sdk_api_init (); - if (ret != 0) { - nm_log_warn (LOGD_WIMAX, "Failed to initialize WiMAX: %d", ret); - return; - } - } - sdk_refcount++; -} - -gboolean -nm_wimax_util_sdk_is_initialized (void) -{ - return sdk_refcount > 0; -} - -void -nm_wimax_util_sdk_unref (void) -{ - g_return_if_fail (sdk_refcount > 0); - - sdk_refcount--; - if (sdk_refcount == 0) - iwmx_sdk_api_exit (); -} - -NMWimaxNspNetworkType -nm_wimax_util_convert_network_type (WIMAX_API_NETWORK_TYPE wimax_network_type) -{ - NMWimaxNspNetworkType type; - - switch (wimax_network_type) { - case WIMAX_API_HOME: - type = NM_WIMAX_NSP_NETWORK_TYPE_HOME; - break; - case WIMAX_API_PARTNER: - type = NM_WIMAX_NSP_NETWORK_TYPE_PARTNER; - break; - case WIMAX_API_ROAMING_PARTNER: - type = NM_WIMAX_NSP_NETWORK_TYPE_ROAMING_PARTNER; - break; - default: - type = NM_WIMAX_NSP_NETWORK_TYPE_UNKNOWN; - break; - } - - return type; -} - diff --git a/src/devices/wimax/nm-wimax-util.h b/src/devices/wimax/nm-wimax-util.h deleted file mode 100644 index 5fedc6e8..00000000 --- a/src/devices/wimax/nm-wimax-util.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright (C) 2009 Novell, Inc. - */ - -#ifndef __NETWORKMANAGER_WIMAX_UTIL_H__ -#define __NETWORKMANAGER_WIMAX_UTIL_H__ - -#include <glib.h> - -#include "nm-macros-internal.h" - -NM_PRAGMA_WARNING_DISABLE("-Wstrict-prototypes") -#include <WiMaxType.h> -NM_PRAGMA_WARNING_REENABLE - -#include <WiMaxError.h> -#include "nm-wimax-types.h" - -void nm_wimax_util_sdk_ref (void); - -gboolean nm_wimax_util_sdk_is_initialized (void); - -void nm_wimax_util_sdk_unref (void); - -NMWimaxNspNetworkType nm_wimax_util_convert_network_type (WIMAX_API_NETWORK_TYPE wimax_network_type); - -#endif /* NM_WIMAX_UTIL_H */ diff --git a/src/devices/wwan/Makefile.am b/src/devices/wwan/Makefile.am index 055b07b9..107f630b 100644 --- a/src/devices/wwan/Makefile.am +++ b/src/devices/wwan/Makefile.am @@ -8,14 +8,14 @@ AM_CPPFLAGS = \ -I${top_srcdir}/src/devices \ -I${top_srcdir}/src/settings \ -I${top_srcdir}/src/platform \ - -I${top_srcdir}/include \ - -I$(top_builddir)/include \ + -I${top_builddir}/introspection \ + -I${top_srcdir}/shared \ + -I$(top_builddir)/shared \ -I${top_srcdir}/libnm-core \ -I${top_builddir}/libnm-core \ -DG_LOG_DOMAIN=\""NetworkManager-wwan"\" \ - -DNETWORKMANAGER_COMPILATION \ + -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ - $(DBUS_CFLAGS) \ $(GLIB_CFLAGS) \ $(MM_GLIB_CFLAGS) @@ -47,31 +47,29 @@ WWAN_SYMBOL_VIS_FILE=$(srcdir)/wwan-exports.ver libnm_wwan_la_LDFLAGS = \ -avoid-version \ -Wl,--version-script=$(WWAN_SYMBOL_VIS_FILE) -libnm_wwan_la_LIBADD = $(DBUS_LIBS) $(MM_GLIB_LIBS) +libnm_wwan_la_LIBADD = \ + $(top_builddir)/introspection/libnmdbus.la \ + $(GLIB_LIBS) \ + $(MM_GLIB_LIBS) ########################################################### -nm-device-modem-glue.h: $(top_srcdir)/introspection/nm-device-modem.xml - dbus-binding-tool --prefix=nm_device_modem --mode=glib-server --output=$@ $< - -BUILT_SOURCES += nm-device-modem-glue.h - SYMBOL_VIS_FILE=$(srcdir)/exports.ver libnm_device_plugin_wwan_la_SOURCES = \ nm-wwan-factory.c \ nm-wwan-factory.h \ nm-device-modem.c \ - nm-device-modem.h \ - nm-device-modem-glue.h + nm-device-modem.h libnm_device_plugin_wwan_la_LDFLAGS = \ -module -avoid-version \ -Wl,--version-script=$(SYMBOL_VIS_FILE) libnm_device_plugin_wwan_la_LIBADD = \ + $(top_builddir)/introspection/libnmdbus.la \ libnm-wwan.la \ - $(DBUS_LIBS) + $(GLIB_LIBS) ########################################################### diff --git a/src/devices/wwan/Makefile.in b/src/devices/wwan/Makefile.in index 571b1b7d..ac13135e 100644 --- a/src/devices/wwan/Makefile.in +++ b/src/devices/wwan/Makefile.in @@ -140,7 +140,8 @@ am__uninstall_files_from_dir = { \ am__installdirs = "$(DESTDIR)$(pkglibdir)" LTLIBRARIES = $(pkglib_LTLIBRARIES) am__DEPENDENCIES_1 = -libnm_device_plugin_wwan_la_DEPENDENCIES = libnm-wwan.la \ +libnm_device_plugin_wwan_la_DEPENDENCIES = \ + $(top_builddir)/introspection/libnmdbus.la libnm-wwan.la \ $(am__DEPENDENCIES_1) am_libnm_device_plugin_wwan_la_OBJECTS = nm-wwan-factory.lo \ nm-device-modem.lo @@ -154,8 +155,9 @@ libnm_device_plugin_wwan_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libnm_device_plugin_wwan_la_LDFLAGS) \ $(LDFLAGS) -o $@ -libnm_wwan_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) +libnm_wwan_la_DEPENDENCIES = \ + $(top_builddir)/introspection/libnmdbus.la \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am__objects_1 = nm-modem-enum-types.lo am_libnm_wwan_la_OBJECTS = nm-modem-broadband.lo nm-modem-manager.lo \ nm-modem.lo $(am__objects_1) @@ -243,7 +245,6 @@ BLUEZ5_LIBS = @BLUEZ5_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ -CKDB_PATH = @CKDB_PATH@ CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ @@ -255,8 +256,6 @@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DBUS_CFLAGS = @DBUS_CFLAGS@ -DBUS_GLIB_100_CFLAGS = @DBUS_GLIB_100_CFLAGS@ -DBUS_GLIB_100_LIBS = @DBUS_GLIB_100_LIBS@ DBUS_LIBS = @DBUS_LIBS@ DBUS_SYS_DIR = @DBUS_SYS_DIR@ DEFS = @DEFS@ @@ -266,6 +265,7 @@ DHCPCD_PATH = @DHCPCD_PATH@ DISTRO_NETWORK_SERVICE = @DISTRO_NETWORK_SERVICE@ DLLTOOL = @DLLTOOL@ DNSMASQ_PATH = @DNSMASQ_PATH@ +DNSSEC_TRIGGER_SCRIPT = @DNSSEC_TRIGGER_SCRIPT@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ @@ -320,16 +320,13 @@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ IPTABLES_PATH = @IPTABLES_PATH@ -IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ -IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ LCOV = @LCOV@ LD = @LD@ LDFLAGS = @LDFLAGS@ +LIBAUDIT_CFLAGS = @LIBAUDIT_CFLAGS@ +LIBAUDIT_LIBS = @LIBAUDIT_LIBS@ LIBDL = @LIBDL@ -LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ -LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ -LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ LIBICONV = @LIBICONV@ LIBINTL = @LIBINTL@ LIBM = @LIBM@ @@ -366,6 +363,8 @@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ +NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT = @NM_CONFIG_DEFAULT_LOGGING_AUDIT_TEXT@ +NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT = @NM_CONFIG_LOGGING_BACKEND_DEFAULT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ NM_MICRO_VERSION = @NM_MICRO_VERSION@ NM_MINOR_VERSION = @NM_MINOR_VERSION@ @@ -394,7 +393,6 @@ POLKIT_LIBS = @POLKIT_LIBS@ POSUB = @POSUB@ PPPD_PATH = @PPPD_PATH@ PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ -PPPOE_PATH = @PPPOE_PATH@ QT_CFLAGS = @QT_CFLAGS@ QT_LIBS = @QT_LIBS@ RANLIB = @RANLIB@ @@ -409,6 +407,8 @@ SYSTEMD_200_CFLAGS = @SYSTEMD_200_CFLAGS@ SYSTEMD_200_LIBS = @SYSTEMD_200_LIBS@ SYSTEMD_INHIBIT_CFLAGS = @SYSTEMD_INHIBIT_CFLAGS@ SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ +SYSTEMD_JOURNAL_CFLAGS = @SYSTEMD_JOURNAL_CFLAGS@ +SYSTEMD_JOURNAL_LIBS = @SYSTEMD_JOURNAL_LIBS@ SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ @@ -469,6 +469,7 @@ mkdir_p = @mkdir_p@ nmbinary = @nmbinary@ nmconfdir = @nmconfdir@ nmdatadir = @nmdatadir@ +nmlibdir = @nmlibdir@ nmrundir = @nmrundir@ nmstatedir = @nmstatedir@ oldincludedir = @oldincludedir@ @@ -476,6 +477,7 @@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -497,18 +499,18 @@ AM_CPPFLAGS = \ -I${top_srcdir}/src/devices \ -I${top_srcdir}/src/settings \ -I${top_srcdir}/src/platform \ - -I${top_srcdir}/include \ - -I$(top_builddir)/include \ + -I${top_builddir}/introspection \ + -I${top_srcdir}/shared \ + -I$(top_builddir)/shared \ -I${top_srcdir}/libnm-core \ -I${top_builddir}/libnm-core \ -DG_LOG_DOMAIN=\""NetworkManager-wwan"\" \ - -DNETWORKMANAGER_COMPILATION \ + -DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \ -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ - $(DBUS_CFLAGS) \ $(GLIB_CFLAGS) \ $(MM_GLIB_CFLAGS) -BUILT_SOURCES = $(null) $(GLIB_GENERATED) nm-device-modem-glue.h +BUILT_SOURCES = $(null) $(GLIB_GENERATED) pkglib_LTLIBRARIES = libnm-wwan.la libnm-device-plugin-wwan.la ########################################################### @@ -531,22 +533,28 @@ libnm_wwan_la_LDFLAGS = \ -avoid-version \ -Wl,--version-script=$(WWAN_SYMBOL_VIS_FILE) -libnm_wwan_la_LIBADD = $(DBUS_LIBS) $(MM_GLIB_LIBS) +libnm_wwan_la_LIBADD = \ + $(top_builddir)/introspection/libnmdbus.la \ + $(GLIB_LIBS) \ + $(MM_GLIB_LIBS) + + +########################################################### SYMBOL_VIS_FILE = $(srcdir)/exports.ver libnm_device_plugin_wwan_la_SOURCES = \ nm-wwan-factory.c \ nm-wwan-factory.h \ nm-device-modem.c \ - nm-device-modem.h \ - nm-device-modem-glue.h + nm-device-modem.h libnm_device_plugin_wwan_la_LDFLAGS = \ -module -avoid-version \ -Wl,--version-script=$(SYMBOL_VIS_FILE) libnm_device_plugin_wwan_la_LIBADD = \ + $(top_builddir)/introspection/libnmdbus.la \ libnm-wwan.la \ - $(DBUS_LIBS) + $(GLIB_LIBS) ########################################################### @@ -887,11 +895,6 @@ include $(GLIB_MAKEFILE) @GNOME_CODE_COVERAGE_RULES@ -########################################################### - -nm-device-modem-glue.h: $(top_srcdir)/introspection/nm-device-modem.xml - dbus-binding-tool --prefix=nm_device_modem --mode=glib-server --output=$@ $< - @ENABLE_TESTS_TRUE@check-local: @ENABLE_TESTS_TRUE@ $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-device-plugin-wwan.so $(SYMBOL_VIS_FILE) @ENABLE_TESTS_TRUE@ $(top_srcdir)/tools/check-exports.sh $(builddir)/.libs/libnm-wwan.so $(WWAN_SYMBOL_VIS_FILE) diff --git a/src/devices/wwan/nm-device-modem-glue.h b/src/devices/wwan/nm-device-modem-glue.h deleted file mode 100644 index 21271491..00000000 --- a/src/devices/wwan/nm-device-modem-glue.h +++ /dev/null @@ -1,73 +0,0 @@ -/* Generated by dbus-binding-tool; do not edit! */ - - -#ifndef __dbus_glib_marshal_nm_device_modem_MARSHAL_H__ -#define __dbus_glib_marshal_nm_device_modem_MARSHAL_H__ - -#include <glib-object.h> - -G_BEGIN_DECLS - -#ifdef G_ENABLE_DEBUG -#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v) -#define g_marshal_value_peek_char(v) g_value_get_schar (v) -#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v) -#define g_marshal_value_peek_int(v) g_value_get_int (v) -#define g_marshal_value_peek_uint(v) g_value_get_uint (v) -#define g_marshal_value_peek_long(v) g_value_get_long (v) -#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v) -#define g_marshal_value_peek_int64(v) g_value_get_int64 (v) -#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v) -#define g_marshal_value_peek_enum(v) g_value_get_enum (v) -#define g_marshal_value_peek_flags(v) g_value_get_flags (v) -#define g_marshal_value_peek_float(v) g_value_get_float (v) -#define g_marshal_value_peek_double(v) g_value_get_double (v) -#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v) -#define g_marshal_value_peek_param(v) g_value_get_param (v) -#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v) -#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v) -#define g_marshal_value_peek_object(v) g_value_get_object (v) -#define g_marshal_value_peek_variant(v) g_value_get_variant (v) -#else /* !G_ENABLE_DEBUG */ -/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API. - * Do not access GValues directly in your code. Instead, use the - * g_value_get_*() functions - */ -#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int -#define g_marshal_value_peek_char(v) (v)->data[0].v_int -#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint -#define g_marshal_value_peek_int(v) (v)->data[0].v_int -#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint -#define g_marshal_value_peek_long(v) (v)->data[0].v_long -#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong -#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64 -#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64 -#define g_marshal_value_peek_enum(v) (v)->data[0].v_long -#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong -#define g_marshal_value_peek_float(v) (v)->data[0].v_float -#define g_marshal_value_peek_double(v) (v)->data[0].v_double -#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer -#define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer -#endif /* !G_ENABLE_DEBUG */ - - -G_END_DECLS - -#endif /* __dbus_glib_marshal_nm_device_modem_MARSHAL_H__ */ - -#include <dbus/dbus-glib.h> -static const DBusGMethodInfo dbus_glib_nm_device_modem_methods[] = { -}; - -const DBusGObjectInfo dbus_glib_nm_device_modem_object_info = { 1, - dbus_glib_nm_device_modem_methods, - 0, -"\0", -"org.freedesktop.NetworkManager.Device.Modem\0PropertiesChanged\0\0", -"org.freedesktop.NetworkManager.Device.Modem\0ModemCapabilities\0modem_capabilities\0read\0org.freedesktop.NetworkManager.Device.Modem\0CurrentCapabilities\0current_capabilities\0read\0\0" -}; - diff --git a/src/devices/wwan/nm-device-modem.c b/src/devices/wwan/nm-device-modem.c index ca724c04..edecd24d 100644 --- a/src/devices/wwan/nm-device-modem.c +++ b/src/devices/wwan/nm-device-modem.c @@ -21,14 +21,12 @@ #include "config.h" #include <string.h> -#include <glib.h> +#include "nm-default.h" #include "nm-device-modem.h" #include "nm-modem.h" #include "nm-device-private.h" #include "nm-rfkill-manager.h" -#include "nm-logging.h" -#include "nm-dbus-manager.h" #include "nm-settings-connection.h" #include "nm-modem-broadband.h" #include "NetworkManagerUtils.h" @@ -37,12 +35,12 @@ #include "nm-device-logging.h" _LOG_DECLARE_SELF(NMDeviceModem); +#include "nmdbus-device-modem.h" + G_DEFINE_TYPE (NMDeviceModem, nm_device_modem, NM_TYPE_DEVICE) #define NM_DEVICE_MODEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_MODEM, NMDeviceModemPrivate)) -#include "nm-device-modem-glue.h" - typedef struct { NMModem *modem; NMDeviceModemCapabilities caps; @@ -108,7 +106,7 @@ modem_prepare_result (NMModem *modem, * the device to be auto-activated anymore, which would risk locking * the SIM if the incorrect PIN continues to be used. */ - g_object_set (G_OBJECT (device), NM_DEVICE_AUTOCONNECT, FALSE, NULL); + nm_device_set_autoconnect (device, FALSE); _LOGI (LOGD_MB, "disabling autoconnect due to failed SIM PIN"); } @@ -256,6 +254,12 @@ data_port_changed_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data) } static void +ids_changed_cb (NMModem *modem, GParamSpec *pspec, gpointer user_data) +{ + nm_device_recheck_available_connections (NM_DEVICE (user_data)); +} + +static void modem_state_cb (NMModem *modem, NMModemState new_state, NMModemState old_state, @@ -332,7 +336,7 @@ device_state_changed (NMDevice *device, { NMDeviceModem *self = NM_DEVICE_MODEM (device); NMDeviceModemPrivate *priv = NM_DEVICE_MODEM_GET_PRIVATE (device); - NMConnection *connection = nm_device_get_connection (device); + NMConnection *connection = nm_device_get_applied_connection (device); g_assert (priv->modem); @@ -411,10 +415,7 @@ check_connection_available (NMDevice *device, return FALSE; if (state == NM_MODEM_STATE_LOCKED) { - NMSettingGsm *s_gsm = nm_connection_get_setting_gsm (connection); - - /* Can't use a connection without a PIN if the modem is locked */ - if (!s_gsm || !nm_setting_gsm_get_pin (s_gsm)) + if (!nm_connection_get_setting_gsm (connection)) return FALSE; } @@ -679,6 +680,10 @@ set_modem (NMDeviceModem *self, NMModem *modem) * while in the new ModemManager the data port is set afterwards when the bearer gets * created */ g_signal_connect (modem, "notify::" NM_MODEM_DATA_PORT, G_CALLBACK (data_port_changed_cb), self); + + g_signal_connect (modem, "notify::" NM_MODEM_DEVICE_ID, G_CALLBACK (ids_changed_cb), self); + g_signal_connect (modem, "notify::" NM_MODEM_SIM_ID, G_CALLBACK (ids_changed_cb), self); + g_signal_connect (modem, "notify::" NM_MODEM_SIM_OPERATOR_ID, G_CALLBACK (ids_changed_cb), self); } static void @@ -795,7 +800,7 @@ nm_device_modem_class_init (NMDeviceModemClass *mclass) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); - nm_dbus_manager_register_exported_type (nm_dbus_manager_get (), - G_TYPE_FROM_CLASS (mclass), - &dbus_glib_nm_device_modem_object_info); + nm_exported_object_class_add_interface (NM_EXPORTED_OBJECT_CLASS (mclass), + NMDBUS_TYPE_DEVICE_MODEM_SKELETON, + NULL); } diff --git a/src/devices/wwan/nm-device-modem.h b/src/devices/wwan/nm-device-modem.h index 996195c4..1cf399e1 100644 --- a/src/devices/wwan/nm-device-modem.h +++ b/src/devices/wwan/nm-device-modem.h @@ -21,9 +21,6 @@ #ifndef __NETWORKMANAGER_DEVICE_MODEM_H__ #define __NETWORKMANAGER_DEVICE_MODEM_H__ -#include <glib.h> -#include <glib-object.h> - #include "nm-device.h" #include "nm-modem.h" diff --git a/src/devices/wwan/nm-modem-broadband.c b/src/devices/wwan/nm-modem-broadband.c index ec4f4a2f..427f3ed6 100644 --- a/src/devices/wwan/nm-modem-broadband.c +++ b/src/devices/wwan/nm-modem-broadband.c @@ -20,28 +20,51 @@ #include "config.h" -#include <glib/gi18n.h> #include <string.h> #include <arpa/inet.h> #include <libmm-glib.h> #include "nm-modem-broadband.h" #include "nm-core-internal.h" -#include "nm-logging.h" +#include "nm-default.h" #include "NetworkManagerUtils.h" #include "nm-device-private.h" #include "nm-platform.h" G_DEFINE_TYPE (NMModemBroadband, nm_modem_broadband, NM_TYPE_MODEM) +typedef enum { + CONNECT_STEP_FIRST, + CONNECT_STEP_WAIT_FOR_SIM, + CONNECT_STEP_UNLOCK, + CONNECT_STEP_WAIT_FOR_READY, + CONNECT_STEP_CONNECT, + CONNECT_STEP_LAST +} ConnectStep; + +typedef struct { + NMModemBroadband *self; + ConnectStep step; + + MMModemCapability caps; + NMConnection *connection; + GCancellable *cancellable; + MMSimpleConnectProperties *connect_properties; + GArray *ip_types; + guint ip_types_i; + GError *first_error; +} ConnectContext; + struct _NMModemBroadbandPrivate { /* The modem object from dbus */ MMObject *modem_object; /* Per-interface objects */ MMModem *modem_iface; MMModemSimple *simple_iface; + MMSim *sim_iface; /* Connection setup */ + ConnectContext *ctx; MMBearer *bearer; MMBearerIpConfig *ipv4_config; @@ -257,45 +280,45 @@ create_gsm_connect_properties (NMConnection *connection) return properties; } -typedef struct { - NMModemBroadband *self; - MMModemCapability caps; - MMSimpleConnectProperties *connect_properties; - GArray *ip_types; - guint ip_types_i; - GError *first_error; -} ActStageContext; - static void -act_stage_context_free (ActStageContext *ctx) +connect_context_clear (NMModemBroadband *self) { - g_clear_error (&ctx->first_error); - g_clear_pointer (&ctx->ip_types, (GDestroyNotify) g_array_unref); - g_clear_object (&ctx->connect_properties); - g_object_unref (ctx->self); - g_slice_free (ActStageContext, ctx); + if (self->priv->ctx) { + ConnectContext *ctx = self->priv->ctx; + + g_clear_error (&ctx->first_error); + g_clear_pointer (&ctx->ip_types, (GDestroyNotify) g_array_unref); + g_clear_object (&ctx->cancellable); + g_clear_object (&ctx->connection); + g_clear_object (&ctx->connect_properties); + g_clear_object (&ctx->self); + g_slice_free (ConnectContext, ctx); + self->priv->ctx = NULL; + } } -static void act_stage_context_step (ActStageContext *ctx); +static void connect_context_step (NMModemBroadband *self); static void connect_ready (MMModemSimple *simple_iface, GAsyncResult *res, - ActStageContext *ctx) + NMModemBroadband *self) { + ConnectContext *ctx = self->priv->ctx; GError *error = NULL; NMModemIPMethod ip4_method = NM_MODEM_IP_METHOD_UNKNOWN; NMModemIPMethod ip6_method = NM_MODEM_IP_METHOD_UNKNOWN; - ctx->self->priv->bearer = mm_modem_simple_connect_finish (simple_iface, res, &error); - if (!ctx->self->priv->bearer) { + self->priv->bearer = mm_modem_simple_connect_finish (simple_iface, res, &error); + if (!self->priv->bearer) { if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_SIM_PIN) || (g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_UNAUTHORIZED) && - mm_modem_get_unlock_required (ctx->self->priv->modem_iface) == MM_MODEM_LOCK_SIM_PIN)) { - /* Request PIN */ - ask_for_pin (ctx->self); + mm_modem_get_unlock_required (self->priv->modem_iface) == MM_MODEM_LOCK_SIM_PIN)) { g_error_free (error); - act_stage_context_free (ctx); + + /* Request PIN */ + ask_for_pin (self); + connect_context_clear (self); return; } @@ -312,79 +335,190 @@ connect_ready (MMModemSimple *simple_iface, * retry with the next one, if any. */ ctx->ip_types_i++; - act_stage_context_step (ctx); + connect_context_clear (self); return; } /* Grab IP configurations */ - ctx->self->priv->ipv4_config = mm_bearer_get_ipv4_config (ctx->self->priv->bearer); - if (ctx->self->priv->ipv4_config) - ip4_method = get_bearer_ip_method (ctx->self->priv->ipv4_config); + self->priv->ipv4_config = mm_bearer_get_ipv4_config (self->priv->bearer); + if (self->priv->ipv4_config) + ip4_method = get_bearer_ip_method (self->priv->ipv4_config); - ctx->self->priv->ipv6_config = mm_bearer_get_ipv6_config (ctx->self->priv->bearer); - if (ctx->self->priv->ipv6_config) - ip6_method = get_bearer_ip_method (ctx->self->priv->ipv6_config); + self->priv->ipv6_config = mm_bearer_get_ipv6_config (self->priv->bearer); + if (self->priv->ipv6_config) + ip6_method = get_bearer_ip_method (self->priv->ipv6_config); if (ip4_method == NM_MODEM_IP_METHOD_UNKNOWN && ip6_method == NM_MODEM_IP_METHOD_UNKNOWN) { nm_log_warn (LOGD_MB, "(%s): failed to connect modem: invalid bearer IP configuration", - nm_modem_get_uid (NM_MODEM (ctx->self))); - g_signal_emit_by_name (ctx->self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_CONFIG_FAILED); - act_stage_context_free (ctx); + nm_modem_get_uid (NM_MODEM (self))); + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_CONFIG_FAILED); + connect_context_clear (self); return; } - g_object_set (ctx->self, - NM_MODEM_DATA_PORT, mm_bearer_get_interface (ctx->self->priv->bearer), + g_object_set (self, + NM_MODEM_DATA_PORT, mm_bearer_get_interface (self->priv->bearer), NM_MODEM_IP4_METHOD, ip4_method, NM_MODEM_IP6_METHOD, ip6_method, - NM_MODEM_IP_TIMEOUT, mm_bearer_get_ip_timeout (ctx->self->priv->bearer), + NM_MODEM_IP_TIMEOUT, mm_bearer_get_ip_timeout (self->priv->bearer), NULL); - g_signal_emit_by_name (ctx->self, NM_MODEM_PREPARE_RESULT, TRUE, NM_DEVICE_STATE_REASON_NONE); - act_stage_context_free (ctx); + ctx->step++; + connect_context_step (self); } static void -act_stage_context_step (ActStageContext *ctx) +send_pin_ready (MMSim *sim, GAsyncResult *result, NMModemBroadband *self) { - if (ctx->ip_types_i < ctx->ip_types->len) { - NMModemIPType current; - - current = g_array_index (ctx->ip_types, NMModemIPType, ctx->ip_types_i); - - if (current == NM_MODEM_IP_TYPE_IPV4) - mm_simple_connect_properties_set_ip_type (ctx->connect_properties, MM_BEARER_IP_FAMILY_IPV4); - else if (current == NM_MODEM_IP_TYPE_IPV6) - mm_simple_connect_properties_set_ip_type (ctx->connect_properties, MM_BEARER_IP_FAMILY_IPV6); - else if (current == NM_MODEM_IP_TYPE_IPV4V6) - mm_simple_connect_properties_set_ip_type (ctx->connect_properties, MM_BEARER_IP_FAMILY_IPV4V6); - else - g_assert_not_reached (); - - nm_log_dbg (LOGD_MB, "(%s): launching connection with ip type '%s'", - nm_modem_get_uid (NM_MODEM (ctx->self)), - nm_modem_ip_type_to_string (current)); - - mm_modem_simple_connect (ctx->self->priv->simple_iface, - ctx->connect_properties, - NULL, - (GAsyncReadyCallback)connect_ready, - ctx); + GError *error = NULL; + + if (!mm_sim_send_pin_finish (sim, result, &error)) { + if (g_error_matches (error, MM_MOBILE_EQUIPMENT_ERROR, MM_MOBILE_EQUIPMENT_ERROR_SIM_PIN) || + (g_error_matches (error, MM_CORE_ERROR, MM_CORE_ERROR_UNAUTHORIZED) && + mm_modem_get_unlock_required (self->priv->modem_iface) == MM_MODEM_LOCK_SIM_PIN)) { + ask_for_pin (self); + } else { + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (error)); + } + g_error_free (error); return; + } + + self->priv->ctx->step++; + connect_context_step (self); +} + +static void +connect_context_step (NMModemBroadband *self) +{ + ConnectContext *ctx = self->priv->ctx; + + switch (ctx->step) { + case CONNECT_STEP_FIRST: + ctx->step++; + /* fall through */ + + case CONNECT_STEP_WAIT_FOR_SIM: + if (MODEM_CAPS_3GPP (ctx->caps) && !self->priv->sim_iface) { + /* Have to wait for the SIM to show up */ + break; + } + ctx->step++; + /* fall through */ + + case CONNECT_STEP_UNLOCK: + if ( MODEM_CAPS_3GPP (ctx->caps) + && mm_modem_get_unlock_required (self->priv->modem_iface) == MM_MODEM_LOCK_SIM_PIN) { + NMSettingGsm *s_gsm = nm_connection_get_setting_gsm (ctx->connection); + const char *pin = nm_setting_gsm_get_pin (s_gsm); + + /* If we have a PIN already, send it. If we don't, get it. */ + if (pin) { + mm_sim_send_pin (self->priv->sim_iface, + pin, + ctx->cancellable, + (GAsyncReadyCallback) send_pin_ready, + self); + } else { + ask_for_pin (self); + } + break; + } + ctx->step++; + /* fall through */ + + case CONNECT_STEP_WAIT_FOR_READY: { + GError *error = NULL; + + if (mm_modem_get_state (self->priv->modem_iface) <= MM_MODEM_STATE_LOCKED) + break; + + /* Create core connect properties based on the modem capabilities */ + g_assert (!ctx->connect_properties); + + if (MODEM_CAPS_3GPP (ctx->caps)) + ctx->connect_properties = create_gsm_connect_properties (ctx->connection); + else if (MODEM_CAPS_3GPP2 (ctx->caps)) + ctx->connect_properties = create_cdma_connect_properties (ctx->connection); + else { + nm_log_warn (LOGD_MB, "(%s): Failed to connect '%s': not a mobile broadband modem", + nm_modem_get_uid (NM_MODEM (self)), + nm_connection_get_id (ctx->connection)); + + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED); + connect_context_clear (self); + break; + } + g_assert (ctx->connect_properties); + + /* Build up list of IP types that we need to use in the retries */ + ctx->ip_types = nm_modem_get_connection_ip_type (NM_MODEM (self), ctx->connection, &error); + if (!ctx->ip_types) { + nm_log_warn (LOGD_MB, "(%s): Failed to connect '%s': %s", + nm_modem_get_uid (NM_MODEM (self)), + nm_connection_get_id (ctx->connection), + error ? error->message : "unknown error"); + g_clear_error (&error); + + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED); + connect_context_clear (self); + break; + } + + ctx->step++; + /* fall through */ } - /* If we have a saved error from a previous attempt, use it */ - if (!ctx->first_error) - ctx->first_error = g_error_new_literal (NM_DEVICE_ERROR, - NM_DEVICE_ERROR_INVALID_CONNECTION, - "invalid bearer IP configuration"); - - nm_log_warn (LOGD_MB, "(%s): failed to connect modem: %s", - nm_modem_get_uid (NM_MODEM (ctx->self)), - ctx->first_error->message); - g_signal_emit_by_name (ctx->self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (ctx->first_error)); - act_stage_context_free (ctx); + case CONNECT_STEP_CONNECT: + if (ctx->ip_types_i < ctx->ip_types->len) { + NMModemIPType current; + + current = g_array_index (ctx->ip_types, NMModemIPType, ctx->ip_types_i); + + if (current == NM_MODEM_IP_TYPE_IPV4) + mm_simple_connect_properties_set_ip_type (ctx->connect_properties, MM_BEARER_IP_FAMILY_IPV4); + else if (current == NM_MODEM_IP_TYPE_IPV6) + mm_simple_connect_properties_set_ip_type (ctx->connect_properties, MM_BEARER_IP_FAMILY_IPV6); + else if (current == NM_MODEM_IP_TYPE_IPV4V6) + mm_simple_connect_properties_set_ip_type (ctx->connect_properties, MM_BEARER_IP_FAMILY_IPV4V6); + else + g_assert_not_reached (); + + nm_log_dbg (LOGD_MB, "(%s): launching connection with ip type '%s'", + nm_modem_get_uid (NM_MODEM (self)), + nm_modem_ip_type_to_string (current)); + + mm_modem_simple_connect (self->priv->simple_iface, + ctx->connect_properties, + NULL, + (GAsyncReadyCallback) connect_ready, + self); + break; + } + + ctx->step++; + /* fall through */ + + case CONNECT_STEP_LAST: + if (self->priv->ipv4_config || self->priv->ipv6_config) { + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, TRUE, NM_DEVICE_STATE_REASON_NONE); + } else { + /* If we have a saved error from a previous attempt, use it */ + if (!ctx->first_error) + ctx->first_error = g_error_new_literal (NM_DEVICE_ERROR, + NM_DEVICE_ERROR_INVALID_CONNECTION, + "invalid bearer IP configuration"); + + nm_log_warn (LOGD_MB, "(%s): failed to connect modem: %s", + nm_modem_get_uid (NM_MODEM (self)), + ctx->first_error->message); + g_signal_emit_by_name (self, NM_MODEM_PREPARE_RESULT, FALSE, translate_mm_error (ctx->first_error)); + } + + connect_context_clear (self); + break; + } } static NMActStageReturn @@ -393,8 +527,6 @@ act_stage1_prepare (NMModem *_self, NMDeviceStateReason *reason) { NMModemBroadband *self = NM_MODEM_BROADBAND (_self); - ActStageContext *ctx; - GError *error = NULL; /* Make sure we can get the Simple interface from the modem */ if (!self->priv->simple_iface) { @@ -407,41 +539,16 @@ act_stage1_prepare (NMModem *_self, } } - /* Allocate new context for this activation stage attempt */ - ctx = g_slice_new0 (ActStageContext); - ctx->self = NM_MODEM_BROADBAND (g_object_ref (self)); - ctx->caps = mm_modem_get_current_capabilities (self->priv->modem_iface); + connect_context_clear (self); - /* Create core connect properties based on the modem capabilities */ - if (MODEM_CAPS_3GPP (ctx->caps)) - ctx->connect_properties = create_gsm_connect_properties (connection); - else if (MODEM_CAPS_3GPP2 (ctx->caps)) - ctx->connect_properties = create_cdma_connect_properties (connection); - else { - nm_log_warn (LOGD_MB, "(%s): Failed to connect '%s': not a mobile broadband modem", - nm_modem_get_uid (NM_MODEM (self)), - nm_connection_get_id (connection)); - act_stage_context_free (ctx); - *reason = NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED; - return NM_ACT_STAGE_RETURN_FAILURE; - } - g_assert (ctx->connect_properties); - - /* Checkout list of IP types that we need to use in the retries */ - ctx->ip_types = nm_modem_get_connection_ip_type (NM_MODEM (self), connection, &error); - if (!ctx->ip_types) { - nm_log_warn (LOGD_MB, "(%s): Failed to connect '%s': %s", - nm_modem_get_uid (NM_MODEM (self)), - nm_connection_get_id (connection), - error ? error->message : "unknown error"); - g_clear_error (&error); - act_stage_context_free (ctx); - *reason = NM_DEVICE_STATE_REASON_MODEM_INIT_FAILED; - return NM_ACT_STAGE_RETURN_FAILURE; - } + /* Allocate new context for this connect stage attempt */ + self->priv->ctx = g_slice_new0 (ConnectContext); + self->priv->ctx->caps = mm_modem_get_current_capabilities (self->priv->modem_iface); + self->priv->ctx->cancellable = g_cancellable_new (); + self->priv->ctx->connection = g_object_ref (connection); g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (self->priv->simple_iface), MODEM_CONNECT_TIMEOUT_SECS * 1000); - act_stage_context_step (ctx); + connect_context_step (self); return NM_ACT_STAGE_RETURN_POSTPONE; } @@ -715,6 +822,7 @@ static_stage3_ip4_done (NMModemBroadband *self) { GError *error = NULL; NMIP4Config *config = NULL; + const char *data_port; const gchar *address_string; const gchar *gw_string; guint32 address_network; @@ -724,6 +832,7 @@ static_stage3_ip4_done (NMModemBroadband *self) guint i; g_assert (self->priv->ipv4_config); + g_assert (self->priv->bearer); nm_log_info (LOGD_MB, "(%s): IPv4 static configuration:", nm_modem_get_uid (NM_MODEM (self))); @@ -743,10 +852,13 @@ static_stage3_ip4_done (NMModemBroadband *self) gw_string = mm_bearer_ip_config_get_gateway (self->priv->ipv4_config); ip4_string_to_num (gw_string, &gw); - config = nm_ip4_config_new (); + data_port = mm_bearer_get_interface (self->priv->bearer); + g_assert (data_port); + config = nm_ip4_config_new (nm_platform_link_get_ifindex (NM_PLATFORM_GET, data_port)); memset (&address, 0, sizeof (address)); address.address = address_network; + address.peer_address = address_network; address.plen = mm_bearer_ip_config_get_prefix (self->priv->ipv4_config); address.source = NM_IP_CONFIG_SOURCE_WWAN; nm_ip4_config_add_address (config, &address); @@ -796,6 +908,7 @@ stage3_ip6_done (NMModemBroadband *self) { GError *error = NULL; NMIP6Config *config = NULL; + const char *data_port; const gchar *address_string; NMPlatformIP6Address address; NMModemIPMethod ip_method; @@ -833,7 +946,9 @@ stage3_ip6_done (NMModemBroadband *self) nm_log_info (LOGD_MB, "(%s): IPv6 base configuration:", nm_modem_get_uid (NM_MODEM (self))); - config = nm_ip6_config_new (); + data_port = mm_bearer_get_interface (self->priv->bearer); + g_assert (data_port); + config = nm_ip6_config_new (nm_platform_link_get_ifindex (NM_PLATFORM_GET, data_port)); address.plen = mm_bearer_ip_config_get_prefix (self->priv->ipv6_config); nm_ip6_config_add_address (config, &address); @@ -941,10 +1056,11 @@ simple_disconnect_ready (MMModemSimple *modem_iface, GError *error = NULL; if (!mm_modem_simple_disconnect_finish (modem_iface, res, &error)) { - if (ctx->warn) + if (ctx->warn && !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) { nm_log_warn (LOGD_MB, "(%s) failed to disconnect modem: %s", nm_modem_get_uid (NM_MODEM (ctx->self)), error->message); + } g_simple_async_result_take_error (ctx->result, error); } @@ -1042,7 +1158,6 @@ modem_state_changed (MMModem *modem, MMModemStateChangeReason reason, NMModemBroadband *self) { - /* After the SIM is unlocked MM1 will move the device to INITIALIZING which * is an unavailable state. That makes state handling confusing here, so * suppress this state change and let the modem move from LOCKED to DISABLED. @@ -1053,6 +1168,9 @@ modem_state_changed (MMModem *modem, nm_modem_set_state (NM_MODEM (self), mm_state_to_nm (new_state), mm_modem_state_change_reason_get_string (reason)); + + if (self->priv->ctx && self->priv->ctx->step == CONNECT_STEP_WAIT_FOR_READY) + connect_context_step (self); } /*****************************************************************************/ @@ -1114,12 +1232,23 @@ get_sim_ready (MMModem *modem, GError *error = NULL; MMSim *new_sim; + new_sim = mm_modem_get_sim_finish (modem, res, &error); - if (new_sim) { + if (new_sim != self->priv->sim_iface) { + g_clear_object (&self->priv->sim_iface); + self->priv->sim_iface = new_sim; + } else + g_clear_object (&new_sim); + + if (self->priv->sim_iface) { g_object_set (G_OBJECT (self), - NM_MODEM_SIM_ID, mm_sim_get_identifier (new_sim), + NM_MODEM_SIM_ID, mm_sim_get_identifier (self->priv->sim_iface), + NM_MODEM_SIM_OPERATOR_ID, mm_sim_get_operator_identifier (self->priv->sim_iface), NULL); - g_object_unref (new_sim); + + /* If we're waiting for the SIM during a connect, proceed with the connect */ + if (self->priv->ctx && self->priv->ctx->step == CONNECT_STEP_WAIT_FOR_SIM) + connect_context_step (self); } else { nm_log_warn (LOGD_MB, "(%s): failed to retrieve SIM object: %s", nm_modem_get_uid (NM_MODEM (self)), @@ -1142,7 +1271,10 @@ sim_changed (MMModem *modem, GParamSpec *pspec, gpointer user_data) (GAsyncReadyCallback) get_sim_ready, g_object_ref (self)); } else - g_object_set (G_OBJECT (self), NM_MODEM_SIM_ID, NULL, NULL); + g_object_set (G_OBJECT (self), + NM_MODEM_SIM_ID, NULL, + NM_MODEM_SIM_OPERATOR_ID, NULL, + NULL); } static void @@ -1226,11 +1358,13 @@ dispose (GObject *object) { NMModemBroadband *self = NM_MODEM_BROADBAND (object); + connect_context_clear (self); g_clear_object (&self->priv->ipv4_config); g_clear_object (&self->priv->ipv6_config); g_clear_object (&self->priv->bearer); g_clear_object (&self->priv->modem_iface); g_clear_object (&self->priv->simple_iface); + g_clear_object (&self->priv->sim_iface); g_clear_object (&self->priv->modem_object); G_OBJECT_CLASS (nm_modem_broadband_parent_class)->dispose (object); diff --git a/src/devices/wwan/nm-modem-broadband.h b/src/devices/wwan/nm-modem-broadband.h index 2268bac4..a54e63a6 100644 --- a/src/devices/wwan/nm-modem-broadband.h +++ b/src/devices/wwan/nm-modem-broadband.h @@ -21,7 +21,6 @@ #ifndef __NETWORKMANAGER_MODEM_BROADBAND_H__ #define __NETWORKMANAGER_MODEM_BROADBAND_H__ -#include <glib-object.h> #include "nm-modem.h" G_BEGIN_DECLS diff --git a/src/devices/wwan/nm-modem-enum-types.c b/src/devices/wwan/nm-modem-enum-types.c index 6fbb3b6d..2d02ede9 100644 --- a/src/devices/wwan/nm-modem-enum-types.c +++ b/src/devices/wwan/nm-modem-enum-types.c @@ -3,6 +3,8 @@ /* Generated by glib-mkenums. Do not edit */ +#include "config.h" + #include "nm-modem-enum-types.h" #include "nm-modem.h" diff --git a/src/devices/wwan/nm-modem-manager.c b/src/devices/wwan/nm-modem-manager.c index f0e56926..c28d86ad 100644 --- a/src/devices/wwan/nm-modem-manager.c +++ b/src/devices/wwan/nm-modem-manager.c @@ -27,7 +27,8 @@ #include <libmm-glib.h> #include "nm-modem-manager.h" -#include "nm-logging.h" +#include "nm-default.h" +#include "nm-dbus-compat.h" #include "nm-modem.h" #include "nm-modem-broadband.h" @@ -193,10 +194,7 @@ modem_manager_name_owner_changed (MMManager *modem_manager, gchar *name_owner; /* Quit poking, if any */ - if (self->priv->mm_launch_id) { - g_source_remove (self->priv->mm_launch_id); - self->priv->mm_launch_id = 0; - } + nm_clear_g_source (&self->priv->mm_launch_id); name_owner = g_dbus_object_manager_client_get_name_owner (G_DBUS_OBJECT_MANAGER_CLIENT (modem_manager)); if (!name_owner) { @@ -265,7 +263,7 @@ modem_manager_poke (NMModemManager *self) g_dbus_connection_call (self->priv->dbus_connection, "org.freedesktop.ModemManager1", "/org/freedesktop/ModemManager1", - "org.freedesktop.DBus.Peer", + DBUS_INTERFACE_PEER, "Ping", NULL, /* inputs */ NULL, /* outputs */ @@ -434,10 +432,7 @@ dispose (GObject *object) { NMModemManager *self = NM_MODEM_MANAGER (object); - if (self->priv->mm_launch_id) { - g_source_remove (self->priv->mm_launch_id); - self->priv->mm_launch_id = 0; - } + nm_clear_g_source (&self->priv->mm_launch_id); modem_manager_clear_signals (self); g_clear_object (&self->priv->modem_manager); diff --git a/src/devices/wwan/nm-modem-manager.h b/src/devices/wwan/nm-modem-manager.h index 9e0db41e..b0014c6a 100644 --- a/src/devices/wwan/nm-modem-manager.h +++ b/src/devices/wwan/nm-modem-manager.h @@ -23,7 +23,6 @@ #ifndef __NETWORKMANAGER_MODEM_MANAGER_H__ #define __NETWORKMANAGER_MODEM_MANAGER_H__ -#include <glib-object.h> #include "nm-modem.h" #define NM_TYPE_MODEM_MANAGER (nm_modem_manager_get_type ()) diff --git a/src/devices/wwan/nm-modem.c b/src/devices/wwan/nm-modem.c index 3385a6fd..15104307 100644 --- a/src/devices/wwan/nm-modem.c +++ b/src/devices/wwan/nm-modem.c @@ -22,17 +22,17 @@ #include "config.h" #include <string.h> + #include "nm-modem.h" +#include "nm-core-internal.h" #include "nm-platform.h" -#include "nm-dbus-manager.h" #include "nm-setting-connection.h" -#include "nm-properties-changed-signal.h" -#include "nm-logging.h" +#include "nm-default.h" #include "NetworkManagerUtils.h" #include "nm-device-private.h" -#include "nm-dbus-glib-types.h" #include "nm-modem-enum-types.h" #include "nm-route-manager.h" +#include "gsystem-local-alloc.h" G_DEFINE_TYPE (NMModem, nm_modem, G_TYPE_OBJECT) @@ -52,6 +52,7 @@ enum { PROP_DEVICE_ID, PROP_SIM_ID, PROP_IP_TYPES, + PROP_SIM_OPERATOR_ID, LAST_PROP }; @@ -71,12 +72,13 @@ typedef struct { char *device_id; char *sim_id; NMModemIPType ip_types; + char *sim_operator_id; NMPPPManager *ppp_manager; NMActRequest *act_request; guint32 secrets_tries; - guint32 secrets_id; + NMActRequestGetSecretsCallId secrets_id; guint32 mm_ip_timeout; @@ -287,7 +289,7 @@ nm_modem_get_connection_ip_type (NMModem *self, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, "Connection requested IPv4 but IPv4 is " - "unsuported by the modem."); + "unsupported by the modem."); return NULL; } return build_single_ip_type_array (NM_MODEM_IP_TYPE_IPV4); @@ -299,7 +301,7 @@ nm_modem_get_connection_ip_type (NMModem *self, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION, "Connection requested IPv6 but IPv6 is " - "unsuported by the modem."); + "unsupported by the modem."); return NULL; } return build_single_ip_type_array (NM_MODEM_IP_TYPE_IPV6); @@ -350,6 +352,24 @@ nm_modem_get_connection_ip_type (NMModem *self, return NULL; } +const char * +nm_modem_get_device_id (NMModem *self) +{ + return NM_MODEM_GET_PRIVATE (self)->device_id; +} + +const char * +nm_modem_get_sim_id (NMModem *self) +{ + return NM_MODEM_GET_PRIVATE (self)->sim_id; +} + +const char * +nm_modem_get_sim_operator_id (NMModem *self) +{ + return NM_MODEM_GET_PRIVATE (self)->sim_operator_id; +} + /*****************************************************************************/ /* IP method PPP */ @@ -493,7 +513,7 @@ ppp_stage3_ip_config_start (NMModem *self, return NM_ACT_STAGE_RETURN_POSTPONE; if (NM_MODEM_GET_CLASS (self)->get_user_pass) { - NMConnection *connection = nm_act_request_get_connection (req); + NMConnection *connection = nm_act_request_get_applied_connection (req); g_assert (connection); if (!NM_MODEM_GET_CLASS (self)->get_user_pass (self, connection, &ppp_name, NULL)) @@ -511,7 +531,7 @@ ppp_stage3_ip_config_start (NMModem *self, priv->ppp_manager = nm_ppp_manager_new (priv->data_port); if (nm_ppp_manager_start (priv->ppp_manager, req, ppp_name, ip_timeout, &error)) { - g_signal_connect (priv->ppp_manager, "state-changed", + g_signal_connect (priv->ppp_manager, NM_PPP_MANAGER_STATE_CHANGED, G_CALLBACK (ppp_state_changed), self); g_signal_connect (priv->ppp_manager, "ip4-config", @@ -532,8 +552,7 @@ ppp_stage3_ip_config_start (NMModem *self, error && error->message ? error->message : "(unknown)"); g_error_free (error); - g_object_unref (priv->ppp_manager); - priv->ppp_manager = NULL; + nm_exported_object_clear_and_unexport (&priv->ppp_manager); *reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED; ret = NM_ACT_STAGE_RETURN_FAILURE; @@ -563,7 +582,7 @@ nm_modem_stage3_ip4_config_start (NMModem *self, req = nm_device_get_act_request (device); g_assert (req); - connection = nm_act_request_get_connection (req); + connection = nm_act_request_get_applied_connection (req); g_assert (connection); method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP4_CONFIG); @@ -680,7 +699,7 @@ nm_modem_stage3_ip6_config_start (NMModem *self, g_return_val_if_fail (NM_IS_ACT_REQUEST (req), NM_ACT_STAGE_RETURN_FAILURE); g_return_val_if_fail (reason != NULL, NM_ACT_STAGE_RETURN_FAILURE); - connection = nm_act_request_get_connection (req); + connection = nm_act_request_get_applied_connection (req); g_assert (connection); method = nm_utils_get_ip_config_method (connection, NM_TYPE_SETTING_IP6_CONFIG); @@ -725,16 +744,13 @@ cancel_get_secrets (NMModem *self) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); - if (priv->secrets_id) { - nm_act_request_cancel_secrets (priv->act_request, priv->secrets_id); - priv->secrets_id = 0; - } + nm_act_request_cancel_secrets (priv->act_request, priv->secrets_id); } static void modem_secrets_cb (NMActRequest *req, - guint32 call_id, - NMConnection *connection, + NMActRequestGetSecretsCallId call_id, + NMSettingsConnection *connection, GError *error, gpointer user_data) { @@ -743,7 +759,10 @@ modem_secrets_cb (NMActRequest *req, g_return_if_fail (call_id == priv->secrets_id); - priv->secrets_id = 0; + priv->secrets_id = NULL; + + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; if (error) nm_log_warn (LOGD_MB, "(%s): %s", nm_modem_get_uid (self), error->message); @@ -751,7 +770,7 @@ modem_secrets_cb (NMActRequest *req, g_signal_emit (self, signals[AUTH_RESULT], 0, error); } -gboolean +void nm_modem_get_secrets (NMModem *self, const char *setting_name, gboolean request_new, @@ -770,10 +789,8 @@ nm_modem_get_secrets (NMModem *self, hint, modem_secrets_cb, self); - if (priv->secrets_id) - g_signal_emit (self, signals[AUTH_REQUESTED], 0); - - return !!(priv->secrets_id); + g_return_if_fail (priv->secrets_id); + g_signal_emit (self, signals[AUTH_REQUESTED], 0); } /*****************************************************************************/ @@ -793,8 +810,7 @@ nm_modem_act_stage1_prepare (NMModem *self, NMDeviceStateReason *reason) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); - NMActStageReturn ret; - GPtrArray *hints = NULL; + gs_unref_ptrarray GPtrArray *hints = NULL; const char *setting_name = NULL; NMSecretAgentGetSecretsFlags flags = NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION; NMConnection *connection; @@ -803,7 +819,7 @@ nm_modem_act_stage1_prepare (NMModem *self, g_object_unref (priv->act_request); priv->act_request = g_object_ref (req); - connection = nm_act_request_get_connection (req); + connection = nm_act_request_get_applied_connection (req); g_assert (connection); setting_name = nm_connection_need_secrets (connection, &hints); @@ -823,18 +839,9 @@ nm_modem_act_stage1_prepare (NMModem *self, hints ? g_ptr_array_index (hints, 0) : NULL, modem_secrets_cb, self); - if (priv->secrets_id) { - g_signal_emit (self, signals[AUTH_REQUESTED], 0); - ret = NM_ACT_STAGE_RETURN_POSTPONE; - } else { - *reason = NM_DEVICE_STATE_REASON_NO_SECRETS; - ret = NM_ACT_STAGE_RETURN_FAILURE; - } - - if (hints) - g_ptr_array_free (hints, TRUE); - - return ret; + g_return_val_if_fail (priv->secrets_id, NM_ACT_STAGE_RETURN_FAILURE); + g_signal_emit (self, signals[AUTH_REQUESTED], 0); + return NM_ACT_STAGE_RETURN_POSTPONE; } /*****************************************************************************/ @@ -859,6 +866,67 @@ nm_modem_act_stage2_config (NMModem *self, gboolean nm_modem_check_connection_compatible (NMModem *self, NMConnection *connection) { + NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (self); + NMSettingConnection *s_con; + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + + if (g_str_equal (nm_setting_connection_get_connection_type (s_con), + NM_SETTING_GSM_SETTING_NAME)) { + NMSettingGsm *s_gsm; + const char *str; + + s_gsm = nm_connection_get_setting_gsm (connection); + if (!s_gsm) + return FALSE; + + str = nm_setting_gsm_get_device_id (s_gsm); + if (str) { + if (!priv->device_id) { + nm_log_dbg (LOGD_MB, "(%s): %s/%s has device-id, device does not", + priv->uid, + nm_connection_get_uuid (connection), + nm_connection_get_id (connection)); + return FALSE; + } + if (strcmp (str, priv->device_id)) { + nm_log_dbg (LOGD_MB, "(%s): %s/%s device-id mismatch", + priv->uid, + nm_connection_get_uuid (connection), + nm_connection_get_id (connection)); + return FALSE; + } + } + + /* SIM properties may not be available before the SIM is unlocked, so + * to ensure that autoconnect works, the connection's SIM properties + * are only compared if present on the device. + */ + + str = nm_setting_gsm_get_sim_id (s_gsm); + if (str && priv->sim_id) { + if (strcmp (str, priv->sim_id)) { + nm_log_dbg (LOGD_MB, "(%s): %s/%s sim-id mismatch", + priv->uid, + nm_connection_get_uuid (connection), + nm_connection_get_id (connection)); + return FALSE; + } + } + + str = nm_setting_gsm_get_sim_operator_id (s_gsm); + if (str && priv->sim_operator_id) { + if (strcmp (str, priv->sim_operator_id)) { + nm_log_dbg (LOGD_MB, "(%s): %s/%s sim-operator-id mismatch", + priv->uid, + nm_connection_get_uuid (connection), + nm_connection_get_id (connection)); + return FALSE; + } + } + } + if (NM_MODEM_GET_CLASS (self)->check_connection_compatible) return NM_MODEM_GET_CLASS (self)->check_connection_compatible (self, connection); return FALSE; @@ -899,10 +967,7 @@ deactivate_cleanup (NMModem *self, NMDevice *device) priv->in_bytes = priv->out_bytes = 0; - if (priv->ppp_manager) { - g_object_unref (priv->ppp_manager); - priv->ppp_manager = NULL; - } + nm_exported_object_clear_and_unexport (&priv->ppp_manager); if (device) { g_return_if_fail (NM_IS_DEVICE (device)); @@ -1315,6 +1380,9 @@ get_property (GObject *object, guint prop_id, case PROP_IP_TYPES: g_value_set_uint (value, priv->ip_types); break; + case PROP_SIM_OPERATOR_ID: + g_value_set_string (value, priv->sim_operator_id); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1326,6 +1394,7 @@ set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { NMModemPrivate *priv = NM_MODEM_GET_PRIVATE (object); + const char *s; switch (prop_id) { case PROP_PATH: @@ -1369,6 +1438,12 @@ set_property (GObject *object, guint prop_id, case PROP_IP_TYPES: priv->ip_types = g_value_get_uint (value); break; + case PROP_SIM_OPERATOR_ID: + g_clear_pointer (&priv->sim_operator_id, g_free); + s = g_value_get_string (value); + if (s && s[0]) + priv->sim_operator_id = g_strdup (s); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1400,6 +1475,7 @@ finalize (GObject *object) g_free (priv->data_port); g_free (priv->device_id); g_free (priv->sim_id); + g_free (priv->sim_operator_id); G_OBJECT_CLASS (nm_modem_parent_class)->finalize (object); } @@ -1514,6 +1590,13 @@ nm_modem_class_init (NMModemClass *klass) 0, G_MAXUINT32, NM_MODEM_IP_TYPE_IPV4, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property + (object_class, PROP_SIM_OPERATOR_ID, + g_param_spec_string (NM_MODEM_SIM_OPERATOR_ID, "", "", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + /* Signals */ signals[PPP_STATS] = diff --git a/src/devices/wwan/nm-modem.h b/src/devices/wwan/nm-modem.h index 2cace890..60e5589b 100644 --- a/src/devices/wwan/nm-modem.h +++ b/src/devices/wwan/nm-modem.h @@ -22,7 +22,7 @@ #ifndef __NETWORKMANAGER_MODEM_H__ #define __NETWORKMANAGER_MODEM_H__ -#include <glib-object.h> +#include "nm-default.h" #include "ppp-manager/nm-ppp-manager.h" #include "nm-device.h" @@ -36,18 +36,19 @@ G_BEGIN_DECLS #define NM_MODEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_MODEM, NMModemClass)) /* Properties */ -#define NM_MODEM_UID "uid" -#define NM_MODEM_PATH "path" -#define NM_MODEM_DRIVER "driver" -#define NM_MODEM_CONTROL_PORT "control-port" -#define NM_MODEM_DATA_PORT "data-port" -#define NM_MODEM_IP4_METHOD "ip4-method" -#define NM_MODEM_IP6_METHOD "ip6-method" -#define NM_MODEM_IP_TIMEOUT "ip-timeout" -#define NM_MODEM_STATE "state" -#define NM_MODEM_DEVICE_ID "device-id" -#define NM_MODEM_SIM_ID "sim-id" -#define NM_MODEM_IP_TYPES "ip-types" /* Supported IP types */ +#define NM_MODEM_UID "uid" +#define NM_MODEM_PATH "path" +#define NM_MODEM_DRIVER "driver" +#define NM_MODEM_CONTROL_PORT "control-port" +#define NM_MODEM_DATA_PORT "data-port" +#define NM_MODEM_IP4_METHOD "ip4-method" +#define NM_MODEM_IP6_METHOD "ip6-method" +#define NM_MODEM_IP_TIMEOUT "ip-timeout" +#define NM_MODEM_STATE "state" +#define NM_MODEM_DEVICE_ID "device-id" +#define NM_MODEM_SIM_ID "sim-id" +#define NM_MODEM_IP_TYPES "ip-types" /* Supported IP types */ +#define NM_MODEM_SIM_OPERATOR_ID "sim-operator-id" /* Signals */ #define NM_MODEM_PPP_STATS "ppp-stats" @@ -179,12 +180,15 @@ typedef struct { GType nm_modem_get_type (void); -const char *nm_modem_get_path (NMModem *modem); -const char *nm_modem_get_uid (NMModem *modem); -const char *nm_modem_get_control_port (NMModem *modem); -const char *nm_modem_get_data_port (NMModem *modem); -const char *nm_modem_get_driver (NMModem *modem); -gboolean nm_modem_get_iid (NMModem *modem, NMUtilsIPv6IfaceId *out_iid); +const char *nm_modem_get_path (NMModem *modem); +const char *nm_modem_get_uid (NMModem *modem); +const char *nm_modem_get_control_port (NMModem *modem); +const char *nm_modem_get_data_port (NMModem *modem); +const char *nm_modem_get_driver (NMModem *modem); +const char *nm_modem_get_device_id (NMModem *modem); +const char *nm_modem_get_sim_id (NMModem *modem); +const char *nm_modem_get_sim_operator_id (NMModem *modem); +gboolean nm_modem_get_iid (NMModem *modem, NMUtilsIPv6IfaceId *out_iid); gboolean nm_modem_owns_port (NMModem *modem, const char *iface); @@ -218,10 +222,10 @@ NMActStageReturn nm_modem_stage3_ip6_config_start (NMModem *modem, void nm_modem_ip4_pre_commit (NMModem *modem, NMDevice *device, NMIP4Config *config); -gboolean nm_modem_get_secrets (NMModem *modem, - const char *setting_name, - gboolean request_new, - const char *hint); +void nm_modem_get_secrets (NMModem *modem, + const char *setting_name, + gboolean request_new, + const char *hint); void nm_modem_deactivate (NMModem *modem, NMDevice *device); diff --git a/src/devices/wwan/nm-wwan-factory.c b/src/devices/wwan/nm-wwan-factory.c index 49b0b0af..2fd9e0bd 100644 --- a/src/devices/wwan/nm-wwan-factory.c +++ b/src/devices/wwan/nm-wwan-factory.c @@ -29,12 +29,12 @@ #include "nm-setting-cdma.h" #include "nm-modem-manager.h" #include "nm-device-modem.h" -#include "nm-logging.h" +#include "nm-default.h" #include "nm-platform.h" static GType nm_wwan_factory_get_type (void); -static void device_factory_interface_init (NMDeviceFactory *factory_iface); +static void device_factory_interface_init (NMDeviceFactoryInterface *factory_iface); G_DEFINE_TYPE_EXTENDED (NMWwanFactory, nm_wwan_factory, G_TYPE_OBJECT, 0, G_IMPLEMENT_INTERFACE (NM_TYPE_DEVICE_FACTORY, device_factory_interface_init)) @@ -96,9 +96,14 @@ NM_DEVICE_FACTORY_DECLARE_TYPES ( ) static NMDevice * -new_link (NMDeviceFactory *factory, NMPlatformLink *plink, gboolean *out_ignore, GError **error) +create_device (NMDeviceFactory *factory, + const char *iface, + const NMPlatformLink *plink, + NMConnection *connection, + gboolean *out_ignore) { - g_warn_if_fail (plink->type == NM_LINK_TYPE_WWAN_ETHERNET); + g_return_val_if_fail (plink, NULL); + g_return_val_if_fail (plink->type == NM_LINK_TYPE_WWAN_ETHERNET, NULL); *out_ignore = TRUE; return NULL; } @@ -123,10 +128,10 @@ nm_wwan_factory_init (NMWwanFactory *self) } static void -device_factory_interface_init (NMDeviceFactory *factory_iface) +device_factory_interface_init (NMDeviceFactoryInterface *factory_iface) { factory_iface->get_supported_types = get_supported_types; - factory_iface->new_link = new_link; + factory_iface->create_device = create_device; factory_iface->start = start; } diff --git a/src/devices/wwan/nm-wwan-factory.h b/src/devices/wwan/nm-wwan-factory.h index c6c03f1f..78031e60 100644 --- a/src/devices/wwan/nm-wwan-factory.h +++ b/src/devices/wwan/nm-wwan-factory.h @@ -21,7 +21,7 @@ #ifndef __NETWORKMANAGER_WWAN_FACTORY_H__ #define __NETWORKMANAGER_WWAN_FACTORY_H__ -#include <glib-object.h> +#include "nm-default.h" #define NM_TYPE_WWAN_FACTORY (nm_wwan_factory_get_type ()) #define NM_WWAN_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_WWAN_FACTORY, NMWwanFactory)) |