diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/Makefile.am | 29 | ||||
| -rw-r--r-- | tools/Makefile.in | 224 | ||||
| -rwxr-xr-x | tools/check-exports.sh | 57 | ||||
| -rwxr-xr-x | tools/debug-helper.py | 61 | ||||
| -rw-r--r-- | tools/generate-settings-spec.c | 457 | ||||
| -rwxr-xr-x | tools/run-test-valgrind.sh | 26 | ||||
| -rwxr-xr-x | tools/test-networkmanager-service.py | 1170 | ||||
| -rwxr-xr-x | tools/test-sudo-wrapper.sh | 29 |
8 files changed, 1366 insertions, 687 deletions
diff --git a/tools/Makefile.am b/tools/Makefile.am index 2fea947b..f008956d 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -1,26 +1,7 @@ -GENERATE_SETTINGS_SPEC_SOURCE = generate-settings-spec.c - -AM_CPPFLAGS = \ - -I$(top_srcdir)/include \ - -I$(top_builddir)/include \ - -I$(top_srcdir)/libnm-util \ - -I$(top_builddir)/libnm-util \ - -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ - $(GLIB_CFLAGS) \ - $(DBUS_CFLAGS) - -noinst_PROGRAMS = \ - generate-settings-spec - -generate_settings_spec_SOURCES = \ - $(GENERATE_SETTINGS_SPEC_SOURCE) - -generate_settings_spec_LDADD = \ - $(top_builddir)/libnm-util/libnm-util.la \ - $(GLIB_LIBS) \ - $(DBUS_LIBS) - EXTRA_DIST = \ - doc-generator.xsl \ check-exports.sh \ - $(GENERATE_SETTINGS_SPEC_SOURCE) + debug-helper.py \ + doc-generator.xsl \ + run-test-valgrind.sh \ + test-networkmanager-service.py \ + test-sudo-wrapper.sh diff --git a/tools/Makefile.in b/tools/Makefile.in index e2102094..cab82382 100644 --- a/tools/Makefile.in +++ b/tools/Makefile.in @@ -13,7 +13,6 @@ # PARTICULAR PURPOSE. @SET_MAKE@ - VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ @@ -78,10 +77,8 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -noinst_PROGRAMS = generate-settings-spec$(EXEEXT) subdir = tools -DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ - $(top_srcdir)/build-aux/depcomp +DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/ax_lib_readline.m4 \ $(top_srcdir)/m4/compiler_warnings.m4 \ @@ -102,18 +99,6 @@ mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = -PROGRAMS = $(noinst_PROGRAMS) -am__objects_1 = generate-settings-spec.$(OBJEXT) -am_generate_settings_spec_OBJECTS = $(am__objects_1) -generate_settings_spec_OBJECTS = $(am_generate_settings_spec_OBJECTS) -am__DEPENDENCIES_1 = -generate_settings_spec_DEPENDENCIES = \ - $(top_builddir)/libnm-util/libnm-util.la $(am__DEPENDENCIES_1) \ - $(am__DEPENDENCIES_1) -AM_V_lt = $(am__v_lt_@AM_V@) -am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) -am__v_lt_0 = --silent -am__v_lt_1 = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false @@ -126,54 +111,14 @@ 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 = $(generate_settings_spec_SOURCES) -DIST_SOURCES = $(generate_settings_spec_SOURCES) +SOURCES = +DIST_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 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ALL_LINGUAS = @ALL_LINGUAS@ @@ -184,6 +129,8 @@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ +BLUEZ5_CFLAGS = @BLUEZ5_CFLAGS@ +BLUEZ5_LIBS = @BLUEZ5_LIBS@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ @@ -307,6 +254,7 @@ NEWT_CFLAGS = @NEWT_CFLAGS@ NEWT_LIBS = @NEWT_LIBS@ NM = @NM@ NMEDIT = @NMEDIT@ +NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT = @NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT@ NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ NM_MICRO_VERSION = @NM_MICRO_VERSION@ NM_MINOR_VERSION = @NM_MINOR_VERSION@ @@ -326,6 +274,7 @@ 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@ @@ -352,7 +301,7 @@ SYSTEMD_INHIBIT_LIBS = @SYSTEMD_INHIBIT_LIBS@ SYSTEMD_LOGIN_CFLAGS = @SYSTEMD_LOGIN_CFLAGS@ SYSTEMD_LOGIN_LIBS = @SYSTEMD_LOGIN_LIBS@ SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ -UDEV_BASE_DIR = @UDEV_BASE_DIR@ +UDEV_DIR = @UDEV_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ @@ -431,33 +380,17 @@ with_dhcpcd = @with_dhcpcd@ with_netconfig = @with_netconfig@ with_resolvconf = @with_resolvconf@ with_valgrind = @with_valgrind@ -GENERATE_SETTINGS_SPEC_SOURCE = generate-settings-spec.c -AM_CPPFLAGS = \ - -I$(top_srcdir)/include \ - -I$(top_builddir)/include \ - -I$(top_srcdir)/libnm-util \ - -I$(top_builddir)/libnm-util \ - -DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \ - $(GLIB_CFLAGS) \ - $(DBUS_CFLAGS) - -generate_settings_spec_SOURCES = \ - $(GENERATE_SETTINGS_SPEC_SOURCE) - -generate_settings_spec_LDADD = \ - $(top_builddir)/libnm-util/libnm-util.la \ - $(GLIB_LIBS) \ - $(DBUS_LIBS) - EXTRA_DIST = \ - doc-generator.xsl \ check-exports.sh \ - $(GENERATE_SETTINGS_SPEC_SOURCE) + debug-helper.py \ + doc-generator.xsl \ + run-test-valgrind.sh \ + test-networkmanager-service.py \ + test-sudo-wrapper.sh all: all-am .SUFFIXES: -.SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ @@ -489,105 +422,17 @@ $(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 - -generate-settings-spec$(EXEEXT): $(generate_settings_spec_OBJECTS) $(generate_settings_spec_DEPENDENCIES) $(EXTRA_generate_settings_spec_DEPENDENCIES) - @rm -f generate-settings-spec$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(generate_settings_spec_OBJECTS) $(generate_settings_spec_LDADD) $(LIBS) - -mostlyclean-compile: - -rm -f *.$(OBJEXT) - -distclean-compile: - -rm -f *.tab.c - -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generate-settings-spec.Po@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< - -.c.obj: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< - mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs +tags TAGS: -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 +ctags CTAGS: + +cscope cscopelist: -distclean-tags: - -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ @@ -621,7 +466,7 @@ distdir: $(DISTFILES) done check-am: all-am check: check-am -all-am: Makefile $(PROGRAMS) +all-am: Makefile installdirs: install: install-am install-exec: install-exec-am @@ -655,14 +500,11 @@ maintainer-clean-generic: @echo "it deletes files that may require special tools to rebuild." clean: clean-am -clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ - mostlyclean-am +clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am - -rm -rf ./$(DEPDIR) -rm -f Makefile -distclean-am: clean-am distclean-compile distclean-generic \ - distclean-tags +distclean-am: clean-am distclean-generic dvi: dvi-am @@ -705,14 +547,12 @@ 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 +mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am @@ -726,19 +566,17 @@ uninstall-am: .MAKE: install-am install-strip -.PHONY: CTAGS GTAGS TAGS all all-am check 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 \ +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + cscopelist-am ctags-am distclean distclean-generic \ + distclean-libtool 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-generic mostlyclean-libtool pdf pdf-am ps ps-am \ - tags tags-am uninstall uninstall-am + tags-am uninstall uninstall-am # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/tools/check-exports.sh b/tools/check-exports.sh index b5a9e952..dfd882c1 100755 --- a/tools/check-exports.sh +++ b/tools/check-exports.sh @@ -4,22 +4,53 @@ LC_ALL=C export LC_ALL stat=0 -so=$1 -def=$2 +so="$1" +def="$2" +PATTERN="_ANCHOR_" -# Have to prefix with a tab and suffix with a ';' to match .ver file format -get_syms='nm "$so" | grep "^[[:xdigit:]]\+ T " | sed "s/^[[:xdigit:]]\+ T //" | sed "s/^/\t/" | sed "s/$/;/"' +TMPFILE="$(mktemp .nm-check-exports.XXXXXX)" -echo $so: checking exported symbols against $def -{ - echo "{" - echo "global:" - eval $get_syms | sort -u - echo "local:" - echo " *;" - echo "};" -} | diff -u "$def" - >&2 || stat=1 +get_syms() { + nm "$1" | + sed -n 's/^[[:xdigit:]]\+ [DT] //p' | + sort +} +get_syms_from_def() { + # be strict and only parse entries that start with one \t and end with a ';' + sed -n 's/^\t\([_a-zA-Z0-9]\+\);$/\1/p' "$1" | + grep '^\*$' -v | + sort +} + +anchor() { + sed "s/.*/$PATTERN\0$PATTERN/" +} + +unanchor() { + sed "s/^$PATTERN\(.*\)$PATTERN\$/\1/" +} + + +get_syms "$so" | anchor > "$TMPFILE" +WRONG="$(get_syms_from_def "$def" | anchor | grep -F -f - "$TMPFILE" -v)" +RESULT=$? +if [ $RESULT -eq 0 ]; then + stat=1 + echo ">>library \"$so\" exports symbols that are not in linker script \"$def\":" + echo "$WRONG" | unanchor | nl +fi + +get_syms_from_def "$def" | anchor > "$TMPFILE" +WRONG="$(get_syms "$so" | anchor | grep -F -f - "$TMPFILE" -v)" +RESULT=$? +if [ $RESULT -eq 0 ]; then + stat=1 + echo ">>linker script \"$def\" contains symbols that are not exported by library \"$so\":" + echo "$WRONG" | unanchor | nl +fi + +rm -rf "$TMPFILE" exit $stat diff --git a/tools/debug-helper.py b/tools/debug-helper.py new file mode 100755 index 00000000..07338242 --- /dev/null +++ b/tools/debug-helper.py @@ -0,0 +1,61 @@ +#!/usr/bin/python +# Copyright (C) 2011 Mathieu Trudel-Lapierre <mathieu.tl@gmail.com> + +import dbus +import argparse + +bus = dbus.SystemBus() + +parser = argparse.ArgumentParser(description='Interface to easily control logging levels for NetworkManager, ModemManager, and wpasupplicant.') + +# NM options +parser.add_argument('--nm', dest='do_set_nm_logging', action='store', + help='modify log level for NetworkManager (debug, info, etc.)') +parser.add_argument('--domains', dest='log_domains', action='store', + default=[], nargs='+', + help='log "domains" to use with NetworkManager (HW, CORE, etc.)') + +# MM options +parser.add_argument('--mm', dest='do_set_mm_logging', action='store', + help='modify log level for ModemManager (debug, info, etc.)') + +# wpasupplicant options +parser.add_argument('--wpa', dest='do_set_wpa_logging', action='store', + help='modify log level for wpasupplicant (debug, msgdump, info, etc.)') + +args = parser.parse_args() + +if args.do_set_nm_logging: + #print args.log_domains + dom_msg = "" + if args.log_domains: + dom_msg = " for domains: " + ','.join(args.log_domains) + print "Setting NetworkManager log level to '" + args.do_set_nm_logging + "'" + dom_msg + + nm_bus = bus.get_object('org.freedesktop.NetworkManager', '/org/freedesktop/NetworkManager') + nm = dbus.Interface(nm_bus, dbus_interface='org.freedesktop.NetworkManager') + nm.SetLogging(args.do_set_nm_logging, ','.join(args.log_domains)) + +if args.do_set_mm_logging: + print "Setting ModemManager log level to '" + args.do_set_mm_logging + "'" + + mm_bus = bus.get_object('org.freedesktop.ModemManager', '/org/freedesktop/ModemManager') + mm = dbus.Interface(mm_bus, dbus_interface='org.freedesktop.ModemManager') + mm.SetLogging(args.do_set_mm_logging) + +if args.do_set_wpa_logging: + print "Setting wpa_supplicant log level to '" + args.do_set_wpa_logging + "'" + + if 'debug' in args.do_set_wpa_logging or 'msgdump' in args.do_set_wpa_logging: + print "Enabling timestamps for wpasupplicant debugging logs" + use_timestamps = dbus.Boolean(True, variant_level=1) + else: + print "Disabling timestamps for wpasupplicant debugging logs" + use_timestamps = dbus.Boolean(False, variant_level=1) + + wpa_bus = bus.get_object('fi.w1.wpa_supplicant1', '/fi/w1/wpa_supplicant1') + wpa_properties = dbus.Interface(wpa_bus, dbus_interface='org.freedesktop.DBus.Properties') + wpa_properties.Set('fi.w1.wpa_supplicant1', 'DebugTimestamp', use_timestamps) + wpa_properties.Set('fi.w1.wpa_supplicant1', 'DebugLevel', + dbus.String(args.do_set_wpa_logging, variant_level=1)) + diff --git a/tools/generate-settings-spec.c b/tools/generate-settings-spec.c deleted file mode 100644 index f53fdba1..00000000 --- a/tools/generate-settings-spec.c +++ /dev/null @@ -1,457 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* - * Dan Williams <dcbw@redhat.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2009 - 2013 Red Hat, Inc. - */ - -#include <stdio.h> -#include <errno.h> -#include <unistd.h> -#include <string.h> -#include <time.h> - -#include <glib.h> -#include <dbus/dbus-glib.h> -#include "config.h" - -#include <nm-setting.h> -#include <nm-setting-8021x.h> -#include <nm-setting-adsl.h> -#include <nm-setting-bluetooth.h> -#include <nm-setting-bond.h> -#include <nm-setting-bridge.h> -#include <nm-setting-bridge-port.h> -#include <nm-setting-cdma.h> -#include <nm-setting-connection.h> -#include <nm-setting-dcb.h> -#include <nm-setting-gsm.h> -#include <nm-setting-infiniband.h> -#include <nm-setting-ip4-config.h> -#include <nm-setting-ip6-config.h> -#include <nm-setting-olpc-mesh.h> -#include <nm-setting-ppp.h> -#include <nm-setting-pppoe.h> -#include <nm-setting-serial.h> -#include <nm-setting-team.h> -#include <nm-setting-team-port.h> -#include <nm-setting-vlan.h> -#include <nm-setting-vpn.h> -#include <nm-setting-wimax.h> -#include <nm-setting-wired.h> -#include <nm-setting-wireless.h> -#include <nm-setting-wireless-security.h> - -#include <nm-utils.h> - -typedef NMSetting* (*SettingNewFunc) (void); - -static SettingNewFunc funcs[] = { - nm_setting_802_1x_new, - nm_setting_adsl_new, - nm_setting_bluetooth_new, - nm_setting_bond_new, - nm_setting_bridge_new, - nm_setting_bridge_port_new, - nm_setting_cdma_new, - nm_setting_connection_new, - nm_setting_dcb_new, - nm_setting_gsm_new, - nm_setting_infiniband_new, - nm_setting_ip4_config_new, - nm_setting_ip6_config_new, - nm_setting_olpc_mesh_new, - nm_setting_ppp_new, - nm_setting_pppoe_new, - nm_setting_serial_new, - nm_setting_team_new, - nm_setting_team_port_new, - nm_setting_vlan_new, - nm_setting_vpn_new, - nm_setting_wimax_new, - nm_setting_wired_new, - nm_setting_wireless_new, - nm_setting_wireless_security_new, - NULL -}; - -typedef struct { - const char *gvalue_name; - const char *new_name; -} TypeNameElement; - -static TypeNameElement name_map[] = { - { "gchararray", "string" }, - { "GSList_gchararray_", "array of string" }, - { "GArray_guchar_", "byte array" }, - { "gboolean", "boolean" }, - { "guint64", "uint64" }, - { "gint", "int32" }, - { "guint", "uint32" }, - { "GArray_guint_", "array of uint32" }, - { "GPtrArray_GArray_guint__", "array of array of uint32" }, - { "GPtrArray_GArray_guchar__", "array of byte array" }, - { "GPtrArray_gchararray_", "array of string" }, - { "GHashTable_gchararray+gchararray_", "dict of (string::string)" }, - { "GPtrArray_GValueArray_GArray_guchar_+guint+GArray_guchar___", "array of (byte array, uint32, byte array)" }, - { "GPtrArray_GValueArray_GArray_guchar_+guint+GArray_guchar_+guint__", "array of (byte array, uint32, byte array, uint32)" }, - { NULL, NULL } -}; - -static void -write_one_setting (FILE *f, gboolean book, SettingNewFunc func) -{ - NMSetting *s; - GParamSpec **props, **iter; - guint num; - const char *row_fmt_str; - - s = func (); - - /* write out section header */ - (void) fprintf (f, - "<table>\n" - " <title>%s setting</title>\n" - " <tgroup cols=\"4\">\n" - " <thead>\n" - " <row>\n" - " <entry>Key Name</entry>\n" - " <entry>Value Type</entry>\n" - " <entry>Default Value</entry>\n" - " <entry>Value Description</entry>\n" - " </row>\n" - " </thead>\n" - " <tbody>\n", - nm_setting_get_name (s)); - - props = g_object_class_list_properties (G_OBJECT_GET_CLASS (G_OBJECT (s)), &num); - for (iter = props; iter && *iter; iter++) { - const char *key_name, *value_type, *value_desc; - char *default_value; - TypeNameElement *name_iter; - GValue value = G_VALUE_INIT; - char *flags_str = NULL; - - value_type = g_type_name (G_PARAM_SPEC_VALUE_TYPE (*iter)); - for (name_iter = &name_map[0]; name_iter && name_iter->gvalue_name; name_iter++) { - if (!strcmp (value_type, name_iter->gvalue_name)) { - value_type = name_iter->new_name; - break; - } - } - - key_name = g_param_spec_get_name (*iter); - value_desc = g_param_spec_get_blurb (*iter); - - g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (*iter)); - g_param_value_set_default (*iter, &value); - default_value = g_strdup_value_contents (&value); - if (default_value && !strcmp (default_value, "NULL")) { - g_free (default_value); - default_value = NULL; - } - - if (!strcmp (key_name, NM_SETTING_NAME)) { - g_free (default_value); - default_value = NULL; - g_object_get (G_OBJECT (s), NM_SETTING_NAME, &default_value, NULL); - } - - if (g_str_has_suffix (key_name, "-flags")) - flags_str = g_strdup_printf (" (see <xref linkend=\"secrets-flags\"/> for flag values)"); - - if (book) - row_fmt_str = - " <row>\n" - " <entry><screen>%s</screen></entry>\n" - " <entry><screen>%s</screen></entry>\n" - " <entry><screen>%s</screen></entry>\n" - " <entry>%s%s</entry>\n" - " </row>\n"; - else - row_fmt_str = - " <row>\n" - " <entry align=\"left\">%s</entry>\n" - " <entry align=\"left\">%s</entry>\n" - " <entry align=\"left\">%s</entry>\n" - " <entry>%s%s</entry>\n" - " </row>\n"; - - (void) fprintf (f, row_fmt_str, - key_name, - value_type, - default_value ? default_value : "", - value_desc, - flags_str ? flags_str : ""); - - g_free (flags_str); - g_free (default_value); - } - - (void) fprintf (f, - " </tbody>\n" - " </tgroup>\n" - "</table>\n"); - - g_object_unref (s); -} - -static void -writer_header_docbook_section (FILE *f) -{ - (void) fprintf (f, - "<?xml version=\"1.0\"?>\n" - "<!DOCTYPE section PUBLIC \"-//OASIS//DTD DocBook XML V4.3//EN\"\n" - " \"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd\" [\n" - "<!ENTITY %% local.common.attrib \"xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'\">" - "]>" - "<section>\n" - " <title>Configuration Settings</title>\n" - " <para>\n"); -} - -static void -writer_footer_docbook_section (FILE *f) -{ - (void) fprintf (f, - " </para>\n" - "</section>\n"); -} - -static void -writer_header_docbook_manpage (FILE *f) -{ - char time_str[64]; - time_t t; - - t = time (NULL); - strftime (time_str, sizeof (time_str), "%d %B %Y", localtime (&t)); - - (void) fprintf (f, - "<?xml version=\"1.0\"?>\n" - "<!DOCTYPE refentry PUBLIC \"-//OASIS//DTD DocBook XML V4.3//EN\"\n" - " \"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd\" [\n" - "<!ENTITY %% local.common.attrib \"xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'\">" - "]>" - "<refentry id=\"nm-settings\">\n" - " <refentryinfo>\n" - " <date>%s</date>\n" - " </refentryinfo>\n" - " <refmeta>\n" - " <refentrytitle>nm-settings</refentrytitle>\n" - " <manvolnum>5</manvolnum>\n" - " <refmiscinfo class=\"source\">NetworkManager</refmiscinfo>\n" - " <refmiscinfo class=\"manual\">Configuration</refmiscinfo>\n" - " <refmiscinfo class=\"version\">%s</refmiscinfo>\n" - " </refmeta>\n" - " <refnamediv>\n" - " <refname>nm-settings</refname>\n" - " <refpurpose>Description of settings and properties of NetworkManager connection profiles</refpurpose>\n" - " </refnamediv>\n" - " <refsect1>\n" - " <title>DESCRIPTION</title>\n" - " <para>\n" - " NetworkManager is based on a concept of connection profiles, sometimes referred to as\n" - " connections only. These connection profiles contain a network configuration. When\n" - " NetworkManager activates a connection profile on a network device the configuration will\n" - " be applied and an active network connection will be established. Users are free to create\n" - " as many connection profiles as they see fit. Thus they are flexible in having various network\n" - " configurations for different networking needs. The connection profiles are handled by\n" - " NetworkManager via <emphasis>settings service</emphasis> and are exported on D-Bus\n" - " (<emphasis>/org/freedesktop/NetworkManager/Settings/<num></emphasis> objects).\n" - " The conceptual objects can be described as follows:\n" - " <variablelist>\n" - " <varlistentry>\n" - " <term>Connection (profile)</term>\n" - " <listitem>\n" - " <para>\n" - " A specific, encapsulated, independent group of settings describing\n" - " all the configuration required to connect to a specific network.\n" - " It is referred to by a unique identifier called the UUID. A connection\n" - " is tied to a one specific device type, but not necessarily a specific\n" - " hardware device. It is composed of one or more <emphasis>Settings</emphasis>\n" - " objects.\n" - " </para>\n" - " </listitem>\n" - " </varlistentry>\n" - " </variablelist>\n" - " <variablelist>\n" - " <varlistentry>\n" - " <term>Setting</term>\n" - " <listitem>\n" - " <para>\n" - " A group of related key/value pairs describing a specific piece of a\n" - " <emphasis>Connection (profile)</emphasis>. Settings keys and allowed values are\n" - " described in the tables below. Keys are also reffered to as properties.\n" - " Developers can find the setting objects and their properties in the libnm-util\n" - " sources. Look for the <function>class_init</function> functions near the bottom of\n" - " each setting source file.\n" - " </para>\n" - " </listitem>\n" - " </varlistentry>\n" - " </variablelist>\n" - " <variablelist>\n" - " <para>\n" - " The settings and properties shown in tables below list all available connection\n" - " configuration options. However, note that not all settings are applicable to all\n" - " connection types. NetworkManager provides a command-line tool <emphasis>nmcli</emphasis>\n" - " that allows direct configuration of the settings and properties according to a connection\n" - " profile type. <emphasis>nmcli</emphasis> connection editor has also a built-in\n" - " <emphasis>describe</emphasis> command that can display description of particular settings\n" - " and properties of this page.\n" - " </para>\n" - " </variablelist>\n", - time_str, VERSION); -} - -static void -writer_footer_docbook_manpage (FILE *f) -{ - (void) fprintf (f, - " </para>\n" - " <refsect2 id=\"secrets-flags\">\n" - " <title>Secret flag types:</title>\n" - " <para>\n" - " Each secret property in a setting has an associated <emphasis>flags</emphasis> property\n" - " that describes how to handle that secret. The <emphasis>flags</emphasis> property is a bitfield\n" - " that contains zero or more of the following values logically OR-ed together.\n" - " </para>\n" - " <itemizedlist>\n" - " <listitem>\n" - " <para>0x0 (none) - the system is responsible for providing and storing this secret.</para>\n" - " </listitem>\n" - " <listitem>\n" - " <para>0x1 (agent-owned) - a user-session secret agent is responsible for providing and storing\n" - " this secret; when it is required, agents will be asked to provide it.</para>\n" - " </listitem>\n" - " <listitem>\n" - " <para>0x2 (not-saved) - this secret should not be saved but should be requested from the user\n" - " each time it is required. This flag should be used for One-Time-Pad secrets, PIN codes from hardware tokens,\n" - " or if the user simply does not want to save the secret.</para>\n" - " </listitem>\n" - " <listitem>\n" - " <para>0x4 (not-required) - in some situations it cannot be automatically determined that a secret\n" - " is required or not. This flag hints that the secret is not required and should not be requested from the user.</para>\n" - " </listitem>\n" - " </itemizedlist>\n" - " </refsect2>\n" - " </refsect1>\n" - " <refsect1>\n" - " <title>AUTHOR</title>\n" - " <para>\n" - " <author>\n" - " <firstname>NetworkManager developers</firstname>\n" - " </author>\n" - " </para>\n" - " </refsect1>\n" - " <refsect1>\n" - " <title>FILES</title>\n" - " <para>/etc/NetworkManager/system-connections</para>\n" - " <para>or distro plugin-specific location</para>\n" - " </refsect1>\n" - " <refsect1>\n" - " <title>SEE ALSO</title>\n" - " <para>https://live.gnome.org/NetworkManagerConfiguration</para>\n" - " <para>NetworkManager(8), nmcli(1), nmcli-examples(5), NetworkManager.conf(5)</para>\n" - " </refsect1>\n" - "</refentry>\n"); -} - -static void -usage (const char *str) -{ - fprintf (stderr, "Usage: %s <type> <output file> [<type> <output file>]\n" - "<type> := book|refentry\n", - str); - _exit (1); -} - -int -main (int argc, char *argv[]) -{ - GError *error = NULL; - FILE *f1 = NULL, *f2 = NULL; - SettingNewFunc *fptr; - const char *book_file = NULL, *refentry_file = NULL;; - - if (argc != 3 && argc != 5) - usage (argv[0]); - - if (strcmp (argv[1], "book") == 0) - book_file = argv[2]; - else if (strcmp (argv[1], "refentry") == 0) - refentry_file = argv[2]; - else - usage (argv[0]); - - if (argc == 5) { - if (strcmp (argv[3], "book") == 0 && !book_file) - book_file = argv[4]; - else if (strcmp (argv[3], "refentry") == 0 && !refentry_file) - refentry_file = argv[4]; - else - usage (argv[0]); - } - -#if !GLIB_CHECK_VERSION (2, 35, 0) - g_type_init (); -#endif - - if (!nm_utils_init (&error)) { - fprintf (stderr, "ERR: failed to initialize libnm-util: %s", error->message); - _exit (2); - } - - if (book_file) { - f1 = fopen (book_file, "w"); - if (!f1) { - fprintf (stderr, "ERR: could not create %s: %d\n", book_file, errno); - _exit (3); - } - } - if (refentry_file) { - f2 = fopen (refentry_file, "w"); - if (!f2) { - fprintf (stderr, "ERR: could not create %s: %d\n", refentry_file, errno); - _exit (3); - } - } - - /* Write out docbook 'book' xml - for html generation */ - if (f1) { - writer_header_docbook_section (f1); - for (fptr = funcs; fptr && *fptr; fptr++) - write_one_setting (f1, TRUE, *fptr); - writer_footer_docbook_section (f1); - } - - /* Write out docbook 'refentry' xml - for man page generation */ - if (f2) { - writer_header_docbook_manpage (f2); - for (fptr = funcs; fptr && *fptr; fptr++) - write_one_setting (f2, FALSE, *fptr); - writer_footer_docbook_manpage (f2); - } - - if (f1) - fclose (f1); - if (f2) - fclose (f2); - _exit (0); -} - diff --git a/tools/run-test-valgrind.sh b/tools/run-test-valgrind.sh new file mode 100755 index 00000000..506fff75 --- /dev/null +++ b/tools/run-test-valgrind.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +LIBTOOL="$1"; shift +VALGRIND="$1"; shift +SUPPRESSIONS="$1"; shift +TEST="$1"; shift + +LOGFILE="valgrind-`echo "$TEST" | tr -cd '[:alpha:]-'`.log" + +export G_SLICE=always-malloc +export G_DEBUG=gc-friendly +$LIBTOOL --mode=execute "$VALGRIND" \ + --quiet \ + --error-exitcode=1 \ + --leak-check=full \ + --gen-suppressions=all \ + --suppressions="$SUPPRESSIONS" \ + --log-file="$LOGFILE" \ + "$TEST" +RESULT=$? + +if [ $RESULT -ne 0 ]; then + echo "Don't forget to check the valgrind log at '`realpath $LOGFILE`'." >&2 +fi + +exit $RESULT diff --git a/tools/test-networkmanager-service.py b/tools/test-networkmanager-service.py new file mode 100755 index 00000000..56453389 --- /dev/null +++ b/tools/test-networkmanager-service.py @@ -0,0 +1,1170 @@ +#!/usr/bin/env python +# -*- Mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + +from __future__ import print_function + +from gi.repository import GLib +import sys +import dbus +import dbus.service +import dbus.mainloop.glib +import random + +mainloop = GLib.MainLoop() + +# NM State +NM_STATE_UNKNOWN = 0 +NM_STATE_ASLEEP = 10 +NM_STATE_DISCONNECTED = 20 +NM_STATE_DISCONNECTING = 30 +NM_STATE_CONNECTING = 40 +NM_STATE_CONNECTED_LOCAL = 50 +NM_STATE_CONNECTED_SITE = 60 +NM_STATE_CONNECTED_GLOBAL = 70 + +# Device state +NM_DEVICE_STATE_UNKNOWN = 0 +NM_DEVICE_STATE_UNMANAGED = 10 +NM_DEVICE_STATE_UNAVAILABLE = 20 +NM_DEVICE_STATE_DISCONNECTED = 30 +NM_DEVICE_STATE_PREPARE = 40 +NM_DEVICE_STATE_CONFIG = 50 +NM_DEVICE_STATE_NEED_AUTH = 60 +NM_DEVICE_STATE_IP_CONFIG = 70 +NM_DEVICE_STATE_IP_CHECK = 80 +NM_DEVICE_STATE_SECONDARIES = 90 +NM_DEVICE_STATE_ACTIVATED = 100 +NM_DEVICE_STATE_DEACTIVATING = 110 +NM_DEVICE_STATE_FAILED = 120 + +# Device type +NM_DEVICE_TYPE_UNKNOWN = 0 +NM_DEVICE_TYPE_ETHERNET = 1 +NM_DEVICE_TYPE_WIFI = 2 +NM_DEVICE_TYPE_UNUSED1 = 3 +NM_DEVICE_TYPE_UNUSED2 = 4 +NM_DEVICE_TYPE_BT = 5 +NM_DEVICE_TYPE_OLPC_MESH = 6 +NM_DEVICE_TYPE_WIMAX = 7 +NM_DEVICE_TYPE_MODEM = 8 +NM_DEVICE_TYPE_INFINIBAND = 9 +NM_DEVICE_TYPE_BOND = 10 +NM_DEVICE_TYPE_VLAN = 11 +NM_DEVICE_TYPE_ADSL = 12 +NM_DEVICE_TYPE_BRIDGE = 13 +NM_DEVICE_TYPE_GENERIC = 14 +NM_DEVICE_TYPE_TEAM = 15 + +# AC state +NM_ACTIVE_CONNECTION_STATE_UNKNOWN = 0 +NM_ACTIVE_CONNECTION_STATE_ACTIVATING = 1 +NM_ACTIVE_CONNECTION_STATE_ACTIVATED = 2 +NM_ACTIVE_CONNECTION_STATE_DEACTIVATING = 3 +NM_ACTIVE_CONNECTION_STATE_DEACTIVATED = 4 + +######################################################### +IFACE_DBUS = 'org.freedesktop.DBus' + +class UnknownInterfaceException(dbus.DBusException): + _dbus_error_name = IFACE_DBUS + '.UnknownInterface' + +class UnknownPropertyException(dbus.DBusException): + _dbus_error_name = IFACE_DBUS + '.UnknownProperty' + +def to_path_array(src): + array = dbus.Array([], signature=dbus.Signature('o')) + for o in src: + array.append(o.path) + return array + +def to_path(src): + if src: + return dbus.ObjectPath(src.path) + return dbus.ObjectPath("/") + +class ExportedObj(dbus.service.Object): + def __init__(self, bus, object_path): + dbus.service.Object.__init__(self, bus, object_path) + self._bus = bus + self.path = object_path + self.__dbus_ifaces = {} + + def add_dbus_interface(self, dbus_iface, get_props_func): + self.__dbus_ifaces[dbus_iface] = get_props_func + + def _get_dbus_properties(self, iface): + return self.__dbus_ifaces[iface]() + + @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, in_signature='s', out_signature='a{sv}') + def GetAll(self, iface): + if iface not in self.__dbus_ifaces.keys(): + raise UnknownInterfaceException() + return self._get_dbus_properties(iface) + + @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, in_signature='ss', out_signature='v') + def Get(self, iface, name): + if iface not in self.__dbus_ifaces.keys(): + raise UnknownInterfaceException() + props = self._get_dbus_properties(iface) + if not name in props.keys(): + raise UnknownPropertyException() + return props[name] + +################################################################### +IFACE_DEVICE = 'org.freedesktop.NetworkManager.Device' + +class NotSoftwareException(dbus.DBusException): + _dbus_error_name = IFACE_DEVICE + '.NotSoftware' + +PD_UDI = "Udi" +PD_IFACE = "Interface" +PD_DRIVER = "Driver" +PD_STATE = "State" +PD_ACTIVE_CONNECTION = "ActiveConnection" +PD_IP4_CONFIG = "Ip4Config" +PD_IP6_CONFIG = "Ip6Config" +PD_DHCP4_CONFIG = "Dhcp4Config" +PD_DHCP6_CONFIG = "Dhcp6Config" +PD_MANAGED = "Managed" +PD_AUTOCONNECT = "Autoconnect" +PD_DEVICE_TYPE = "DeviceType" +PD_AVAILABLE_CONNECTIONS = "AvailableConnections" + +class Device(ExportedObj): + counter = 1 + + def __init__(self, bus, iface, devtype): + object_path = "/org/freedesktop/NetworkManager/Devices/%d" % Device.counter + Device.counter = Device.counter + 1 + ExportedObj.__init__(self, bus, object_path) + self.add_dbus_interface(IFACE_DEVICE, self.__get_props) + + self.iface = iface + self.udi = "/sys/devices/virtual/%s" % iface + self.devtype = devtype + self.active_connection = None + self.state = NM_DEVICE_STATE_UNAVAILABLE + self.ip4_config = None + self.ip6_config = None + self.dhcp4_config = None + self.dhcp6_config = None + self.available_connections = [] + + # Properties interface + def __get_props(self): + props = {} + props[PD_UDI] = self.udi + props[PD_IFACE] = self.iface + props[PD_DRIVER] = "virtual" + props[PD_STATE] = dbus.UInt32(self.state) + props[PD_ACTIVE_CONNECTION] = to_path(self.active_connection) + props[PD_IP4_CONFIG] = to_path(self.ip4_config) + props[PD_IP6_CONFIG] = to_path(self.ip6_config) + props[PD_DHCP4_CONFIG] = to_path(self.dhcp4_config) + props[PD_DHCP6_CONFIG] = to_path(self.dhcp6_config) + props[PD_MANAGED] = True + props[PD_AUTOCONNECT] = True + props[PD_DEVICE_TYPE] = dbus.UInt32(self.devtype) + props[PD_AVAILABLE_CONNECTIONS] = to_path_array(self.available_connections) + return props + + # methods + @dbus.service.method(dbus_interface=IFACE_DEVICE, in_signature='', out_signature='') + def Disconnect(self): + pass + + @dbus.service.method(dbus_interface=IFACE_DEVICE, in_signature='', out_signature='') + def Delete(self): + # We don't currently support any software device types, so... + raise NotSoftwareException() + pass + + def __notify(self, propname): + props = self._get_dbus_properties(IFACE_DEVICE) + changed = { propname: props[propname] } + Device.PropertiesChanged(self, changed) + + @dbus.service.signal(IFACE_DEVICE, signature='a{sv}') + def PropertiesChanged(self, changed): + pass + + def set_active_connection(self, ac): + self.active_connection = ac + self.__notify(PD_ACTIVE_CONNECTION) + +################################################################### + +def random_mac(): + return '%02X:%02X:%02X:%02X:%02X:%02X' % ( + random.randint(0, 255), random.randint(0, 255), random.randint(0, 255), + random.randint(0, 255), random.randint(0, 255), random.randint(0, 255) + ) + +################################################################### +IFACE_WIRED = 'org.freedesktop.NetworkManager.Device.Wired' + +PE_HW_ADDRESS = "HwAddress" +PE_PERM_HW_ADDRESS = "PermHwAddress" +PE_SPEED = "Speed" +PE_CARRIER = "Carrier" + +class WiredDevice(Device): + def __init__(self, bus, iface): + Device.__init__(self, bus, iface, NM_DEVICE_TYPE_ETHERNET) + self.add_dbus_interface(IFACE_WIRED, self.__get_props) + + self.mac = random_mac() + self.carrier = False + + # Properties interface + def __get_props(self): + props = {} + props[PE_HW_ADDRESS] = self.mac + props[PE_PERM_HW_ADDRESS] = self.mac + props[PE_SPEED] = dbus.UInt32(100) + props[PE_CARRIER] = self.carrier + return props + + def __notify(self, propname): + props = self._get_dbus_properties(IFACE_WIRED) + changed = { propname: props[propname] } + WiredDevice.PropertiesChanged(self, changed) + + @dbus.service.signal(IFACE_WIRED, signature='a{sv}') + def PropertiesChanged(self, changed): + pass + +################################################################### +IFACE_VLAN = 'org.freedesktop.NetworkManager.Device.Vlan' + +PV_HW_ADDRESS = "HwAddress" +PV_CARRIER = "Carrier" +PV_VLAN_ID = "VlanId" + +class VlanDevice(Device): + def __init__(self, bus, iface): + Device.__init__(self, bus, iface, NM_DEVICE_TYPE_VLAN) + self.add_dbus_interface(IFACE_VLAN, self.__get_props) + + self.mac = random_mac() + self.carrier = False + self.vlan_id = 1 + + # Properties interface + def __get_props(self): + props = {} + props[PV_HW_ADDRESS] = self.mac + props[PV_CARRIER] = self.carrier + props[PV_VLAN_ID] = self.vlan_id + return props + + @dbus.service.signal(IFACE_VLAN, signature='a{sv}') + def PropertiesChanged(self, changed): + pass + +################################################################### +IFACE_WIFI_AP = 'org.freedesktop.NetworkManager.AccessPoint' + +PP_FLAGS = "Flags" +PP_WPA_FLAGS = "WpaFlags" +PP_RSN_FLAGS = "RsnFlags" +PP_SSID = "Ssid" +PP_FREQUENCY = "Frequency" +PP_HW_ADDRESS = "HwAddress" +PP_MODE = "Mode" +PP_MAX_BITRATE = "MaxBitrate" +PP_STRENGTH = "Strength" + +class WifiAp(ExportedObj): + counter = 0 + + def __init__(self, bus, ssid, mac, flags, wpaf, rsnf, freq): + path = "/org/freedesktop/NetworkManager/AccessPoint/%d" % WifiAp.counter + WifiAp.counter = WifiAp.counter + 1 + ExportedObj.__init__(self, bus, path) + self.add_dbus_interface(IFACE_WIFI_AP, self.__get_props) + + self.ssid = ssid + if mac: + self.bssid = mac + else: + self.bssid = random_mac() + self.flags = flags + self.wpaf = wpaf + self.rsnf = rsnf + self.freq = freq + self.strength = random.randint(0, 100) + self.strength_id = GLib.timeout_add_seconds(10, self.strength_cb, None) + + def __del__(self): + if self.strength_id > 0: + GLib.source_remove(self.strength_id) + self.strength_id = 0 + + def strength_cb(self, ignored): + self.strength = random.randint(0, 100) + self.__notify(PP_STRENGTH) + return True + + # Properties interface + def __get_props(self): + props = {} + props[PP_FLAGS] = dbus.UInt32(self.flags) + props[PP_WPA_FLAGS] = dbus.UInt32(self.wpaf) + props[PP_RSN_FLAGS] = dbus.UInt32(self.rsnf) + props[PP_SSID] = dbus.ByteArray(self.ssid) + props[PP_FREQUENCY] = dbus.UInt32(self.freq) + props[PP_HW_ADDRESS] = self.bssid + props[PP_MODE] = dbus.UInt32(2) # NM_802_11_MODE_INFRA + props[PP_MAX_BITRATE] = dbus.UInt32(54000) + props[PP_STRENGTH] = dbus.Byte(self.strength) + return props + + def __notify(self, propname): + props = self._get_dbus_properties(IFACE_WIFI_AP) + changed = { propname: props[propname] } + WifiAp.PropertiesChanged(self, changed) + + @dbus.service.signal(IFACE_WIFI_AP, signature='a{sv}') + def PropertiesChanged(self, changed): + pass + +################################################################### +IFACE_WIFI = 'org.freedesktop.NetworkManager.Device.Wireless' + +class ApNotFoundException(dbus.DBusException): + _dbus_error_name = IFACE_WIFI + '.AccessPointNotFound' + +PW_HW_ADDRESS = "HwAddress" +PW_PERM_HW_ADDRESS = "PermHwAddress" +PW_MODE = "Mode" +PW_BITRATE = "Bitrate" +PW_ACCESS_POINTS = "AccessPoints" +PW_ACTIVE_ACCESS_POINT = "ActiveAccessPoint" +PW_WIRELESS_CAPABILITIES = "WirelessCapabilities" + +class WifiDevice(Device): + def __init__(self, bus, iface): + Device.__init__(self, bus, iface, NM_DEVICE_TYPE_WIFI) + self.add_dbus_interface(IFACE_WIFI, self.__get_props) + + self.mac = random_mac() + self.aps = [] + self.active_ap = None + + # methods + @dbus.service.method(dbus_interface=IFACE_WIFI, in_signature='', out_signature='ao') + def GetAccessPoints(self): + # only include non-hidden APs + array = [] + for a in self.aps: + if a.ssid(): + array.append(a) + return to_path_array(array) + + @dbus.service.method(dbus_interface=IFACE_WIFI, in_signature='', out_signature='ao') + def GetAllAccessPoints(self): + # include all APs including hidden ones + return to_path_array(self.aps) + + @dbus.service.method(dbus_interface=IFACE_WIFI, in_signature='a{sv}', out_signature='') + def RequestScan(self, props): + pass + + @dbus.service.signal(IFACE_WIFI, signature='o') + def AccessPointAdded(self, ap_path): + pass + + def add_ap(self, ap): + self.aps.append(ap) + self.__notify(PW_ACCESS_POINTS) + self.AccessPointAdded(to_path(ap)) + + @dbus.service.signal(IFACE_WIFI, signature='o') + def AccessPointRemoved(self, ap_path): + pass + + def remove_ap(self, ap): + self.aps.remove(ap) + self.__notify(PW_ACCESS_POINTS) + self.AccessPointRemoved(to_path(ap)) + + # Properties interface + def __get_props(self): + props = {} + props[PW_HW_ADDRESS] = self.mac + props[PW_PERM_HW_ADDRESS] = self.mac + props[PW_MODE] = dbus.UInt32(3) # NM_802_11_MODE_INFRA + props[PW_BITRATE] = dbus.UInt32(21000) + props[PW_WIRELESS_CAPABILITIES] = dbus.UInt32(0xFF) + props[PW_ACCESS_POINTS] = to_path_array(self.aps) + props[PW_ACTIVE_ACCESS_POINT] = to_path(self.active_ap) + return props + + def __notify(self, propname): + props = self._get_dbus_properties(IFACE_WIFI) + changed = { propname: props[propname] } + WifiDevice.PropertiesChanged(self, changed) + + @dbus.service.signal(IFACE_WIFI, signature='a{sv}') + def PropertiesChanged(self, changed): + pass + + # test functions + def add_test_ap(self, ssid, mac): + ap = WifiAp(self._bus, ssid, mac, 0x1, 0x1cc, 0x1cc, 2412) + self.add_ap(ap) + return ap.path + + def remove_ap_by_path(self, path): + for ap in self.aps: + if ap.path == path: + self.remove_ap(ap) + return + raise ApNotFoundException("AP %s not found" % path) + + +################################################################### +IFACE_WIMAX_NSP = 'org.freedesktop.NetworkManager.WiMax.Nsp' + +PN_NAME = "Name" +PN_SIGNAL_QUALITY = "SignalQuality" +PN_NETWORK_TYPE = "NetworkType" + +class WimaxNsp(ExportedObj): + counter = 0 + + def __init__(self, bus, name): + path = "/org/freedesktop/NetworkManager/Nsp/%d" % WimaxNsp.counter + WimaxNsp.counter = WimaxNsp.counter + 1 + ExportedObj.__init__(self, bus, path) + self.add_dbus_interface(IFACE_WIMAX_NSP, self.__get_props) + + self.name = name + self.strength = random.randint(0, 100) + self.strength_id = GLib.timeout_add_seconds(10, self.strength_cb, None) + + def __del__(self): + if self.strength_id > 0: + GLib.source_remove(self.strength_id) + self.strength_id = 0 + + def strength_cb(self, ignored): + self.strength = random.randint(0, 100) + self.__notify(PN_SIGNAL_QUALITY) + return True + + # Properties interface + def __get_props(self): + props = {} + props[PN_NAME] = self.name + props[PN_SIGNAL_QUALITY] = dbus.UInt32(self.strength) + props[PN_NETWORK_TYPE] = dbus.UInt32(0x1) # NM_WIMAX_NSP_NETWORK_TYPE_HOME + return props + + def __notify(self, propname): + props = self._get_dbus_properties(IFACE_WIMAX_NSP) + changed = { propname: props[propname] } + WimaxNsp.PropertiesChanged(self, changed) + + @dbus.service.signal(IFACE_WIMAX_NSP, signature='a{sv}') + def PropertiesChanged(self, changed): + pass + +################################################################### +IFACE_WIMAX = 'org.freedesktop.NetworkManager.Device.WiMax' + +class NspNotFoundException(dbus.DBusException): + _dbus_error_name = IFACE_WIMAX + '.NspNotFound' + +PX_NSPS = "Nsps" +PX_HW_ADDRESS = "HwAddress" +PX_CENTER_FREQUENCY = "CenterFrequency" +PX_RSSI = "Rssi" +PX_CINR = "Cinr" +PX_TX_POWER = "TxPower" +PX_BSID = "Bsid" +PX_ACTIVE_NSP = "ActiveNsp" + +class WimaxDevice(Device): + def __init__(self, bus, iface): + Device.__init__(self, bus, iface, NM_DEVICE_TYPE_WIMAX) + self.add_dbus_interface(IFACE_WIMAX, self.__get_props) + + self.mac = random_mac() + self.bsid = random_mac() + self.nsps = [] + self.active_nsp = None + + # methods + @dbus.service.method(dbus_interface=IFACE_WIMAX, in_signature='', out_signature='ao') + def GetNspList(self): + # include all APs including hidden ones + return to_path_array(self.nsps) + + @dbus.service.signal(IFACE_WIMAX, signature='o') + def NspAdded(self, nsp_path): + pass + + def add_nsp(self, nsp): + self.nsps.append(nsp) + self.__notify(PX_NSPS) + self.NspAdded(to_path(nsp)) + + @dbus.service.signal(IFACE_WIMAX, signature='o') + def NspRemoved(self, nsp_path): + pass + + def remove_nsp(self, nsp): + self.nsps.remove(nsp) + self.__notify(PX_NSPS) + self.NspRemoved(to_path(nsp)) + + # Properties interface + def __get_props(self): + props = {} + props[PX_HW_ADDRESS] = self.mac + props[PX_CENTER_FREQUENCY] = dbus.UInt32(2525) + props[PX_RSSI] = dbus.Int32(-48) + props[PX_CINR] = dbus.Int32(24) + props[PX_TX_POWER] = dbus.Int32(9) + props[PX_BSID] = self.bsid + props[PX_NSPS] = to_path_array(self.nsps) + props[PX_ACTIVE_NSP] = to_path(self.active_nsp) + return props + + def __notify(self, propname): + props = self._get_dbus_properties(IFACE_WIMAX) + changed = { propname: props[propname] } + WimaxDevice.PropertiesChanged(self, changed) + + @dbus.service.signal(IFACE_WIMAX, signature='a{sv}') + def PropertiesChanged(self, changed): + pass + + # test functions + def add_test_nsp(self, name): + nsp = WimaxNsp(self._bus, name) + self.add_nsp(nsp) + return nsp.path + + def remove_nsp_by_path(self, path): + for nsp in self.nsps: + if nsp.path == path: + self.remove_nsp(nsp) + return + raise NspNotFoundException("NSP %s not found" % path) + +################################################################### +IFACE_ACTIVE_CONNECTION = 'org.freedesktop.NetworkManager.Connection.Active' + +PAC_CONNECTION = "Connection" +PAC_SPECIFIC_OBJECT = "SpecificObject" +PAC_ID = "Id" +PAC_UUID = "Uuid" +PAC_TYPE = "Type" +PAC_DEVICES = "Devices" +PAC_STATE = "State" +PAC_DEFAULT = "Default" +PAC_IP4CONFIG = "Ip4Config" +PAC_DHCP4CONFIG = "Dhcp4Config" +PAC_DEFAULT6 = "Default6" +PAC_IP6CONFIG = "Ip6Config" +PAC_DHCP6CONFIG = "Dhcp6Config" +PAC_VPN = "Vpn" +PAC_MASTER = "Master" + +class ActiveConnection(ExportedObj): + counter = 1 + + def __init__(self, bus, device, connection, specific_object): + object_path = "/org/freedesktop/NetworkManager/ActiveConnection/%d" % ActiveConnection.counter + ActiveConnection.counter = ActiveConnection.counter + 1 + ExportedObj.__init__(self, bus, object_path) + self.add_dbus_interface(IFACE_ACTIVE_CONNECTION, self.__get_props) + + self.device = device + self.conn = connection + self.specific_object = specific_object + self.state = NM_ACTIVE_CONNECTION_STATE_UNKNOWN + self.default = False + self.ip4config = None + self.dhcp4config = None + self.default6 = False + self.ip6config = None + self.dhcp6config = None + self.vpn = False + self.master = None + + # Properties interface + def __get_props(self): + props = {} + props[PAC_CONNECTION] = to_path(self.conn) + props[PAC_SPECIFIC_OBJECT] = to_path(self.specific_object) + conn_settings = self.conn.GetSettings() + s_con = conn_settings['connection'] + props[PAC_ID] = s_con['id'] + props[PAC_UUID] = s_con['uuid'] + props[PAC_TYPE] = s_con['type'] + props[PAC_DEVICES] = to_path_array([self.device]) + props[PAC_STATE] = dbus.UInt32(self.state) + props[PAC_DEFAULT] = self.default + props[PAC_IP4CONFIG] = to_path(self.ip4config) + props[PAC_DHCP4CONFIG] = to_path(self.dhcp4config) + props[PAC_DEFAULT6] = self.default6 + props[PAC_IP6CONFIG] = to_path(self.ip6config) + props[PAC_DHCP6CONFIG] = to_path(self.dhcp6config) + props[PAC_VPN] = self.vpn + props[PAC_MASTER] = to_path(self.master) + return props + + @dbus.service.signal(IFACE_ACTIVE_CONNECTION, signature='a{sv}') + def PropertiesChanged(self, changed): + pass + +################################################################### +IFACE_TEST = 'org.freedesktop.NetworkManager.LibnmGlibTest' +IFACE_NM = 'org.freedesktop.NetworkManager' + +class PermissionDeniedException(dbus.DBusException): + _dbus_error_name = IFACE_NM + '.PermissionDenied' + +class UnknownDeviceException(dbus.DBusException): + _dbus_error_name = IFACE_NM + '.UnknownDevice' + +class UnknownConnectionException(dbus.DBusException): + _dbus_error_name = IFACE_NM + '.UnknownConnection' + +PM_DEVICES = 'Devices' +PM_NETWORKING_ENABLED = 'NetworkingEnabled' +PM_WWAN_ENABLED = 'WwanEnabled' +PM_WWAN_HARDWARE_ENABLED = 'WwanHardwareEnabled' +PM_WIRELESS_ENABLED = 'WirelessEnabled' +PM_WIRELESS_HARDWARE_ENABLED = 'WirelessHardwareEnabled' +PM_WIMAX_ENABLED = 'WimaxEnabled' +PM_WIMAX_HARDWARE_ENABLED = 'WimaxHardwareEnabled' +PM_ACTIVE_CONNECTIONS = 'ActiveConnections' +PM_PRIMARY_CONNECTION = 'PrimaryConnection' +PM_ACTIVATING_CONNECTION = 'ActivatingConnection' +PM_STARTUP = 'Startup' +PM_STATE = 'State' +PM_VERSION = 'Version' +PM_CONNECTIVITY = 'Connectivity' + +def set_device_ac_cb(device, ac): + device.set_active_connection(ac) + +class NetworkManager(ExportedObj): + def __init__(self, bus, object_path): + ExportedObj.__init__(self, bus, object_path) + self.add_dbus_interface(IFACE_NM, self.__get_props) + + self._bus = bus; + self.devices = [] + self.active_connections = [] + self.primary_connection = None + self.activating_connection = None + self.state = NM_STATE_DISCONNECTED + self.connectivity = 1 + + @dbus.service.signal(IFACE_NM, signature='u') + def StateChanged(self, new_state): + pass + + def set_state(self, new_state): + self.state = new_state + self.__notify(PM_STATE) + self.StateChanged(dbus.UInt32(self.state)) + + @dbus.service.method(dbus_interface=IFACE_NM, in_signature='', out_signature='ao') + def GetDevices(self): + return self._get_dbus_properties(IFACE_NM)[PM_DEVICES] + + @dbus.service.method(dbus_interface=IFACE_NM, in_signature='s', out_signature='o') + def GetDeviceByIpIface(self, ip_iface): + for d in self.devices: + # ignore iface/ip_iface distinction for now + if d.iface == ip_iface: + return d.path + raise UnknownDeviceException("No device found for the requested iface.") + + @dbus.service.method(dbus_interface=IFACE_NM, in_signature='ooo', out_signature='o') + def ActivateConnection(self, conpath, devpath, specific_object): + try: + connection = settings.get_connection(conpath) + except Exception as e: + raise UnknownConnectionException("Connection not found") + + hash = connection.GetSettings() + s_con = hash['connection'] + + device = None + for d in self.devices: + if d.path == devpath: + device = d + break + if not device and s_con['type'] == 'vlan': + ifname = s_con['interface-name'] + device = VlanDevice(self._bus, ifname) + self.add_device(device) + if not device: + raise UnknownDeviceException("No device found for the requested iface.") + + # See if we need secrets. For the moment, we only support WPA + if '802-11-wireless-security' in hash: + s_wsec = hash['802-11-wireless-security'] + if (s_wsec['key-mgmt'] == 'wpa-psk' and 'psk' not in s_wsec): + secrets = agent_manager.get_secrets(hash, conpath, '802-11-wireless-security') + if secrets is None: + raise NoSecretsException("No secret agent available") + if '802-11-wireless-security' not in secrets: + raise NoSecretsException("No secrets provided") + s_wsec = secrets['802-11-wireless-security'] + if 'psk' not in s_wsec: + raise NoSecretsException("No secrets provided") + + ac = ActiveConnection(self._bus, device, connection, None) + self.active_connections.append(ac) + self.__notify(PM_ACTIVE_CONNECTIONS) + + if s_con['id'] == 'object-creation-failed-test': + self.active_connections.remove(ac) + ac.remove_from_connection() + else: + GLib.timeout_add(50, set_device_ac_cb, device, ac) + + return to_path(ac) + + @dbus.service.method(dbus_interface=IFACE_NM, in_signature='a{sa{sv}}oo', out_signature='oo') + def AddAndActivateConnection(self, connection, devpath, specific_object): + device = None + for d in self.devices: + if d.path == devpath: + device = d + break + if not device: + raise UnknownDeviceException("No device found for the requested iface.") + + conpath = settings.AddConnection(connection) + return (conpath, self.ActivateConnection(conpath, devpath, specific_object)) + + @dbus.service.method(dbus_interface=IFACE_NM, in_signature='o', out_signature='') + def DeactivateConnection(self, active_connection): + pass + + @dbus.service.method(dbus_interface=IFACE_NM, in_signature='b', out_signature='') + def Sleep(self, do_sleep): + if do_sleep: + self.state = NM_STATE_ASLEEP + else: + self.state = NM_STATE_DISCONNECTED + self.__notify(PM_STATE) + + @dbus.service.method(dbus_interface=IFACE_NM, in_signature='b', out_signature='') + def Enable(self, do_enable): + pass + + @dbus.service.method(dbus_interface=IFACE_NM, in_signature='', out_signature='a{ss}') + def GetPermissions(self): + return { "org.freedesktop.NetworkManager.enable-disable-network": "yes", + "org.freedesktop.NetworkManager.sleep-wake": "no", + "org.freedesktop.NetworkManager.enable-disable-wifi": "yes", + "org.freedesktop.NetworkManager.enable-disable-wwan": "yes", + "org.freedesktop.NetworkManager.enable-disable-wimax": "yes", + "org.freedesktop.NetworkManager.network-control": "yes", + "org.freedesktop.NetworkManager.wifi.share.protected": "yes", + "org.freedesktop.NetworkManager.wifi.share.open": "yes", + "org.freedesktop.NetworkManager.settings.modify.own": "yes", + "org.freedesktop.NetworkManager.settings.modify.system": "yes", + "org.freedesktop.NetworkManager.settings.modify.hostname": "yes" } + + @dbus.service.method(dbus_interface=IFACE_NM, in_signature='ss', out_signature='') + def SetLogging(self, level, domains): + pass + + @dbus.service.method(dbus_interface=IFACE_NM, in_signature='', out_signature='ss') + def GetLogging(self): + return ("info", "HW,RFKILL,CORE,DEVICE,WIFI,ETHER") + + @dbus.service.method(dbus_interface=IFACE_NM, in_signature='', out_signature='u') + def CheckConnectivity(self): + raise PermissionDeniedException("You fail") + + @dbus.service.signal(IFACE_NM, signature='o') + def DeviceAdded(self, devpath): + pass + + def add_device(self, device): + self.devices.append(device) + self.__notify(PM_DEVICES) + self.DeviceAdded(to_path(device)) + + @dbus.service.signal(IFACE_NM, signature='o') + def DeviceRemoved(self, devpath): + pass + + def remove_device(self, device): + self.devices.remove(device) + self.__notify(PM_DEVICES) + self.DeviceRemoved(to_path(device)) + + ################# D-Bus Properties interface + def __get_props(self): + props = {} + props[PM_DEVICES] = to_path_array(self.devices) + props[PM_NETWORKING_ENABLED] = True + props[PM_WWAN_ENABLED] = True + props[PM_WWAN_HARDWARE_ENABLED] = True + props[PM_WIRELESS_ENABLED] = True + props[PM_WIRELESS_HARDWARE_ENABLED] = True + props[PM_WIMAX_ENABLED] = True + props[PM_WIMAX_HARDWARE_ENABLED] = True + props[PM_ACTIVE_CONNECTIONS] = to_path_array(self.active_connections) + props[PM_PRIMARY_CONNECTION] = to_path(self.primary_connection) + props[PM_ACTIVATING_CONNECTION] = to_path(self.activating_connection) + props[PM_STARTUP] = False + props[PM_STATE] = dbus.UInt32(self.state) + props[PM_VERSION] = "0.9.9.0" + props[PM_CONNECTIVITY] = dbus.UInt32(self.connectivity) + return props + + def __notify(self, propname): + props = self._get_dbus_properties(IFACE_NM) + changed = { propname: props[propname] } + NetworkManager.PropertiesChanged(self, changed) + + @dbus.service.signal(IFACE_NM, signature='a{sv}') + def PropertiesChanged(self, changed): + pass + + ################# Testing methods + @dbus.service.method(IFACE_TEST, in_signature='', out_signature='') + def Quit(self): + mainloop.quit() + + @dbus.service.method(IFACE_TEST, in_signature='s', out_signature='o') + def AddWiredDevice(self, ifname): + for d in self.devices: + if d.iface == ifname: + raise PermissionDeniedException("Device already added") + dev = WiredDevice(self._bus, ifname) + self.add_device(dev) + return dbus.ObjectPath(dev.path) + + @dbus.service.method(IFACE_TEST, in_signature='s', out_signature='o') + def AddWifiDevice(self, ifname): + for d in self.devices: + if d.iface == ifname: + raise PermissionDeniedException("Device already added") + dev = WifiDevice(self._bus, ifname) + self.add_device(dev) + return dbus.ObjectPath(dev.path) + + @dbus.service.method(IFACE_TEST, in_signature='s', out_signature='o') + def AddWimaxDevice(self, ifname): + for d in self.devices: + if d.iface == ifname: + raise PermissionDeniedException("Device already added") + dev = WimaxDevice(self._bus, ifname) + self.add_device(dev) + return dbus.ObjectPath(dev.path) + + @dbus.service.method(IFACE_TEST, in_signature='o', out_signature='') + def RemoveDevice(self, path): + for d in self.devices: + if d.path == path: + self.remove_device(d) + return + raise UnknownDeviceException("Device not found") + + @dbus.service.method(IFACE_TEST, in_signature='sss', out_signature='o') + def AddWifiAp(self, ifname, ssid, mac): + for d in self.devices: + if d.iface == ifname: + return dbus.ObjectPath(d.add_test_ap(ssid, mac)) + raise UnknownDeviceException("Device not found") + + @dbus.service.method(IFACE_TEST, in_signature='so', out_signature='') + def RemoveWifiAp(self, ifname, ap_path): + for d in self.devices: + if d.iface == ifname: + d.remove_ap_by_path(ap_path) + return + raise UnknownDeviceException("Device not found") + + @dbus.service.method(IFACE_TEST, in_signature='ss', out_signature='o') + def AddWimaxNsp(self, ifname, name): + for d in self.devices: + if d.iface == ifname: + return dbus.ObjectPath(d.add_test_nsp(name)) + raise UnknownDeviceException("Device not found") + + @dbus.service.method(IFACE_TEST, in_signature='so', out_signature='') + def RemoveWimaxNsp(self, ifname, nsp_path): + for d in self.devices: + if d.iface == ifname: + d.remove_nsp_by_path(nsp_path) + return + raise UnknownDeviceException("Device not found") + + @dbus.service.method(IFACE_TEST, in_signature='', out_signature='') + def AutoRemoveNextConnection(self): + settings.auto_remove_next_connection() + +################################################################### +IFACE_CONNECTION = 'org.freedesktop.NetworkManager.Settings.Connection' + +class InvalidPropertyException(dbus.DBusException): + _dbus_error_name = IFACE_CONNECTION + '.InvalidProperty' + +class MissingPropertyException(dbus.DBusException): + _dbus_error_name = IFACE_CONNECTION + '.MissingProperty' + +class InvalidSettingException(dbus.DBusException): + _dbus_error_name = IFACE_CONNECTION + '.InvalidSetting' + +class MissingSettingException(dbus.DBusException): + _dbus_error_name = IFACE_CONNECTION + '.MissingSetting' + +class Connection(dbus.service.Object): + def __init__(self, bus, object_path, settings, remove_func): + dbus.service.Object.__init__(self, bus, object_path) + + if 'connection' not in settings: + raise MissingSettingException('connection: setting is required') + s_con = settings['connection'] + if 'type' not in s_con: + raise MissingPropertyException('connection.type: property is required') + type = s_con['type'] + if not type in ['802-3-ethernet', '802-11-wireless', 'vlan', 'wimax']: + raise InvalidPropertyException('connection.type: unsupported connection type') + + self.path = object_path + self.settings = settings + self.remove_func = remove_func + self.visible = True + self.props = {} + self.props['Unsaved'] = False + + # Properties interface + @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, in_signature='s', out_signature='a{sv}') + def GetAll(self, iface): + if iface != IFACE_CONNECTION: + raise UnknownInterfaceException() + return self.props + + @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, in_signature='ss', out_signature='v') + def Get(self, iface, name): + if iface != IFACE_CONNECTION: + raise UnknownInterfaceException() + if not name in self.props.keys(): + raise UnknownPropertyException() + return self.props[name] + + # Connection methods + @dbus.service.method(dbus_interface=IFACE_CONNECTION, in_signature='', out_signature='a{sa{sv}}') + def GetSettings(self): + if not self.visible: + raise PermissionDeniedException() + return self.settings + + @dbus.service.method(dbus_interface=IFACE_CONNECTION, in_signature='b', out_signature='') + def SetVisible(self, vis): + self.visible = vis + self.Updated() + + @dbus.service.method(dbus_interface=IFACE_CONNECTION, in_signature='', out_signature='') + def Delete(self): + self.remove_func(self) + self.Removed() + self.remove_from_connection() + + @dbus.service.signal(IFACE_CONNECTION, signature='') + def Removed(self): + pass + + @dbus.service.signal(IFACE_CONNECTION, signature='') + def Updated(self): + pass + +################################################################### +IFACE_SETTINGS = 'org.freedesktop.NetworkManager.Settings' + +class InvalidHostnameException(dbus.DBusException): + _dbus_error_name = IFACE_SETTINGS + '.InvalidHostname' + +class Settings(dbus.service.Object): + def __init__(self, bus, object_path): + dbus.service.Object.__init__(self, bus, object_path) + self.connections = {} + self.bus = bus + self.counter = 1 + self.remove_next_connection = False + self.props = {} + self.props['Hostname'] = "foobar.baz" + self.props['CanModify'] = True + self.props['Connections'] = dbus.Array([], 'o') + + def auto_remove_next_connection(self): + self.remove_next_connection = True; + + def get_connection(self, path): + return self.connections[path] + + @dbus.service.method(dbus_interface=IFACE_SETTINGS, in_signature='', out_signature='ao') + def ListConnections(self): + return self.connections.keys() + + @dbus.service.method(dbus_interface=IFACE_SETTINGS, in_signature='a{sa{sv}}', out_signature='o') + def AddConnection(self, settings): + path = "/org/freedesktop/NetworkManager/Settings/Connection/{0}".format(self.counter) + self.counter = self.counter + 1 + self.connections[path] = Connection(self.bus, path, settings, self.delete_connection) + self.props['Connections'] = dbus.Array(self.connections.keys(), 'o') + self.NewConnection(path) + self.PropertiesChanged({ 'connections': self.props['Connections'] }) + + if self.remove_next_connection: + self.remove_next_connection = False + self.connections[path].Delete() + + return path + + def delete_connection(self, connection): + del self.connections[connection.path] + self.props['Connections'] = dbus.Array(self.connections.keys(), 'o') + self.PropertiesChanged({ 'connections': self.props['Connections'] }) + + @dbus.service.method(dbus_interface=IFACE_SETTINGS, in_signature='s', out_signature='') + def SaveHostname(self, hostname): + # Arbitrary requirement to test error handling + if hostname.find('.') == -1: + raise InvalidHostnameException() + self.props['Hostname'] = hostname + self.PropertiesChanged({ 'hostname': hostname }) + + @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, in_signature='s', out_signature='a{sv}') + def GetAll(self, iface): + if iface != IFACE_SETTINGS: + raise UnknownInterfaceException() + return self.props + + @dbus.service.method(dbus_interface=dbus.PROPERTIES_IFACE, in_signature='ss', out_signature='v') + def Get(self, iface, name): + if iface != IFACE_SETTINGS: + raise UnknownInterfaceException() + if not name in self.props.keys(): + raise UnknownPropertyException() + return self.props[name] + + @dbus.service.signal(IFACE_SETTINGS, signature='o') + def NewConnection(self, path): + pass + + @dbus.service.signal(IFACE_SETTINGS, signature='a{sv}') + def PropertiesChanged(self, path): + pass + + @dbus.service.method(IFACE_SETTINGS, in_signature='', out_signature='') + def Quit(self): + mainloop.quit() + +################################################################### +IFACE_AGENT_MANAGER = 'org.freedesktop.NetworkManager.AgentManager' +IFACE_AGENT = 'org.freedesktop.NetworkManager.SecretAgent' + +PATH_SECRET_AGENT = '/org/freedesktop/NetworkManager/SecretAgent' + +FLAG_ALLOW_INTERACTION = 0x1 +FLAG_REQUEST_NEW = 0x2 +FLAG_USER_REQUESTED = 0x4 + +class NoSecretsException(dbus.DBusException): + _dbus_error_name = IFACE_AGENT_MANAGER + '.NoSecrets' + +class UserCanceledException(dbus.DBusException): + _dbus_error_name = IFACE_AGENT_MANAGER + '.UserCanceled' + +class AgentManager(dbus.service.Object): + def __init__(self, bus, object_path): + dbus.service.Object.__init__(self, bus, object_path) + self.agents = {} + self.bus = bus + + @dbus.service.method(dbus_interface=IFACE_AGENT_MANAGER, + in_signature='s', out_signature='', + sender_keyword='sender') + def Register(self, name, sender=None): + self.RegisterWithCapabilities(name, 0, sender) + + @dbus.service.method(dbus_interface=IFACE_AGENT_MANAGER, + in_signature='su', out_signature='', + sender_keyword='sender') + def RegisterWithCapabilities(self, name, caps, sender=None): + self.agents[sender] = self.bus.get_object(sender, PATH_SECRET_AGENT) + + @dbus.service.method(dbus_interface=IFACE_AGENT_MANAGER, + in_signature='', out_signature='', + sender_keyword='sender') + def Unregister(self, sender=None): + del self.agents[sender] + + def get_secrets(self, connection, path, setting_name): + if len(self.agents) == 0: + return None + + secrets = {} + for sender in self.agents: + agent = self.agents[sender] + try: + secrets = agent.GetSecrets(connection, path, setting_name, + dbus.Array([], 's'), + FLAG_ALLOW_INTERACTION | FLAG_USER_REQUESTED, + dbus_interface=IFACE_AGENT) + break + except dbus.DBusException as e: + if e.get_dbus_name() == IFACE_AGENT + '.UserCanceled': + raise UserCanceledException('User canceled') + continue + return secrets + +################################################################### + +def stdin_cb(io, condition): + mainloop.quit() + +def quit_cb(user_data): + mainloop.quit() + +def main(): + dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) + + random.seed() + + bus = dbus.SessionBus() + + global manager, settings, agent_manager + manager = NetworkManager(bus, "/org/freedesktop/NetworkManager") + settings = Settings(bus, "/org/freedesktop/NetworkManager/Settings") + agent_manager = AgentManager(bus, "/org/freedesktop/NetworkManager/AgentManager") + + if not bus.request_name("org.freedesktop.NetworkManager"): + sys.exit(1) + + # Watch stdin; if it closes, assume our parent has crashed, and exit + io = GLib.IOChannel.unix_new(0) + io.add_watch(GLib.IOCondition.HUP, stdin_cb) + + # also quit after inactivity to ensure we don't stick around if the above fails somehow + GLib.timeout_add_seconds(20, quit_cb, None) + + try: + mainloop.run() + except Exception as e: + pass + + sys.exit(0) + +if __name__ == '__main__': + main() + diff --git a/tools/test-sudo-wrapper.sh b/tools/test-sudo-wrapper.sh new file mode 100755 index 00000000..b375368e --- /dev/null +++ b/tools/test-sudo-wrapper.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +CMD="$1" +shift; + +# convert the libtool internal path +resolve_cmd() { + local C="$1" + + local C2="$(echo "$C" | sed 's#^\(.*/\)\.libs/lt-\([^/]\+\)$#\1\2#')" + if [[ "$C2" != "$C" && ! -x "$C2" ]]; then + # such a file does not exist... back to $C + C2="$C" + fi + echo "$C2" +} + +if [[ $UID == 0 ]]; then + # we are already root. Execute directly. + exec "$(resolve_cmd "$CMD")" "$@" +elif [[ "$NMTST_SUDO_NO_CALL_SELF" != "" ]]; then + # when setting $NMTST_SUDO_NO_CALL_SELF, pass the (resolved) command + # directly to sudo. + exec sudo "$(resolve_cmd "$CMD")" "$@" +else + # by default, call self again with sudo. + exec sudo -E "$0" "$CMD" "$@" +fi + |