diff options
| author | Michael Biebl <biebl@debian.org> | 2012-06-29 20:12:44 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2012-06-29 20:12:44 +0200 |
| commit | 867254ea7c2b193fecf8cd36cc6e5dc53c290d92 (patch) | |
| tree | 7c698b403882736ab70c3efd524c3460f08c391c /src | |
| parent | de06e5715e780baade318f3490ac7a4c9ce84e32 (diff) | |
Imported Upstream version 0.9.5.95 upstream/0.9.5.95
Diffstat (limited to 'src')
134 files changed, 8640 insertions, 1760 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index f46fbab3..7930c286 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,7 @@ SUBDIRS= \ generated \ logging \ + posix-signals \ dns-manager \ vpn-manager \ dhcp-manager \ @@ -27,6 +28,7 @@ INCLUDES = -I${top_srcdir} \ -I${top_srcdir}/src/generated \ -I${top_builddir}/src/generated \ -I${top_srcdir}/src/logging \ + -I${top_srcdir}/src/posix-signals \ -I${top_srcdir}/src/dns-manager \ -I${top_srcdir}/src/vpn-manager \ -I${top_srcdir}/src/dhcp-manager \ @@ -120,6 +122,8 @@ NetworkManager_SOURCES = \ nm-device-private.h \ nm-device-ethernet.c \ nm-device-ethernet.h \ + nm-device-adsl.c \ + nm-device-adsl.h \ nm-device-wifi.c \ nm-device-wifi.h \ nm-device-wired.c \ @@ -187,7 +191,9 @@ NetworkManager_SOURCES = \ nm-rfkill.h \ nm-session-monitor.h \ nm-session-utils.c \ - nm-session-utils.h + nm-session-utils.h \ + nm-connection-provider.h \ + nm-connection-provider.c if WITH_CONCHECK NetworkManager_SOURCES += nm-connectivity.c nm-connectivity.h @@ -218,6 +224,9 @@ nm-device-ethernet-glue.h: $(top_srcdir)/introspection/nm-device-ethernet.xml nm-device-infiniband-glue.h: $(top_srcdir)/introspection/nm-device-infiniband.xml $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_infiniband --mode=glib-server --output=$@ $< +nm-device-adsl-glue.h: $(top_srcdir)/introspection/nm-device-adsl.xml + $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_adsl --mode=glib-server --output=$@ $< + nm-device-wifi-glue.h: $(top_srcdir)/introspection/nm-device-wifi.xml $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_wifi --mode=glib-server --output=$@ $< @@ -259,6 +268,7 @@ BUILT_SOURCES = \ nm-device-infiniband-glue.h \ nm-device-bond-glue.h \ nm-device-vlan-glue.h \ + nm-device-adsl-glue.h \ nm-device-wifi-glue.h \ nm-device-olpc-mesh-glue.h \ nm-device-bt-glue.h \ @@ -296,6 +306,7 @@ endif NetworkManager_LDADD = \ ./generated/libnm-generated.la \ ./logging/libnm-logging.la \ + ./posix-signals/libnm-posix-signals.la \ ./dns-manager/libdns-manager.la \ ./vpn-manager/libvpn-manager.la \ ./dhcp-manager/libdhcp-manager.la \ diff --git a/src/Makefile.in b/src/Makefile.in index 715658e8..e1c0fff4 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -58,7 +58,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -97,20 +97,21 @@ am__installdirs = "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(sbindir)" \ PROGRAMS = $(libexec_PROGRAMS) $(sbin_PROGRAMS) am__NetworkManager_SOURCES_DIST = nm-call-store.c nm-call-store.h \ nm-device.c nm-device.h nm-device-private.h \ - nm-device-ethernet.c nm-device-ethernet.h nm-device-wifi.c \ - nm-device-wifi.h nm-device-wired.c nm-device-wired.h \ - nm-device-olpc-mesh.c nm-device-olpc-mesh.h nm-device-bt.c \ - nm-device-bt.h nm-device-modem.h nm-device-modem.c \ - nm-device-infiniband.c nm-device-infiniband.h nm-device-bond.c \ - nm-device-bond.h nm-device-vlan.c nm-device-vlan.h \ - nm-wifi-ap.c nm-wifi-ap.h nm-wifi-ap-utils.c \ - nm-wifi-ap-utils.h nm-dbus-manager.h nm-dbus-manager.c \ - nm-udev-manager.c nm-udev-manager.h nm-device-factory.h \ - nm-hostname-provider.c nm-hostname-provider.h nm-ip4-config.c \ - nm-ip4-config.h nm-ip6-config.c nm-ip6-config.h \ - nm-active-connection.h nm-active-connection.c nm-config.h \ - nm-config.c main.c nm-policy.c nm-policy.h nm-policy-hosts.c \ - nm-policy-hosts.h nm-policy-hostname.c nm-policy-hostname.h \ + nm-device-ethernet.c nm-device-ethernet.h nm-device-adsl.c \ + nm-device-adsl.h nm-device-wifi.c nm-device-wifi.h \ + nm-device-wired.c nm-device-wired.h nm-device-olpc-mesh.c \ + nm-device-olpc-mesh.h nm-device-bt.c nm-device-bt.h \ + nm-device-modem.h nm-device-modem.c nm-device-infiniband.c \ + nm-device-infiniband.h nm-device-bond.c nm-device-bond.h \ + nm-device-vlan.c nm-device-vlan.h nm-wifi-ap.c nm-wifi-ap.h \ + nm-wifi-ap-utils.c nm-wifi-ap-utils.h nm-dbus-manager.h \ + nm-dbus-manager.c nm-udev-manager.c nm-udev-manager.h \ + nm-device-factory.h nm-hostname-provider.c \ + nm-hostname-provider.h nm-ip4-config.c nm-ip4-config.h \ + nm-ip6-config.c nm-ip6-config.h nm-active-connection.h \ + nm-active-connection.c nm-config.h nm-config.c main.c \ + nm-policy.c nm-policy.h nm-policy-hosts.c nm-policy-hosts.h \ + nm-policy-hostname.c nm-policy-hostname.h \ NetworkManagerUtils.c NetworkManagerUtils.h nm-system.c \ nm-system.h nm-manager.c nm-manager.h nm-manager-auth.c \ nm-manager-auth.h nm-netlink-monitor.c nm-netlink-monitor.h \ @@ -120,7 +121,8 @@ am__NetworkManager_SOURCES_DIST = nm-call-store.c nm-call-store.h \ nm-properties-changed-signal.h nm-dhcp4-config.c \ nm-dhcp4-config.h nm-dhcp6-config.c nm-dhcp6-config.h \ nm-rfkill.h nm-session-monitor.h nm-session-utils.c \ - nm-session-utils.h nm-connectivity.c nm-connectivity.h \ + nm-session-utils.h nm-connection-provider.h \ + nm-connection-provider.c nm-connectivity.c nm-connectivity.h \ nm-session-monitor-systemd.c nm-session-monitor-ck.c \ nm-session-monitor-null.c @WITH_CONCHECK_TRUE@am__objects_1 = \ @@ -131,6 +133,7 @@ am__NetworkManager_SOURCES_DIST = nm-call-store.c nm-call-store.h \ am_NetworkManager_OBJECTS = NetworkManager-nm-call-store.$(OBJEXT) \ NetworkManager-nm-device.$(OBJEXT) \ NetworkManager-nm-device-ethernet.$(OBJEXT) \ + NetworkManager-nm-device-adsl.$(OBJEXT) \ NetworkManager-nm-device-wifi.$(OBJEXT) \ NetworkManager-nm-device-wired.$(OBJEXT) \ NetworkManager-nm-device-olpc-mesh.$(OBJEXT) \ @@ -163,12 +166,16 @@ am_NetworkManager_OBJECTS = NetworkManager-nm-call-store.$(OBJEXT) \ NetworkManager-nm-properties-changed-signal.$(OBJEXT) \ NetworkManager-nm-dhcp4-config.$(OBJEXT) \ NetworkManager-nm-dhcp6-config.$(OBJEXT) \ - NetworkManager-nm-session-utils.$(OBJEXT) $(am__objects_1) \ - $(am__objects_2) $(am__objects_3) $(am__objects_4) + NetworkManager-nm-session-utils.$(OBJEXT) \ + NetworkManager-nm-connection-provider.$(OBJEXT) \ + $(am__objects_1) $(am__objects_2) $(am__objects_3) \ + $(am__objects_4) NetworkManager_OBJECTS = $(am_NetworkManager_OBJECTS) @WITH_CONCHECK_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) NetworkManager_DEPENDENCIES = ./generated/libnm-generated.la \ - ./logging/libnm-logging.la ./dns-manager/libdns-manager.la \ + ./logging/libnm-logging.la \ + ./posix-signals/libnm-posix-signals.la \ + ./dns-manager/libdns-manager.la \ ./vpn-manager/libvpn-manager.la \ ./dhcp-manager/libdhcp-manager.la \ ./ip6-manager/libip6-manager.la \ @@ -263,10 +270,10 @@ AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ distdir ETAGS = etags CTAGS = ctags -DIST_SUBDIRS = generated logging dns-manager vpn-manager dhcp-manager \ - ip6-manager supplicant-manager ppp-manager backends \ - dnsmasq-manager modem-manager bluez-manager firewall-manager \ - wifi settings wimax . tests +DIST_SUBDIRS = generated logging posix-signals dns-manager vpn-manager \ + dhcp-manager ip6-manager supplicant-manager ppp-manager \ + backends dnsmasq-manager modem-manager bluez-manager \ + firewall-manager wifi settings wimax . tests DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ @@ -365,6 +372,10 @@ 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@ @@ -460,6 +471,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -498,6 +512,8 @@ 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@ @@ -518,16 +534,17 @@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -SUBDIRS = generated logging dns-manager vpn-manager dhcp-manager \ - ip6-manager supplicant-manager ppp-manager backends \ - dnsmasq-manager modem-manager bluez-manager firewall-manager \ - wifi settings $(am__append_1) . tests +SUBDIRS = generated logging posix-signals dns-manager vpn-manager \ + dhcp-manager ip6-manager supplicant-manager ppp-manager \ + backends dnsmasq-manager modem-manager bluez-manager \ + firewall-manager wifi settings $(am__append_1) . tests INCLUDES = -I${top_srcdir} \ -I${top_srcdir}/include \ -I${top_builddir}/include \ -I${top_srcdir}/src/generated \ -I${top_builddir}/src/generated \ -I${top_srcdir}/src/logging \ + -I${top_srcdir}/src/posix-signals \ -I${top_srcdir}/src/dns-manager \ -I${top_srcdir}/src/vpn-manager \ -I${top_srcdir}/src/dhcp-manager \ @@ -607,10 +624,11 @@ libtest_wifi_ap_utils_la_LIBADD = \ NetworkManager_SOURCES = nm-call-store.c nm-call-store.h nm-device.c \ nm-device.h nm-device-private.h nm-device-ethernet.c \ - nm-device-ethernet.h nm-device-wifi.c nm-device-wifi.h \ - nm-device-wired.c nm-device-wired.h nm-device-olpc-mesh.c \ - nm-device-olpc-mesh.h nm-device-bt.c nm-device-bt.h \ - nm-device-modem.h nm-device-modem.c nm-device-infiniband.c \ + nm-device-ethernet.h nm-device-adsl.c nm-device-adsl.h \ + nm-device-wifi.c nm-device-wifi.h nm-device-wired.c \ + nm-device-wired.h nm-device-olpc-mesh.c nm-device-olpc-mesh.h \ + nm-device-bt.c nm-device-bt.h nm-device-modem.h \ + nm-device-modem.c nm-device-infiniband.c \ nm-device-infiniband.h nm-device-bond.c nm-device-bond.h \ nm-device-vlan.c nm-device-vlan.h nm-wifi-ap.c nm-wifi-ap.h \ nm-wifi-ap-utils.c nm-wifi-ap-utils.h nm-dbus-manager.h \ @@ -630,7 +648,8 @@ NetworkManager_SOURCES = nm-call-store.c nm-call-store.h nm-device.c \ nm-properties-changed-signal.h nm-dhcp4-config.c \ nm-dhcp4-config.h nm-dhcp6-config.c nm-dhcp6-config.h \ nm-rfkill.h nm-session-monitor.h nm-session-utils.c \ - nm-session-utils.h $(am__append_2) $(am__append_3) \ + nm-session-utils.h nm-connection-provider.h \ + nm-connection-provider.c $(am__append_2) $(am__append_3) \ $(am__append_4) $(am__append_5) BUILT_SOURCES = \ nm-access-point-glue.h \ @@ -640,6 +659,7 @@ BUILT_SOURCES = \ nm-device-infiniband-glue.h \ nm-device-bond-glue.h \ nm-device-vlan-glue.h \ + nm-device-adsl-glue.h \ nm-device-wifi-glue.h \ nm-device-olpc-mesh-glue.h \ nm-device-bt-glue.h \ @@ -660,7 +680,9 @@ NetworkManager_CPPFLAGS = $(DBUS_CFLAGS) $(GLIB_CFLAGS) \ -DNM_RUN_DIR=\"$(rundir)\" -DNMLOCALEDIR=\"$(datadir)/locale\" \ -DNMPLUGINDIR=\"$(pkglibdir)\" $(am__append_6) NetworkManager_LDADD = ./generated/libnm-generated.la \ - ./logging/libnm-logging.la ./dns-manager/libdns-manager.la \ + ./logging/libnm-logging.la \ + ./posix-signals/libnm-posix-signals.la \ + ./dns-manager/libdns-manager.la \ ./vpn-manager/libvpn-manager.la \ ./dhcp-manager/libdhcp-manager.la \ ./ip6-manager/libip6-manager.la \ @@ -853,8 +875,10 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-active-connection.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-call-store.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-config.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-connection-provider.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-connectivity.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-dbus-manager.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-device-adsl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-device-bond.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-device-bt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NetworkManager-nm-device-ethernet.Po@am__quote@ @@ -1018,6 +1042,22 @@ NetworkManager-nm-device-ethernet.obj: nm-device-ethernet.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-ethernet.obj `if test -f 'nm-device-ethernet.c'; then $(CYGPATH_W) 'nm-device-ethernet.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-ethernet.c'; fi` +NetworkManager-nm-device-adsl.o: nm-device-adsl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-adsl.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-adsl.Tpo -c -o NetworkManager-nm-device-adsl.o `test -f 'nm-device-adsl.c' || echo '$(srcdir)/'`nm-device-adsl.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-adsl.Tpo $(DEPDIR)/NetworkManager-nm-device-adsl.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-device-adsl.c' object='NetworkManager-nm-device-adsl.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-adsl.o `test -f 'nm-device-adsl.c' || echo '$(srcdir)/'`nm-device-adsl.c + +NetworkManager-nm-device-adsl.obj: nm-device-adsl.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-adsl.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-adsl.Tpo -c -o NetworkManager-nm-device-adsl.obj `if test -f 'nm-device-adsl.c'; then $(CYGPATH_W) 'nm-device-adsl.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-adsl.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-adsl.Tpo $(DEPDIR)/NetworkManager-nm-device-adsl.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-device-adsl.c' object='NetworkManager-nm-device-adsl.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-device-adsl.obj `if test -f 'nm-device-adsl.c'; then $(CYGPATH_W) 'nm-device-adsl.c'; else $(CYGPATH_W) '$(srcdir)/nm-device-adsl.c'; fi` + NetworkManager-nm-device-wifi.o: nm-device-wifi.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-device-wifi.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-device-wifi.Tpo -c -o NetworkManager-nm-device-wifi.o `test -f 'nm-device-wifi.c' || echo '$(srcdir)/'`nm-device-wifi.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-device-wifi.Tpo $(DEPDIR)/NetworkManager-nm-device-wifi.Po @@ -1546,6 +1586,22 @@ NetworkManager-nm-session-utils.obj: nm-session-utils.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-session-utils.obj `if test -f 'nm-session-utils.c'; then $(CYGPATH_W) 'nm-session-utils.c'; else $(CYGPATH_W) '$(srcdir)/nm-session-utils.c'; fi` +NetworkManager-nm-connection-provider.o: nm-connection-provider.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-connection-provider.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-connection-provider.Tpo -c -o NetworkManager-nm-connection-provider.o `test -f 'nm-connection-provider.c' || echo '$(srcdir)/'`nm-connection-provider.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-connection-provider.Tpo $(DEPDIR)/NetworkManager-nm-connection-provider.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-connection-provider.c' object='NetworkManager-nm-connection-provider.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-connection-provider.o `test -f 'nm-connection-provider.c' || echo '$(srcdir)/'`nm-connection-provider.c + +NetworkManager-nm-connection-provider.obj: nm-connection-provider.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-connection-provider.obj -MD -MP -MF $(DEPDIR)/NetworkManager-nm-connection-provider.Tpo -c -o NetworkManager-nm-connection-provider.obj `if test -f 'nm-connection-provider.c'; then $(CYGPATH_W) 'nm-connection-provider.c'; else $(CYGPATH_W) '$(srcdir)/nm-connection-provider.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-connection-provider.Tpo $(DEPDIR)/NetworkManager-nm-connection-provider.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-connection-provider.c' object='NetworkManager-nm-connection-provider.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o NetworkManager-nm-connection-provider.obj `if test -f 'nm-connection-provider.c'; then $(CYGPATH_W) 'nm-connection-provider.c'; else $(CYGPATH_W) '$(srcdir)/nm-connection-provider.c'; fi` + NetworkManager-nm-connectivity.o: nm-connectivity.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(NetworkManager_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT NetworkManager-nm-connectivity.o -MD -MP -MF $(DEPDIR)/NetworkManager-nm-connectivity.Tpo -c -o NetworkManager-nm-connectivity.o `test -f 'nm-connectivity.c' || echo '$(srcdir)/'`nm-connectivity.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/NetworkManager-nm-connectivity.Tpo $(DEPDIR)/NetworkManager-nm-connectivity.Po @@ -2015,6 +2071,9 @@ nm-device-ethernet-glue.h: $(top_srcdir)/introspection/nm-device-ethernet.xml nm-device-infiniband-glue.h: $(top_srcdir)/introspection/nm-device-infiniband.xml $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_infiniband --mode=glib-server --output=$@ $< +nm-device-adsl-glue.h: $(top_srcdir)/introspection/nm-device-adsl.xml + $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_adsl --mode=glib-server --output=$@ $< + nm-device-wifi-glue.h: $(top_srcdir)/introspection/nm-device-wifi.xml $(AM_V_GEN) dbus-binding-tool --prefix=nm_device_wifi --mode=glib-server --output=$@ $< diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c index 6c2c0446..952b4e5d 100644 --- a/src/NetworkManagerUtils.c +++ b/src/NetworkManagerUtils.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2004 - 2011 Red Hat, Inc. + * Copyright (C) 2004 - 2012 Red Hat, Inc. * Copyright (C) 2005 - 2008 Novell, Inc. */ @@ -41,6 +41,7 @@ #include "nm-setting-wireless.h" #include "nm-setting-wireless-security.h" #include "nm-manager-auth.h" +#include "nm-posix-signals.h" /* * nm_ethernet_address_is_valid @@ -94,7 +95,7 @@ nm_spawn_process (const char *args) return -1; } - if (!g_spawn_sync ("/", argv, NULL, 0, NULL, NULL, NULL, NULL, &status, &error)) { + if (!g_spawn_sync ("/", argv, NULL, 0, nm_unblock_posix_signals, NULL, NULL, NULL, &status, &error)) { nm_log_warn (LOGD_CORE, "could not spawn process '%s': %s", args, error->message); g_error_free (error); } diff --git a/src/backends/Makefile.in b/src/backends/Makefile.in index 9c6f7d0c..48895fd3 100644 --- a/src/backends/Makefile.in +++ b/src/backends/Makefile.in @@ -60,7 +60,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -214,6 +214,10 @@ 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@ @@ -309,6 +313,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -347,6 +354,8 @@ 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@ diff --git a/src/backends/NetworkManagerRedHat.c b/src/backends/NetworkManagerRedHat.c index c14eb837..843b03b2 100644 --- a/src/backends/NetworkManagerRedHat.c +++ b/src/backends/NetworkManagerRedHat.c @@ -35,7 +35,11 @@ void nm_backend_update_dns (void) { /* Invalidate the nscd host cache since we changed resolv.conf */ if (g_file_test ("/usr/sbin/nscd", G_FILE_TEST_EXISTS | G_FILE_TEST_IS_EXECUTABLE | G_FILE_TEST_IS_REGULAR)) { - nm_spawn_process ("/etc/init.d/nscd condrestart"); + if (g_file_test ("/etc/init.d/nscd", G_FILE_TEST_EXISTS)) + nm_spawn_process ("/etc/init.d/nscd condrestart"); + else if (g_file_test ("/bin/systemctl", G_FILE_TEST_IS_EXECUTABLE)) + nm_spawn_process ("/bin/systemctl condrestart nscd.service"); + nm_spawn_process ("/usr/sbin/nscd -i hosts"); } } diff --git a/src/bluez-manager/Makefile.in b/src/bluez-manager/Makefile.in index efb5ab4e..eb9b464b 100644 --- a/src/bluez-manager/Makefile.in +++ b/src/bluez-manager/Makefile.in @@ -47,7 +47,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -171,6 +171,10 @@ 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@ @@ -266,6 +270,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -304,6 +311,8 @@ 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@ diff --git a/src/bluez-manager/nm-bluez-adapter.c b/src/bluez-manager/nm-bluez-adapter.c index 27a85e78..4c36f3de 100644 --- a/src/bluez-manager/nm-bluez-adapter.c +++ b/src/bluez-manager/nm-bluez-adapter.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2009 - 2010 Red Hat, Inc. + * Copyright (C) 2009 - 2012 Red Hat, Inc. */ #include <glib.h> @@ -41,6 +41,9 @@ typedef struct { char *address; GHashTable *devices; + + /* Cached for devices */ + NMConnectionProvider *provider; } NMBluezAdapterPrivate; @@ -85,23 +88,18 @@ nm_bluez_adapter_get_initialized (NMBluezAdapter *self) return NM_BLUEZ_ADAPTER_GET_PRIVATE (self)->initialized; } -static void -devices_to_list (gpointer key, gpointer data, gpointer user_data) -{ - NMBluezDevice *device = NM_BLUEZ_DEVICE (data); - GSList **list = user_data; - - if (nm_bluez_device_get_usable (device)) - *list = g_slist_append (*list, data); -} - GSList * nm_bluez_adapter_get_devices (NMBluezAdapter *self) { - NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); GSList *devices = NULL; + GHashTableIter iter; + NMBluezDevice *device; - g_hash_table_foreach (priv->devices, devices_to_list, &devices); + g_hash_table_iter_init (&iter, NM_BLUEZ_ADAPTER_GET_PRIVATE (self)->devices); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) { + if (nm_bluez_device_get_usable (device)) + devices = g_slist_append (devices, device); + } return devices; } @@ -109,16 +107,19 @@ static void device_usable (NMBluezDevice *device, GParamSpec *pspec, gpointer user_data) { NMBluezAdapter *self = NM_BLUEZ_ADAPTER (user_data); - NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); + gboolean usable = nm_bluez_device_get_usable (device); - if (nm_bluez_device_get_usable (device)) + nm_log_dbg (LOGD_BT, "(%s): bluez device now %s", + nm_bluez_device_get_path (device), + usable ? "usable" : "unusable"); + + if (usable) { + nm_log_dbg (LOGD_BT, "(%s): bluez device address %s", + nm_bluez_device_get_path (device), + nm_bluez_device_get_address (device)); g_signal_emit (self, signals[DEVICE_ADDED], 0, device); - else { - g_object_ref (device); - g_hash_table_remove (priv->devices, nm_bluez_device_get_path (device)); + } else g_signal_emit (self, signals[DEVICE_REMOVED], 0, device); - g_object_unref (device); - } } static void @@ -127,6 +128,9 @@ device_initialized (NMBluezDevice *device, gboolean success, gpointer user_data) NMBluezAdapter *self = NM_BLUEZ_ADAPTER (user_data); NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); + nm_log_dbg (LOGD_BT, "(%s): bluez device %s", + nm_bluez_device_get_path (device), + success ? "initialized" : "failed to initialize"); if (!success) g_hash_table_remove (priv->devices, nm_bluez_device_get_path (device)); } @@ -138,10 +142,12 @@ device_created (DBusGProxy *proxy, const char *path, gpointer user_data) NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); NMBluezDevice *device; - device = nm_bluez_device_new (path); + device = nm_bluez_device_new (path, priv->provider); g_signal_connect (device, "initialized", G_CALLBACK (device_initialized), self); g_signal_connect (device, "notify::usable", G_CALLBACK (device_usable), self); - g_hash_table_insert (priv->devices, g_strdup (path), device); + g_hash_table_insert (priv->devices, (gpointer) nm_bluez_device_get_path (device), device); + + nm_log_dbg (LOGD_BT, "(%s): new bluez device found", path); } static void @@ -151,10 +157,12 @@ device_removed (DBusGProxy *proxy, const char *path, gpointer user_data) NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); NMBluezDevice *device; + nm_log_dbg (LOGD_BT, "(%s): bluez device removed", path); + device = g_hash_table_lookup (priv->devices, path); if (device) { g_object_ref (device); - g_hash_table_remove (priv->devices, path); + g_hash_table_remove (priv->devices, nm_bluez_device_get_path (device)); g_signal_emit (self, signals[DEVICE_REMOVED], 0, device); g_object_unref (device); } @@ -214,8 +222,10 @@ query_properties (NMBluezAdapter *self) } } +/***********************************************************/ + NMBluezAdapter * -nm_bluez_adapter_new (const char *path) +nm_bluez_adapter_new (const char *path, NMConnectionProvider *provider) { NMBluezAdapter *self; NMBluezAdapterPrivate *priv; @@ -229,6 +239,9 @@ nm_bluez_adapter_new (const char *path) return NULL; priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); + + priv->provider = provider; + dbus_mgr = nm_dbus_manager_get (); connection = nm_dbus_manager_get_connection (dbus_mgr); @@ -258,7 +271,23 @@ nm_bluez_adapter_init (NMBluezAdapter *self) NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, g_object_unref); + NULL, g_object_unref); +} + +static void +dispose (GObject *object) +{ + NMBluezAdapter *self = NM_BLUEZ_ADAPTER (object); + NMBluezAdapterPrivate *priv = NM_BLUEZ_ADAPTER_GET_PRIVATE (self); + GHashTableIter iter; + NMBluezDevice *device; + + g_hash_table_iter_init (&iter, priv->devices); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &device)) + g_signal_emit (self, signals[DEVICE_REMOVED], 0, device); + g_hash_table_remove_all (priv->devices); + + G_OBJECT_CLASS (nm_bluez_adapter_parent_class)->dispose (object); } static void @@ -320,6 +349,7 @@ nm_bluez_adapter_class_init (NMBluezAdapterClass *config_class) /* virtual methods */ object_class->get_property = get_property; object_class->set_property = set_property; + object_class->dispose = dispose; object_class->finalize = finalize; /* Properties */ diff --git a/src/bluez-manager/nm-bluez-adapter.h b/src/bluez-manager/nm-bluez-adapter.h index c552e989..36aa55df 100644 --- a/src/bluez-manager/nm-bluez-adapter.h +++ b/src/bluez-manager/nm-bluez-adapter.h @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2009 - 2012 Red Hat, Inc. */ #ifndef NM_BLUEZ_ADAPTER_H @@ -25,6 +25,7 @@ #include <glib-object.h> #include "nm-bluez-device.h" +#include "nm-connection-provider.h" #define NM_TYPE_BLUEZ_ADAPTER (nm_bluez_adapter_get_type ()) #define NM_BLUEZ_ADAPTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ_ADAPTER, NMBluezAdapter)) @@ -53,7 +54,8 @@ typedef struct { GType nm_bluez_adapter_get_type (void); -NMBluezAdapter *nm_bluez_adapter_new (const char *path); +NMBluezAdapter *nm_bluez_adapter_new (const char *path, + NMConnectionProvider *provider); const char *nm_bluez_adapter_get_path (NMBluezAdapter *self); diff --git a/src/bluez-manager/nm-bluez-device.c b/src/bluez-manager/nm-bluez-device.c index ecb6ce51..b12a8619 100644 --- a/src/bluez-manager/nm-bluez-device.c +++ b/src/bluez-manager/nm-bluez-device.c @@ -15,13 +15,17 @@ * 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 - 2010 Red Hat, Inc. + * Copyright (C) 2009 - 2012 Red Hat, Inc. */ #include <glib.h> #include <string.h> +#include <net/ethernet.h> +#include <netinet/ether.h> #include "NetworkManager.h" +#include "nm-setting-bluetooth.h" + #include "nm-dbus-manager.h" #include "nm-bluez-device.h" #include "nm-bluez-common.h" @@ -41,9 +45,13 @@ typedef struct { gboolean usable; char *address; + guint8 bin_address[ETH_ALEN]; char *name; guint32 capabilities; gint rssi; + + NMConnectionProvider *provider; + GSList *connections; } NMBluezDevicePrivate; @@ -66,6 +74,8 @@ enum { }; static guint signals[LAST_SIGNAL] = { 0 }; +/***********************************************************/ + const char * nm_bluez_device_get_path (NMBluezDevice *self) { @@ -122,59 +132,137 @@ nm_bluez_device_get_rssi (NMBluezDevice *self) return NM_BLUEZ_DEVICE_GET_PRIVATE (self)->rssi; } -static guint32 -convert_uuids_to_capabilities (const char **strings) +static void +check_emit_usable (NMBluezDevice *self) { - const char **iter; - guint32 capabilities = 0; + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + gboolean new_usable; - for (iter = strings; iter && *iter; iter++) { - char **parts; - guint uuid16; + new_usable = (priv->initialized && priv->capabilities && priv->name && priv->address && priv->connections); + if (new_usable != priv->usable) { + priv->usable = new_usable; + g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_USABLE); + } +} - parts = g_strsplit (*iter, "-", -1); - if (parts == NULL || parts[0] == NULL) { - g_strfreev (parts); - continue; - } +/********************************************************************/ - uuid16 = g_ascii_strtoull (parts[0], NULL, 16); - g_strfreev (parts); +static gboolean +connection_compatible (NMBluezDevice *self, NMConnection *connection) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + NMSettingBluetooth *s_bt; + const char *bt_type; + const GByteArray *bdaddr; - switch (uuid16) { - case 0x1103: - capabilities |= NM_BT_CAPABILITY_DUN; - break; - case 0x1116: - capabilities |= NM_BT_CAPABILITY_NAP; - break; - default: - break; - } + if (!nm_connection_is_type (connection, NM_SETTING_BLUETOOTH_SETTING_NAME)) + return FALSE; + + s_bt = nm_connection_get_setting_bluetooth (connection); + if (!s_bt) + return FALSE; + + bdaddr = nm_setting_bluetooth_get_bdaddr (s_bt); + if (!bdaddr || bdaddr->len != ETH_ALEN) + return FALSE; + if (memcmp (bdaddr->data, priv->bin_address, ETH_ALEN) != 0) + return FALSE; + + bt_type = nm_setting_bluetooth_get_connection_type (s_bt); + if ( g_str_equal (bt_type, NM_SETTING_BLUETOOTH_TYPE_DUN) + && !(priv->capabilities & NM_BT_CAPABILITY_DUN)) + return FALSE; + + if ( g_str_equal (bt_type, NM_SETTING_BLUETOOTH_TYPE_PANU) + && !(priv->capabilities & NM_BT_CAPABILITY_NAP)) + return FALSE; + + return TRUE; +} + +static void +_internal_add_connection (NMBluezDevice *self, NMConnection *connection) +{ + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + if (!g_slist_find (priv->connections, connection)) { + priv->connections = g_slist_prepend (priv->connections, g_object_ref (connection)); + check_emit_usable (self); } +} - return capabilities; +static void +cp_connection_added (NMConnectionProvider *provider, + NMConnection *connection, + NMBluezDevice *self) +{ + if (connection_compatible (self, connection)) + _internal_add_connection (self, connection); } static void -check_emit_usable (NMBluezDevice *self) +cp_connection_removed (NMConnectionProvider *provider, + NMConnection *connection, + NMBluezDevice *self) { NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); - if ( priv->initialized - && priv->capabilities - && priv->name - && priv->address) { - if (!priv->usable) { - priv->usable = TRUE; - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_USABLE); - } - } else { - if (priv->usable) { - priv->usable = FALSE; - g_object_notify (G_OBJECT (self), NM_BLUEZ_DEVICE_USABLE); + if (g_slist_find (priv->connections, connection)) { + priv->connections = g_slist_remove (priv->connections, connection); + g_object_unref (connection); + check_emit_usable (self); + } +} + +static void +cp_connection_updated (NMConnectionProvider *provider, + NMConnection *connection, + NMBluezDevice *self) +{ + if (connection_compatible (self, connection)) + _internal_add_connection (self, connection); + else + cp_connection_removed (provider, connection, self); +} + +static void +cp_connections_loaded (NMConnectionProvider *provider, NMBluezDevice *self) +{ + const GSList *connections, *iter; + + connections = nm_connection_provider_get_connections (provider); + for (iter = connections; iter; iter = g_slist_next (iter)) + cp_connection_added (provider, NM_CONNECTION (iter->data), self); +} + +/***********************************************************/ + +static guint32 +convert_uuids_to_capabilities (const char **strings) +{ + const char **iter; + guint32 capabilities = 0; + + for (iter = strings; iter && *iter; iter++) { + char **parts; + + parts = g_strsplit (*iter, "-", -1); + if (parts && parts[0]) { + switch (g_ascii_strtoull (parts[0], NULL, 16)) { + case 0x1103: + capabilities |= NM_BT_CAPABILITY_DUN; + break; + case 0x1116: + capabilities |= NM_BT_CAPABILITY_NAP; + break; + default: + break; + } } + g_strfreev (parts); } + + return capabilities; } static void @@ -224,6 +312,7 @@ get_properties_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) GError *err = NULL; GValue *value; const char **uuids; + struct ether_addr *tmp; if (!dbus_g_proxy_end_call (proxy, call, &err, DBUS_TYPE_G_MAP_OF_VARIANT, &properties, @@ -237,6 +326,11 @@ get_properties_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) value = g_hash_table_lookup (properties, "Address"); priv->address = value ? g_value_dup_string (value) : NULL; + if (priv->address) { + tmp = ether_aton (priv->address); + g_assert (tmp); + memcpy (priv->bin_address, tmp->ether_addr_octet, ETH_ALEN); + } value = g_hash_table_lookup (properties, "Name"); priv->name = value ? g_value_dup_string (value) : NULL; @@ -253,6 +347,9 @@ get_properties_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) g_hash_table_unref (properties); + /* Check if any connections match this device */ + cp_connections_loaded (priv->provider, self); + priv->initialized = TRUE; g_signal_emit (self, signals[INITIALIZED], 0, TRUE); @@ -275,14 +372,18 @@ query_properties (NMBluezDevice *self) } } +/********************************************************************/ + NMBluezDevice * -nm_bluez_device_new (const char *path) +nm_bluez_device_new (const char *path, NMConnectionProvider *provider) { NMBluezDevice *self; NMBluezDevicePrivate *priv; NMDBusManager *dbus_mgr; DBusGConnection *connection; + g_return_val_if_fail (path != NULL, NULL); + g_return_val_if_fail (provider != NULL, NULL); self = (NMBluezDevice *) g_object_new (NM_TYPE_BLUEZ_DEVICE, NM_BLUEZ_DEVICE_PATH, path, @@ -291,6 +392,29 @@ nm_bluez_device_new (const char *path) return NULL; priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + priv->provider = provider; + + g_signal_connect (priv->provider, + NM_CP_SIGNAL_CONNECTION_ADDED, + G_CALLBACK (cp_connection_added), + self); + + g_signal_connect (priv->provider, + NM_CP_SIGNAL_CONNECTION_REMOVED, + G_CALLBACK (cp_connection_removed), + self); + + g_signal_connect (priv->provider, + NM_CP_SIGNAL_CONNECTION_UPDATED, + G_CALLBACK (cp_connection_updated), + self); + + g_signal_connect (priv->provider, + NM_CP_SIGNAL_CONNECTIONS_LOADED, + G_CALLBACK (cp_connections_loaded), + self); + dbus_mgr = nm_dbus_manager_get (); connection = nm_dbus_manager_get_connection (dbus_mgr); @@ -319,6 +443,24 @@ nm_bluez_device_init (NMBluezDevice *self) } static void +dispose (GObject *object) +{ + NMBluezDevice *self = NM_BLUEZ_DEVICE (object); + NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (self); + + g_slist_foreach (priv->connections, (GFunc) g_object_unref, NULL); + g_slist_free (priv->connections); + priv->connections = NULL; + + g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_added, self); + g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_removed, self); + g_signal_handlers_disconnect_by_func (priv->provider, cp_connection_updated, self); + g_signal_handlers_disconnect_by_func (priv->provider, cp_connections_loaded, self); + + G_OBJECT_CLASS (nm_bluez_device_parent_class)->dispose (object); +} + +static void finalize (GObject *object) { NMBluezDevicePrivate *priv = NM_BLUEZ_DEVICE_GET_PRIVATE (object); @@ -389,6 +531,7 @@ nm_bluez_device_class_init (NMBluezDeviceClass *config_class) /* virtual methods */ object_class->get_property = get_property; object_class->set_property = set_property; + object_class->dispose = dispose; object_class->finalize = finalize; /* Properties */ diff --git a/src/bluez-manager/nm-bluez-device.h b/src/bluez-manager/nm-bluez-device.h index 8a6b3597..f5fdbf5f 100644 --- a/src/bluez-manager/nm-bluez-device.h +++ b/src/bluez-manager/nm-bluez-device.h @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2009 Red Hat, Inc. + * Copyright (C) 2009 - 2012 Red Hat, Inc. */ #ifndef NM_BLUEZ_DEVICE_H @@ -24,6 +24,9 @@ #include <glib.h> #include <glib-object.h> +#include "nm-connection.h" +#include "nm-connection-provider.h" + #define NM_TYPE_BLUEZ_DEVICE (nm_bluez_device_get_type ()) #define NM_BLUEZ_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_BLUEZ_DEVICE, NMBluezDevice)) #define NM_BLUEZ_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_BLUEZ_DEVICE, NMBluezDeviceClass)) @@ -53,7 +56,7 @@ typedef struct { GType nm_bluez_device_get_type (void); -NMBluezDevice *nm_bluez_device_new (const char *path); +NMBluezDevice *nm_bluez_device_new (const char *path, NMConnectionProvider *provider); const char *nm_bluez_device_get_path (NMBluezDevice *self); diff --git a/src/bluez-manager/nm-bluez-manager.c b/src/bluez-manager/nm-bluez-manager.c index 942d0f34..e485ffe4 100644 --- a/src/bluez-manager/nm-bluez-manager.c +++ b/src/bluez-manager/nm-bluez-manager.c @@ -16,7 +16,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Copyright (C) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2010 Red Hat, Inc. + * Copyright (C) 2007 - 2012 Red Hat, Inc. */ #include <signal.h> @@ -37,6 +37,8 @@ typedef struct { NMDBusManager *dbus_mgr; gulong name_owner_changed_id; + NMConnectionProvider *provider; + DBusGProxy *proxy; NMBluezAdapter *adapter; @@ -165,7 +167,7 @@ default_adapter_changed (DBusGProxy *proxy, const char *path, NMBluezManager *se /* Add the new default adapter */ if (path) { - priv->adapter = nm_bluez_adapter_new (path); + priv->adapter = nm_bluez_adapter_new (path, priv->provider); g_signal_connect (priv->adapter, "initialized", G_CALLBACK (adapter_initialized), self); } } @@ -238,12 +240,6 @@ bluez_connect (NMBluezManager *self) } static void -remove_all_devices (NMBluezManager *self, gboolean do_signal) -{ - /* FIXME: do something */ -} - -static void name_owner_changed_cb (NMDBusManager *dbus_mgr, const char *name, const char *old_owner, @@ -251,6 +247,7 @@ name_owner_changed_cb (NMDBusManager *dbus_mgr, gpointer user_data) { NMBluezManager *self = NM_BLUEZ_MANAGER (user_data); + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); gboolean old_owner_good = (old_owner && strlen (old_owner)); gboolean new_owner_good = (new_owner && strlen (new_owner)); @@ -260,8 +257,13 @@ name_owner_changed_cb (NMDBusManager *dbus_mgr, if (!old_owner_good && new_owner_good) query_default_adapter (self); - else if (old_owner_good && !new_owner_good) - remove_all_devices (self, TRUE); + else if (old_owner_good && !new_owner_good) { + /* Throwing away the adapter removes all devices too */ + if (priv->adapter) { + g_object_unref (priv->adapter); + priv->adapter = NULL; + } + } } static void @@ -274,7 +276,10 @@ bluez_cleanup (NMBluezManager *self, gboolean do_signal) priv->proxy = NULL; } - remove_all_devices (self, do_signal); + if (priv->adapter) { + g_object_unref (priv->adapter); + priv->adapter = NULL; + } } static void @@ -290,24 +295,22 @@ dbus_connection_changed_cb (NMDBusManager *dbus_mgr, bluez_connect (self); } +/****************************************************************/ NMBluezManager * -nm_bluez_manager_new (void) -{ - return NM_BLUEZ_MANAGER (g_object_new (NM_TYPE_BLUEZ_MANAGER, NULL)); -} - -NMBluezManager * -nm_bluez_manager_get (void) +nm_bluez_manager_get (NMConnectionProvider *provider) { static NMBluezManager *singleton = NULL; - if (!singleton) - singleton = nm_bluez_manager_new (); - else - g_object_ref (singleton); + if (singleton) + return g_object_ref (singleton); + singleton = (NMBluezManager *) g_object_new (NM_TYPE_BLUEZ_MANAGER, NULL); g_assert (singleton); + + /* Cache the connection provider for NMBluezAdapter objects */ + NM_BLUEZ_MANAGER_GET_PRIVATE (singleton)->provider = provider; + return singleton; } @@ -333,13 +336,20 @@ nm_bluez_manager_init (NMBluezManager *self) } static void -finalize (GObject *object) +dispose (GObject *object) { NMBluezManager *self = NM_BLUEZ_MANAGER (object); + NMBluezManagerPrivate *priv = NM_BLUEZ_MANAGER_GET_PRIVATE (self); bluez_cleanup (self, FALSE); - G_OBJECT_CLASS (nm_bluez_manager_parent_class)->finalize (object); + 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); + g_object_unref (priv->dbus_mgr); + } + + G_OBJECT_CLASS (nm_bluez_manager_parent_class)->dispose (object); } static void @@ -350,11 +360,11 @@ nm_bluez_manager_class_init (NMBluezManagerClass *klass) g_type_class_add_private (klass, sizeof (NMBluezManagerPrivate)); /* virtual methods */ - object_class->finalize = finalize; + object_class->dispose = dispose; /* Signals */ signals[BDADDR_ADDED] = - g_signal_new ("bdaddr-added", + g_signal_new (NM_BLUEZ_MANAGER_BDADDR_ADDED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (NMBluezManagerClass, bdaddr_added), @@ -363,7 +373,7 @@ nm_bluez_manager_class_init (NMBluezManagerClass *klass) G_TYPE_NONE, 4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_UINT); signals[BDADDR_REMOVED] = - g_signal_new ("bdaddr-removed", + g_signal_new (NM_BLUEZ_MANAGER_BDADDR_REMOVED, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (NMBluezManagerClass, bdaddr_removed), diff --git a/src/bluez-manager/nm-bluez-manager.h b/src/bluez-manager/nm-bluez-manager.h index 9cfab1b7..1549e699 100644 --- a/src/bluez-manager/nm-bluez-manager.h +++ b/src/bluez-manager/nm-bluez-manager.h @@ -16,7 +16,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Copyright (C) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2009 Red Hat, Inc. + * Copyright (C) 2007 - 2012 Red Hat, Inc. */ #ifndef NM_BLUEZ_MANAGER_H @@ -25,6 +25,8 @@ #include <glib.h> #include <glib-object.h> +#include "nm-connection-provider.h" + G_BEGIN_DECLS #define NM_TYPE_BLUEZ_MANAGER (nm_bluez_manager_get_type ()) @@ -34,6 +36,9 @@ G_BEGIN_DECLS #define NM_IS_BLUEZ_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_BLUEZ_MANAGER)) #define NM_BLUEZ_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_BLUEZ_MANAGER, NMBluezManagerClass)) +#define NM_BLUEZ_MANAGER_BDADDR_ADDED "bdaddr-added" +#define NM_BLUEZ_MANAGER_BDADDR_REMOVED "bdaddr-removed" + typedef struct { GObject parent; } NMBluezManager; @@ -55,8 +60,8 @@ typedef struct { GType nm_bluez_manager_get_type (void); -NMBluezManager *nm_bluez_manager_new (void); -NMBluezManager *nm_bluez_manager_get (void); +NMBluezManager *nm_bluez_manager_get (NMConnectionProvider *provider); + void nm_bluez_manager_query_devices (NMBluezManager *manager); #endif /* NM_BLUEZ_MANAGER_H */ diff --git a/src/dhcp-manager/Makefile.am b/src/dhcp-manager/Makefile.am index ce34c416..11560fde 100644 --- a/src/dhcp-manager/Makefile.am +++ b/src/dhcp-manager/Makefile.am @@ -7,6 +7,7 @@ INCLUDES = \ -I${top_srcdir}/src/generated \ -I${top_builddir}/src/generated \ -I${top_srcdir}/src/logging \ + -I${top_srcdir}/src/posix-signals \ -I${top_srcdir}/libnm-util \ -I${top_builddir}/libnm-util \ -I${top_srcdir}/src @@ -33,6 +34,7 @@ libdhcp_dhclient_la_CPPFLAGS = \ libdhcp_dhclient_la_LIBADD = \ $(top_builddir)/src/logging/libnm-logging.la \ + $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ $(top_builddir)/libnm-util/libnm-util.la \ $(DBUS_LIBS) \ $(GLIB_LIBS) @@ -58,6 +60,7 @@ libdhcp_manager_la_CPPFLAGS = \ libdhcp_manager_la_LIBADD = \ $(top_builddir)/src/logging/libnm-logging.la \ + $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ $(builddir)/libdhcp-dhclient.la \ $(DBUS_LIBS) \ $(GLIB_LIBS) diff --git a/src/dhcp-manager/Makefile.in b/src/dhcp-manager/Makefile.in index 4c389562..3d71a405 100644 --- a/src/dhcp-manager/Makefile.in +++ b/src/dhcp-manager/Makefile.in @@ -47,7 +47,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -58,6 +58,7 @@ LTLIBRARIES = $(noinst_LTLIBRARIES) am__DEPENDENCIES_1 = libdhcp_dhclient_la_DEPENDENCIES = \ $(top_builddir)/src/logging/libnm-logging.la \ + $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ $(top_builddir)/libnm-util/libnm-util.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_libdhcp_dhclient_la_OBJECTS = \ @@ -69,6 +70,7 @@ am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) am__v_lt_0 = --silent libdhcp_manager_la_DEPENDENCIES = \ $(top_builddir)/src/logging/libnm-logging.la \ + $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ $(builddir)/libdhcp-dhclient.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_libdhcp_manager_la_OBJECTS = libdhcp_manager_la-nm-dhcp-client.lo \ @@ -217,6 +219,10 @@ 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@ @@ -312,6 +318,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -350,6 +359,8 @@ 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@ @@ -378,6 +389,7 @@ INCLUDES = \ -I${top_srcdir}/src/generated \ -I${top_builddir}/src/generated \ -I${top_srcdir}/src/logging \ + -I${top_srcdir}/src/posix-signals \ -I${top_srcdir}/libnm-util \ -I${top_builddir}/libnm-util \ -I${top_srcdir}/src @@ -403,6 +415,7 @@ libdhcp_dhclient_la_CPPFLAGS = \ libdhcp_dhclient_la_LIBADD = \ $(top_builddir)/src/logging/libnm-logging.la \ + $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ $(top_builddir)/libnm-util/libnm-util.la \ $(DBUS_LIBS) \ $(GLIB_LIBS) @@ -428,6 +441,7 @@ libdhcp_manager_la_CPPFLAGS = \ libdhcp_manager_la_LIBADD = \ $(top_builddir)/src/logging/libnm-logging.la \ + $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ $(builddir)/libdhcp-dhclient.la \ $(DBUS_LIBS) \ $(GLIB_LIBS) diff --git a/src/dhcp-manager/nm-dhcp-client.c b/src/dhcp-manager/nm-dhcp-client.c index 16c6dd77..ea4084ac 100644 --- a/src/dhcp-manager/nm-dhcp-client.c +++ b/src/dhcp-manager/nm-dhcp-client.c @@ -570,8 +570,20 @@ nm_dhcp_client_new_options (NMDHCPClient *self, g_hash_table_remove_all (priv->options); g_hash_table_foreach (options, copy_option, priv->options); - if (old_state == new_state) - return; + if (old_state == new_state) { + /* dhclient will stay in the same state (or, really, provide the same + * reason) for operations like RENEW and REBIND. We need to ensure + * that triggers various DHCP lease change code, so we need to pass + * along same-state transitions for these states. + */ + if ( new_state != DHC_BOUND4 + && new_state != DHC_RENEW4 + && new_state != DHC_REBIND4 + && new_state != DHC_BOUND6 + && new_state != DHC_RENEW6 + && new_state != DHC_REBIND6) + return; + } /* Handle changed device state */ if (state_is_bound (new_state)) { @@ -1217,12 +1229,6 @@ ip6_options_to_config (NMDHCPClient *self) return NULL; } - addr = nm_ip6_address_new (); - if (!addr) { - nm_log_warn (LOGD_DHCP6, "(%s): couldn't allocate memory for an IP6 Address!", priv->iface); - goto error; - } - str = g_hash_table_lookup (priv->options, "new_ip6_address"); if (str) { if (!inet_pton (AF_INET6, str, &tmp_addr)) { @@ -1231,35 +1237,17 @@ ip6_options_to_config (NMDHCPClient *self) goto error; } + addr = nm_ip6_address_new (); + g_assert (addr); nm_ip6_address_set_address (addr, &tmp_addr); - nm_log_info (LOGD_DHCP6, " address %s", str); - } else { - /* No address in managed mode is a hard error */ - if (priv->info_only == FALSE) - goto error; - - /* But "info-only" setups don't necessarily need an address */ - nm_ip6_address_unref (addr); - addr = NULL; - } - - /* Only care about prefix if we got an address */ - if (addr) { - str = g_hash_table_lookup (priv->options, "new_ip6_prefixlen"); - if (str) { - long unsigned int prefix; - - errno = 0; - prefix = strtoul (str, NULL, 10); - if (errno != 0 || prefix > 128) - goto error; - - nm_ip6_address_set_prefix (addr, (guint32) prefix); - nm_log_info (LOGD_DHCP6, " prefix %lu", prefix); - } + /* DHCPv6 IA_NA assignments are single address only */ + nm_ip6_address_set_prefix (addr, 128); + nm_log_info (LOGD_DHCP6, " address %s/128", str); nm_ip6_config_take_address (ip6_config, addr); - addr = NULL; + } else if (priv->info_only == FALSE) { + /* No address in Managed mode is a hard error */ + goto error; } str = g_hash_table_lookup (priv->options, "new_host_name"); @@ -1288,8 +1276,6 @@ ip6_options_to_config (NMDHCPClient *self) return ip6_config; error: - if (addr) - nm_ip6_address_unref (addr); g_object_unref (ip6_config); return NULL; } diff --git a/src/dhcp-manager/nm-dhcp-dhclient.c b/src/dhcp-manager/nm-dhcp-dhclient.c index 09321396..043cd63d 100644 --- a/src/dhcp-manager/nm-dhcp-dhclient.c +++ b/src/dhcp-manager/nm-dhcp-dhclient.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2005 - 2010 Red Hat, Inc. + * Copyright (C) 2005 - 2012 Red Hat, Inc. */ #define _XOPEN_SOURCE @@ -40,6 +40,7 @@ #include "nm-utils.h" #include "nm-logging.h" #include "nm-dhcp-dhclient-utils.h" +#include "nm-posix-signals.h" G_DEFINE_TYPE (NMDHCPDhclient, nm_dhcp_dhclient, NM_TYPE_DHCP_CLIENT) @@ -333,6 +334,7 @@ merge_dhclient_config (const char *iface, g_assert (new); success = g_file_set_contents (conf_file, new, -1, error); g_free (new); + g_free (orig); return success; } @@ -407,6 +409,12 @@ dhclient_child_setup (gpointer user_data G_GNUC_UNUSED) /* We are in the child process at this point */ pid_t pid = getpid (); setpgid (pid, pid); + + /* + * We blocked signals in main(). We need to restore original signal + * mask for dhclient here so that it can receive signals. + */ + nm_unblock_posix_signals (NULL); } static GPid diff --git a/src/dhcp-manager/nm-dhcp-dhcpcd.c b/src/dhcp-manager/nm-dhcp-dhcpcd.c index 237661fe..dc9bee13 100644 --- a/src/dhcp-manager/nm-dhcp-dhcpcd.c +++ b/src/dhcp-manager/nm-dhcp-dhcpcd.c @@ -35,6 +35,7 @@ #include "nm-dhcp-dhcpcd.h" #include "nm-utils.h" #include "nm-logging.h" +#include "nm-posix-signals.h" G_DEFINE_TYPE (NMDHCPDhcpcd, nm_dhcp_dhcpcd, NM_TYPE_DHCP_CLIENT) @@ -83,6 +84,12 @@ dhcpcd_child_setup (gpointer user_data G_GNUC_UNUSED) /* We are in the child process at this point */ pid_t pid = getpid (); setpgid (pid, pid); + + /* + * We blocked signals in main(). We need to restore original signal + * mask for dhcpcd here so that it can receive signals. + */ + nm_unblock_posix_signals (NULL); } static GPid diff --git a/src/dhcp-manager/tests/Makefile.in b/src/dhcp-manager/tests/Makefile.in index 20422cdb..d325dd9e 100644 --- a/src/dhcp-manager/tests/Makefile.in +++ b/src/dhcp-manager/tests/Makefile.in @@ -48,7 +48,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -169,6 +169,10 @@ 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@ @@ -264,6 +268,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -302,6 +309,8 @@ 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@ diff --git a/src/dns-manager/Makefile.am b/src/dns-manager/Makefile.am index 331f85c4..fd31b140 100644 --- a/src/dns-manager/Makefile.am +++ b/src/dns-manager/Makefile.am @@ -1,5 +1,6 @@ INCLUDES = \ -I${top_srcdir}/src/logging \ + -I${top_srcdir}/src/posix-signals \ -I${top_srcdir}/libnm-util \ -I${top_builddir}/libnm-util \ -I${top_srcdir}/src \ @@ -28,6 +29,7 @@ libdns_manager_la_CPPFLAGS = \ libdns_manager_la_LIBADD = \ $(top_builddir)/src/logging/libnm-logging.la \ + $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ $(LIBNL_LIBS) \ $(DBUS_LIBS) \ $(GLIB_LIBS) diff --git a/src/dns-manager/Makefile.in b/src/dns-manager/Makefile.in index c9b8b0b3..ddcce666 100644 --- a/src/dns-manager/Makefile.in +++ b/src/dns-manager/Makefile.in @@ -47,7 +47,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -58,6 +58,7 @@ LTLIBRARIES = $(noinst_LTLIBRARIES) am__DEPENDENCIES_1 = libdns_manager_la_DEPENDENCIES = \ $(top_builddir)/src/logging/libnm-logging.la \ + $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_libdns_manager_la_OBJECTS = libdns_manager_la-nm-dns-manager.lo \ @@ -172,6 +173,10 @@ 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@ @@ -267,6 +272,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -305,6 +313,8 @@ 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@ @@ -327,6 +337,7 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ INCLUDES = \ -I${top_srcdir}/src/logging \ + -I${top_srcdir}/src/posix-signals \ -I${top_srcdir}/libnm-util \ -I${top_builddir}/libnm-util \ -I${top_srcdir}/src \ @@ -354,6 +365,7 @@ libdns_manager_la_CPPFLAGS = \ libdns_manager_la_LIBADD = \ $(top_builddir)/src/logging/libnm-logging.la \ + $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ $(LIBNL_LIBS) \ $(DBUS_LIBS) \ $(GLIB_LIBS) diff --git a/src/dns-manager/nm-dns-manager.c b/src/dns-manager/nm-dns-manager.c index 6272e374..38ef08ea 100644 --- a/src/dns-manager/nm-dns-manager.c +++ b/src/dns-manager/nm-dns-manager.c @@ -16,7 +16,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Copyright (C) 2004 - 2005 Colin Walters <walters@redhat.com> - * Copyright (C) 2004 - 2011 Red Hat, Inc. + * Copyright (C) 2004 - 2012 Red Hat, Inc. * Copyright (C) 2005 - 2008 Novell, Inc. * and others */ @@ -42,6 +42,7 @@ #include "nm-logging.h" #include "backends/nm-backend.h" #include "NetworkManagerUtils.h" +#include "nm-posix-signals.h" #include "nm-dns-plugin.h" #include "nm-dns-dnsmasq.h" @@ -61,6 +62,8 @@ G_DEFINE_TYPE(NMDnsManager, nm_dns_manager, G_TYPE_OBJECT) NM_TYPE_DNS_MANAGER, \ NMDnsManagerPrivate)) +#define HASH_LEN 20 + typedef struct { gboolean disposed; @@ -70,14 +73,10 @@ typedef struct { NMIP6Config *ip6_device_config; GSList *configs; char *hostname; + guint updates_queue; - /* poor man's hash; we assume that the IP4 config object won't change - * after it's given to us, which is (at this time) a fair assumption. So - * we track the order of the currently applied IP configs and if they - * haven't changed we don't need to rewrite resolv.conf. - */ - #define HLEN 6 - gpointer hash[HLEN]; + guint8 hash[HASH_LEN]; /* SHA1 hash of current DNS config */ + guint8 prev_hash[HASH_LEN]; /* Hash when begin_updates() was called */ GSList *plugins; @@ -218,6 +217,12 @@ netconfig_child_setup (gpointer user_data G_GNUC_UNUSED) { pid_t pid = getpid (); setpgid (pid, pid); + + /* + * We blocked signals in main(). We need to restore original signal + * mask for netconfig here so that it can receive signals. + */ + nm_unblock_posix_signals (NULL); } static GPid @@ -529,34 +534,43 @@ out: } static void -compute_hash (NMDnsManager *self, gpointer *hash) +compute_hash (NMDnsManager *self, guint8 buffer[HASH_LEN]) { NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); - gpointer check[HLEN]; + GChecksum *sum; GSList *iter; - int i = 0; + gsize len = HASH_LEN; - memset (check, 0, sizeof (check)); + sum = g_checksum_new (G_CHECKSUM_SHA1); + g_assert (len == g_checksum_type_get_length (G_CHECKSUM_SHA1)); if (priv->ip4_vpn_config) - check[i++] = priv->ip4_vpn_config; + nm_ip4_config_hash (priv->ip4_vpn_config, sum, TRUE); if (priv->ip4_device_config) - check[i++] = priv->ip4_device_config; + nm_ip4_config_hash (priv->ip4_device_config, sum, TRUE); if (priv->ip6_vpn_config) - check[i++] = priv->ip6_vpn_config; + nm_ip6_config_hash (priv->ip6_vpn_config, sum, TRUE); if (priv->ip6_device_config) - check[i++] = priv->ip6_device_config; + nm_ip6_config_hash (priv->ip6_device_config, sum, TRUE); - /* Add two more "other" configs if any exist */ - for (iter = priv->configs; iter && i < HLEN; iter = g_slist_next (iter)) { - if ( (iter->data != priv->ip4_vpn_config) - && (iter->data != priv->ip4_device_config) - && (iter->data != priv->ip6_vpn_config) - && (iter->data != priv->ip6_device_config)) - check[i++] = iter->data; + /* add any other configs we know about */ + for (iter = priv->configs; iter; iter = g_slist_next (iter)) { + if ( (iter->data == priv->ip4_vpn_config) + && (iter->data == priv->ip4_device_config) + && (iter->data == priv->ip6_vpn_config) + && (iter->data == priv->ip6_device_config)) + continue; + + if (NM_IS_IP4_CONFIG (iter->data)) + nm_ip4_config_hash (NM_IP4_CONFIG (iter->data), sum, TRUE); + else if (NM_IS_IP6_CONFIG (iter->data)) + nm_ip6_config_hash (NM_IP6_CONFIG (iter->data), sum, TRUE); } - memcpy (hash, check, sizeof (check)); + + memset (buffer, 0, sizeof (buffer)); + g_checksum_get_digest (sum, buffer, &len); + g_checksum_free (sum); } static gboolean @@ -581,6 +595,8 @@ update_dns (NMDnsManager *self, priv = NM_DNS_MANAGER_GET_PRIVATE (self); + nm_log_dbg (LOGD_DNS, "updating resolv.conf"); + if (iface && (iface != priv->last_iface)) { g_free (priv->last_iface); priv->last_iface = g_strdup (iface); @@ -784,23 +800,6 @@ plugin_failed (NMDnsPlugin *plugin, gpointer user_data) } } -static gboolean -config_changed (NMDnsManager *self) -{ - NMDnsManagerPrivate *priv = NM_DNS_MANAGER_GET_PRIVATE (self); - gpointer check[HLEN]; - - /* We only store HLEN configs; so if there are actually more than that, - * we have to assume that the config has changed. - */ - if (g_slist_length (priv->configs) > HLEN) - return TRUE; - - /* Otherwise return TRUE if the configuration has changed */ - compute_hash (self, check); - return memcmp (check, priv->hash, sizeof (check)) ? TRUE : FALSE; -} - gboolean nm_dns_manager_add_ip4_config (NMDnsManager *mgr, const char *iface, @@ -831,10 +830,7 @@ nm_dns_manager_add_ip4_config (NMDnsManager *mgr, if (!g_slist_find (priv->configs, config)) priv->configs = g_slist_append (priv->configs, g_object_ref (config)); - if (!config_changed (mgr)) - return TRUE; - - if (!update_dns (mgr, iface, FALSE, &error)) { + if (!priv->updates_queue && !update_dns (mgr, iface, FALSE, &error)) { nm_log_warn (LOGD_DNS, "could not commit DNS changes: (%d) %s", error ? error->code : -1, error && error->message ? error->message : "(unknown)"); @@ -871,10 +867,7 @@ nm_dns_manager_remove_ip4_config (NMDnsManager *mgr, g_object_unref (config); - if (!config_changed (mgr)) - return TRUE; - - if (!update_dns (mgr, iface, FALSE, &error)) { + if (!priv->updates_queue && !update_dns (mgr, iface, FALSE, &error)) { nm_log_warn (LOGD_DNS, "could not commit DNS changes: (%d) %s", error ? error->code : -1, error && error->message ? error->message : "(unknown)"); @@ -901,8 +894,6 @@ nm_dns_manager_add_ip6_config (NMDnsManager *mgr, switch (cfg_type) { case NM_DNS_IP_CONFIG_TYPE_VPN: - /* FIXME: not quite yet... */ - g_return_val_if_fail (cfg_type != NM_DNS_IP_CONFIG_TYPE_VPN, FALSE); priv->ip6_vpn_config = config; break; case NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE: @@ -916,10 +907,7 @@ nm_dns_manager_add_ip6_config (NMDnsManager *mgr, if (!g_slist_find (priv->configs, config)) priv->configs = g_slist_append (priv->configs, g_object_ref (config)); - if (!config_changed (mgr)) - return TRUE; - - if (!update_dns (mgr, iface, FALSE, &error)) { + if (!priv->updates_queue && !update_dns (mgr, iface, FALSE, &error)) { nm_log_warn (LOGD_DNS, "could not commit DNS changes: (%d) %s", error ? error->code : -1, error && error->message ? error->message : "(unknown)"); @@ -956,10 +944,7 @@ nm_dns_manager_remove_ip6_config (NMDnsManager *mgr, g_object_unref (config); - if (!config_changed (mgr)) - return TRUE; - - if (!update_dns (mgr, iface, FALSE, &error)) { + if (!priv->updates_queue && !update_dns (mgr, iface, FALSE, &error)) { nm_log_warn (LOGD_DNS, "could not commit DNS changes: (%d) %s", error ? error->code : -1, error && error->message ? error->message : "(unknown)"); @@ -997,7 +982,7 @@ nm_dns_manager_set_hostname (NMDnsManager *mgr, * wants one. But hostname changes are system-wide and *not* tied to a * specific interface, so netconfig can't really handle this. Fake it. */ - if (!update_dns (mgr, priv->last_iface, FALSE, &error)) { + if (!priv->updates_queue && !update_dns (mgr, priv->last_iface, FALSE, &error)) { nm_log_warn (LOGD_DNS, "could not commit DNS changes: (%d) %s", error ? error->code : -1, error && error->message ? error->message : "(unknown)"); @@ -1005,6 +990,58 @@ nm_dns_manager_set_hostname (NMDnsManager *mgr, } } +void +nm_dns_manager_begin_updates (NMDnsManager *mgr, const char *func) +{ + NMDnsManagerPrivate *priv; + + g_return_if_fail (mgr != NULL); + priv = NM_DNS_MANAGER_GET_PRIVATE (mgr); + + /* Save current hash when starting a new batch */ + if (priv->updates_queue == 0) + memcpy (priv->prev_hash, priv->hash, sizeof (priv->hash)); + + priv->updates_queue++; + + nm_log_dbg (LOGD_DNS, "(%s): queueing DNS updates (%d)", func, priv->updates_queue); +} + +void +nm_dns_manager_end_updates (NMDnsManager *mgr, const char *func) +{ + NMDnsManagerPrivate *priv; + GError *error = NULL; + gboolean changed; + guint8 new[HASH_LEN]; + + g_return_if_fail (mgr != NULL); + + priv = NM_DNS_MANAGER_GET_PRIVATE (mgr); + g_return_if_fail (priv->updates_queue > 0); + + compute_hash (mgr, new); + changed = (memcmp (new, priv->prev_hash, sizeof (new)) != 0) ? TRUE : FALSE; + nm_log_dbg (LOGD_DNS, "(%s): DNS configuration %s", __func__, changed ? "changed" : "did not change"); + + priv->updates_queue--; + if ((priv->updates_queue > 0) || (changed == FALSE)) { + nm_log_dbg (LOGD_DNS, "(%s): no DNS changes to commit (%d)", func, priv->updates_queue); + return; + } + + /* Commit all the outstanding changes */ + nm_log_dbg (LOGD_DNS, "(%s): committing DNS changes (%d)", func, priv->updates_queue); + if (!update_dns (mgr, priv->last_iface, FALSE, &error)) { + nm_log_warn (LOGD_DNS, "could not commit DNS changes: (%d) %s", + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + } + + memset (priv->prev_hash, 0, sizeof (priv->prev_hash)); +} + static void load_plugins (NMDnsManager *self, const char **plugins) { @@ -1079,8 +1116,10 @@ nm_dns_manager_error_quark (void) } static void -nm_dns_manager_init (NMDnsManager *mgr) +nm_dns_manager_init (NMDnsManager *self) { + /* Set the initial hash */ + compute_hash (self, NM_DNS_MANAGER_GET_PRIVATE (self)->hash); } static void diff --git a/src/dns-manager/nm-dns-manager.h b/src/dns-manager/nm-dns-manager.h index 25d2a981..f559865b 100644 --- a/src/dns-manager/nm-dns-manager.h +++ b/src/dns-manager/nm-dns-manager.h @@ -66,6 +66,10 @@ GType nm_dns_manager_get_type (void); NMDnsManager * nm_dns_manager_get (const char **plugins); +/* Allow changes to be batched together */ +void nm_dns_manager_begin_updates (NMDnsManager *mgr, const char *func); +void nm_dns_manager_end_updates (NMDnsManager *mgr, const char *func); + gboolean nm_dns_manager_add_ip4_config (NMDnsManager *mgr, const char *iface, NMIP4Config *config, diff --git a/src/dns-manager/nm-dns-plugin.c b/src/dns-manager/nm-dns-plugin.c index e997948e..b26f2b94 100644 --- a/src/dns-manager/nm-dns-plugin.c +++ b/src/dns-manager/nm-dns-plugin.c @@ -13,7 +13,7 @@ * 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 Red Hat, Inc. + * Copyright (C) 2010 - 2012 Red Hat, Inc. * */ @@ -27,6 +27,7 @@ #include "nm-dns-plugin.h" #include "nm-logging.h" +#include "nm-posix-signals.h" typedef struct { gboolean disposed; @@ -141,6 +142,12 @@ child_setup (gpointer user_data G_GNUC_UNUSED) /* We are in the child process at this point */ pid_t pid = getpid (); setpgid (pid, pid); + + /* + * We blocked signals in main(). We need to restore original signal + * mask for DNS plugin here so that it can receive signals. + */ + nm_unblock_posix_signals (NULL); } GPid diff --git a/src/dnsmasq-manager/Makefile.am b/src/dnsmasq-manager/Makefile.am index 66bbdd83..8b7dd683 100644 --- a/src/dnsmasq-manager/Makefile.am +++ b/src/dnsmasq-manager/Makefile.am @@ -1,6 +1,7 @@ INCLUDES = \ -I${top_srcdir}/libnm-util \ -I${top_srcdir}/src/logging \ + -I${top_srcdir}/src/posix-signals \ -I${top_srcdir}/src \ -I${top_srcdir}/include @@ -16,4 +17,5 @@ libdnsmasq_manager_la_CPPFLAGS = \ libdnsmasq_manager_la_LIBADD = \ $(top_builddir)/src/logging/libnm-logging.la \ + $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ $(GLIB_LIBS) diff --git a/src/dnsmasq-manager/Makefile.in b/src/dnsmasq-manager/Makefile.in index bb1e56c0..6da083c4 100644 --- a/src/dnsmasq-manager/Makefile.in +++ b/src/dnsmasq-manager/Makefile.in @@ -47,7 +47,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -58,6 +58,7 @@ LTLIBRARIES = $(noinst_LTLIBRARIES) am__DEPENDENCIES_1 = libdnsmasq_manager_la_DEPENDENCIES = \ $(top_builddir)/src/logging/libnm-logging.la \ + $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ $(am__DEPENDENCIES_1) am_libdnsmasq_manager_la_OBJECTS = \ libdnsmasq_manager_la-nm-dnsmasq-manager.lo @@ -168,6 +169,10 @@ 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@ @@ -263,6 +268,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -301,6 +309,8 @@ 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@ @@ -324,6 +334,7 @@ top_srcdir = @top_srcdir@ INCLUDES = \ -I${top_srcdir}/libnm-util \ -I${top_srcdir}/src/logging \ + -I${top_srcdir}/src/posix-signals \ -I${top_srcdir}/src \ -I${top_srcdir}/include @@ -338,6 +349,7 @@ libdnsmasq_manager_la_CPPFLAGS = \ libdnsmasq_manager_la_LIBADD = \ $(top_builddir)/src/logging/libnm-logging.la \ + $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ $(GLIB_LIBS) all: all-am diff --git a/src/dnsmasq-manager/nm-dnsmasq-manager.c b/src/dnsmasq-manager/nm-dnsmasq-manager.c index ca2f9dc4..0b3b629f 100644 --- a/src/dnsmasq-manager/nm-dnsmasq-manager.c +++ b/src/dnsmasq-manager/nm-dnsmasq-manager.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2008 - 2010 Red Hat, Inc. + * Copyright (C) 2008 - 2012 Red Hat, Inc. */ #include <config.h> @@ -30,6 +30,7 @@ #include "nm-dnsmasq-manager.h" #include "nm-logging.h" #include "nm-glib-compat.h" +#include "nm-posix-signals.h" typedef struct { char *iface; @@ -356,6 +357,12 @@ dm_child_setup (gpointer user_data G_GNUC_UNUSED) /* We are in the child process at this point */ pid_t pid = getpid (); setpgid (pid, pid); + + /* + * We blocked signals in main(). We need to restore original signal + * mask for dnsmasq here so that it can receive signals. + */ + nm_unblock_posix_signals (NULL); } static void diff --git a/src/firewall-manager/Makefile.in b/src/firewall-manager/Makefile.in index 821fa838..59ade87c 100644 --- a/src/firewall-manager/Makefile.in +++ b/src/firewall-manager/Makefile.in @@ -47,7 +47,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -168,6 +168,10 @@ 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@ @@ -263,6 +267,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -301,6 +308,8 @@ 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@ diff --git a/src/generated/Makefile.in b/src/generated/Makefile.in index 85a346be..966a9638 100644 --- a/src/generated/Makefile.in +++ b/src/generated/Makefile.in @@ -48,7 +48,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -167,6 +167,10 @@ 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@ @@ -262,6 +266,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -300,6 +307,8 @@ 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@ diff --git a/src/generated/nm-enum-types.c b/src/generated/nm-enum-types.c index a9973b4d..aa73b52e 100644 --- a/src/generated/nm-enum-types.c +++ b/src/generated/nm-enum-types.c @@ -5,29 +5,30 @@ #include "nm-enum-types.h" -#include "nm-device-vlan.h" +#include "nm-ip4-config.h" #include "nm-device-olpc-mesh.h" #include "nm-hostname-provider.h" #include "nm-device.h" #include "nm-rfkill.h" #include "NetworkManagerUtils.h" +#include "nm-device-vlan.h" #include "nm-device-factory.h" #include "nm-active-connection.h" #include "nm-wifi-ap.h" -#include "nm-device-ethernet.h" #include "nm-device-bt.h" +#include "nm-device-private.h" #include "nm-device-wifi.h" #include "nm-dbus-manager.h" #include "nm-dhcp4-config.h" #include "nm-dhcp6-config.h" #include "nm-netlink-compat.h" #include "nm-session-monitor.h" -#include "nm-ip4-config.h" #include "nm-device-bond.h" #include "nm-wifi-ap-utils.h" -#include "nm-call-store.h" +#include "nm-device-adsl.h" #include "nm-policy-hosts.h" #include "nm-udev-manager.h" +#include "nm-connection-provider.h" #include "nm-manager.h" #include "nm-device-modem.h" #include "nm-device-wired.h" @@ -37,7 +38,7 @@ #include "nm-device-infiniband.h" #include "nm-properties-changed-signal.h" #include "nm-ip6-config.h" -#include "nm-device-private.h" +#include "nm-call-store.h" #include "nm-policy.h" #include "nm-manager-auth.h" #include "nm-config.h" @@ -45,6 +46,7 @@ #include "nm-netlink-monitor.h" #include "nm-system.h" #include "nm-connectivity.h" +#include "nm-device-ethernet.h" #include "nm-logging.h" #include "nm-dns-utils.h" #include "nm-dns-plugin.h" @@ -56,9 +58,9 @@ #include "nm-vpn-connection.h" #include "nm-dhcp-dhcpcd.h" #include "nm-dhcp-dhclient.h" +#include "nm-dhcp-manager.h" #include "nm-dhcp-client.h" #include "nm-dhcp-dhclient-utils.h" -#include "nm-dhcp-manager.h" #include "nm-ip6-manager.h" #include "nm-supplicant-types.h" #include "nm-supplicant-config.h" @@ -97,20 +99,30 @@ #include "nm-wimax-nsp.h" GType -nm_vlan_error_get_type (void) +nm_ip4_config_compare_flags_get_type (void) { static volatile gsize g_define_type_id__volatile = 0; if (g_once_init_enter (&g_define_type_id__volatile)) { static const GEnumValue values[] = { - { NM_VLAN_ERROR_CONNECTION_NOT_VLAN, "NM_VLAN_ERROR_CONNECTION_NOT_VLAN", "ConnectionNotVlan" }, - { NM_VLAN_ERROR_CONNECTION_INVALID, "NM_VLAN_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, - { NM_VLAN_ERROR_CONNECTION_INCOMPATIBLE, "NM_VLAN_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, + { NM_IP4_COMPARE_FLAG_NONE, "NM_IP4_COMPARE_FLAG_NONE", "none" }, + { NM_IP4_COMPARE_FLAG_ADDRESSES, "NM_IP4_COMPARE_FLAG_ADDRESSES", "addresses" }, + { NM_IP4_COMPARE_FLAG_PTP_ADDRESS, "NM_IP4_COMPARE_FLAG_PTP_ADDRESS", "ptp-address" }, + { NM_IP4_COMPARE_FLAG_NAMESERVERS, "NM_IP4_COMPARE_FLAG_NAMESERVERS", "nameservers" }, + { NM_IP4_COMPARE_FLAG_ROUTES, "NM_IP4_COMPARE_FLAG_ROUTES", "routes" }, + { NM_IP4_COMPARE_FLAG_DOMAINS, "NM_IP4_COMPARE_FLAG_DOMAINS", "domains" }, + { NM_IP4_COMPARE_FLAG_SEARCHES, "NM_IP4_COMPARE_FLAG_SEARCHES", "searches" }, + { NM_IP4_COMPARE_FLAG_MTU, "NM_IP4_COMPARE_FLAG_MTU", "mtu" }, + { NM_IP4_COMPARE_FLAG_MSS, "NM_IP4_COMPARE_FLAG_MSS", "mss" }, + { NM_IP4_COMPARE_FLAG_WINS_SERVERS, "NM_IP4_COMPARE_FLAG_WINS_SERVERS", "wins-servers" }, + { NM_IP4_COMPARE_FLAG_NIS_SERVERS, "NM_IP4_COMPARE_FLAG_NIS_SERVERS", "nis-servers" }, + { NM_IP4_COMPARE_FLAG_NIS_DOMAIN, "NM_IP4_COMPARE_FLAG_NIS_DOMAIN", "nis-domain" }, + { NM_IP4_COMPARE_FLAG_ALL, "NM_IP4_COMPARE_FLAG_ALL", "all" }, { 0, NULL, NULL } }; GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMVlanError"), values); + g_enum_register_static (g_intern_static_string ("NMIP4ConfigCompareFlags"), values); g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); } @@ -199,20 +211,20 @@ nm_rf_kill_type_get_type (void) return g_define_type_id__volatile; } GType -nm_ethernet_error_get_type (void) +nm_vlan_error_get_type (void) { static volatile gsize g_define_type_id__volatile = 0; if (g_once_init_enter (&g_define_type_id__volatile)) { static const GEnumValue values[] = { - { NM_ETHERNET_ERROR_CONNECTION_NOT_WIRED, "NM_ETHERNET_ERROR_CONNECTION_NOT_WIRED", "ConnectionNotWired" }, - { NM_ETHERNET_ERROR_CONNECTION_INVALID, "NM_ETHERNET_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, - { NM_ETHERNET_ERROR_CONNECTION_INCOMPATIBLE, "NM_ETHERNET_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, + { NM_VLAN_ERROR_CONNECTION_NOT_VLAN, "NM_VLAN_ERROR_CONNECTION_NOT_VLAN", "ConnectionNotVlan" }, + { NM_VLAN_ERROR_CONNECTION_INVALID, "NM_VLAN_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, + { NM_VLAN_ERROR_CONNECTION_INCOMPATIBLE, "NM_VLAN_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, { 0, NULL, NULL } }; GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMEthernetError"), values); + g_enum_register_static (g_intern_static_string ("NMVlanError"), values); g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); } @@ -250,6 +262,7 @@ nm_wifi_error_get_type (void) { NM_WIFI_ERROR_CONNECTION_INVALID, "NM_WIFI_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, { NM_WIFI_ERROR_CONNECTION_INCOMPATIBLE, "NM_WIFI_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, { NM_WIFI_ERROR_ACCESS_POINT_NOT_FOUND, "NM_WIFI_ERROR_ACCESS_POINT_NOT_FOUND", "AccessPointNotFound" }, + { NM_WIFI_ERROR_SCAN_NOT_ALLOWED, "NM_WIFI_ERROR_SCAN_NOT_ALLOWED", "ScanNotAllowed" }, { 0, NULL, NULL } }; GType g_define_type_id = @@ -260,50 +273,40 @@ nm_wifi_error_get_type (void) return g_define_type_id__volatile; } GType -nm_ip4_config_compare_flags_get_type (void) +nm_bond_error_get_type (void) { static volatile gsize g_define_type_id__volatile = 0; if (g_once_init_enter (&g_define_type_id__volatile)) { static const GEnumValue values[] = { - { NM_IP4_COMPARE_FLAG_NONE, "NM_IP4_COMPARE_FLAG_NONE", "none" }, - { NM_IP4_COMPARE_FLAG_ADDRESSES, "NM_IP4_COMPARE_FLAG_ADDRESSES", "addresses" }, - { NM_IP4_COMPARE_FLAG_PTP_ADDRESS, "NM_IP4_COMPARE_FLAG_PTP_ADDRESS", "ptp-address" }, - { NM_IP4_COMPARE_FLAG_NAMESERVERS, "NM_IP4_COMPARE_FLAG_NAMESERVERS", "nameservers" }, - { NM_IP4_COMPARE_FLAG_ROUTES, "NM_IP4_COMPARE_FLAG_ROUTES", "routes" }, - { NM_IP4_COMPARE_FLAG_DOMAINS, "NM_IP4_COMPARE_FLAG_DOMAINS", "domains" }, - { NM_IP4_COMPARE_FLAG_SEARCHES, "NM_IP4_COMPARE_FLAG_SEARCHES", "searches" }, - { NM_IP4_COMPARE_FLAG_MTU, "NM_IP4_COMPARE_FLAG_MTU", "mtu" }, - { NM_IP4_COMPARE_FLAG_MSS, "NM_IP4_COMPARE_FLAG_MSS", "mss" }, - { NM_IP4_COMPARE_FLAG_WINS_SERVERS, "NM_IP4_COMPARE_FLAG_WINS_SERVERS", "wins-servers" }, - { NM_IP4_COMPARE_FLAG_NIS_SERVERS, "NM_IP4_COMPARE_FLAG_NIS_SERVERS", "nis-servers" }, - { NM_IP4_COMPARE_FLAG_NIS_DOMAIN, "NM_IP4_COMPARE_FLAG_NIS_DOMAIN", "nis-domain" }, - { NM_IP4_COMPARE_FLAG_ALL, "NM_IP4_COMPARE_FLAG_ALL", "all" }, + { NM_BOND_ERROR_CONNECTION_NOT_BOND, "NM_BOND_ERROR_CONNECTION_NOT_BOND", "ConnectionNotBond" }, + { NM_BOND_ERROR_CONNECTION_INVALID, "NM_BOND_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, + { NM_BOND_ERROR_CONNECTION_INCOMPATIBLE, "NM_BOND_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, { 0, NULL, NULL } }; GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMIP4ConfigCompareFlags"), values); + g_enum_register_static (g_intern_static_string ("NMBondError"), values); g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); } return g_define_type_id__volatile; } GType -nm_bond_error_get_type (void) +nm_adsl_error_get_type (void) { static volatile gsize g_define_type_id__volatile = 0; if (g_once_init_enter (&g_define_type_id__volatile)) { static const GEnumValue values[] = { - { NM_BOND_ERROR_CONNECTION_NOT_BOND, "NM_BOND_ERROR_CONNECTION_NOT_BOND", "ConnectionNotBond" }, - { NM_BOND_ERROR_CONNECTION_INVALID, "NM_BOND_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, - { NM_BOND_ERROR_CONNECTION_INCOMPATIBLE, "NM_BOND_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, + { NM_ADSL_ERROR_CONNECTION_NOT_ADSL, "NM_ADSL_ERROR_CONNECTION_NOT_ADSL", "not-adsl" }, + { NM_ADSL_ERROR_CONNECTION_INVALID, "NM_ADSL_ERROR_CONNECTION_INVALID", "invalid" }, + { NM_ADSL_ERROR_CONNECTION_INCOMPATIBLE, "NM_ADSL_ERROR_CONNECTION_INCOMPATIBLE", "incompatible" }, { 0, NULL, NULL } }; GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMBondError"), values); + g_enum_register_static (g_intern_static_string ("NMAdslError"), values); g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); } @@ -512,6 +515,26 @@ nm_netlink_monitor_error_get_type (void) return g_define_type_id__volatile; } GType +nm_ethernet_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_ETHERNET_ERROR_CONNECTION_NOT_WIRED, "NM_ETHERNET_ERROR_CONNECTION_NOT_WIRED", "ConnectionNotWired" }, + { NM_ETHERNET_ERROR_CONNECTION_INVALID, "NM_ETHERNET_ERROR_CONNECTION_INVALID", "ConnectionInvalid" }, + { NM_ETHERNET_ERROR_CONNECTION_INCOMPATIBLE, "NM_ETHERNET_ERROR_CONNECTION_INCOMPATIBLE", "ConnectionIncompatible" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMEthernetError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType nm_logging_error_get_type (void) { static volatile gsize g_define_type_id__volatile = 0; @@ -593,6 +616,25 @@ nm_vpn_manager_error_get_type (void) return g_define_type_id__volatile; } GType +nm_dhcp_manager_error_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) + { + static const GEnumValue values[] = { + { NM_DHCP_MANAGER_ERROR_BAD_CLIENT, "NM_DHCP_MANAGER_ERROR_BAD_CLIENT", "BadClient" }, + { NM_DHCP_MANAGER_ERROR_INTERNAL, "NM_DHCP_MANAGER_ERROR_INTERNAL", "InternalError" }, + { 0, NULL, NULL } + }; + GType g_define_type_id = + g_enum_register_static (g_intern_static_string ("NMDHCPManagerError"), values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + + return g_define_type_id__volatile; +} +GType nm_dhcp_state_get_type (void) { static volatile gsize g_define_type_id__volatile = 0; @@ -635,25 +677,6 @@ nm_dhcp_state_get_type (void) return g_define_type_id__volatile; } GType -nm_dhcp_manager_error_get_type (void) -{ - static volatile gsize g_define_type_id__volatile = 0; - - if (g_once_init_enter (&g_define_type_id__volatile)) - { - static const GEnumValue values[] = { - { NM_DHCP_MANAGER_ERROR_BAD_CLIENT, "NM_DHCP_MANAGER_ERROR_BAD_CLIENT", "BadClient" }, - { NM_DHCP_MANAGER_ERROR_INTERNAL, "NM_DHCP_MANAGER_ERROR_INTERNAL", "InternalError" }, - { 0, NULL, NULL } - }; - GType g_define_type_id = - g_enum_register_static (g_intern_static_string ("NMDHCPManagerError"), values); - g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); - } - - return g_define_type_id__volatile; -} -GType nm_opt_type_get_type (void) { static volatile gsize g_define_type_id__volatile = 0; diff --git a/src/generated/nm-enum-types.h b/src/generated/nm-enum-types.h index 324dbf6a..608eaad6 100644 --- a/src/generated/nm-enum-types.h +++ b/src/generated/nm-enum-types.h @@ -9,8 +9,8 @@ #include <glib-object.h> G_BEGIN_DECLS -GType nm_vlan_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_VLAN_ERROR (nm_vlan_error_get_type ()) +GType nm_ip4_config_compare_flags_get_type (void) G_GNUC_CONST; +#define NM_TYPE_IP4_CONFIG_COMPARE_FLAGS (nm_ip4_config_compare_flags_get_type ()) GType nm_olpc_mesh_error_get_type (void) G_GNUC_CONST; #define NM_TYPE_OLPC_MESH_ERROR (nm_olpc_mesh_error_get_type ()) GType nm_device_error_get_type (void) G_GNUC_CONST; @@ -19,16 +19,16 @@ GType nm_rf_kill_state_get_type (void) G_GNUC_CONST; #define NM_TYPE_RF_KILL_STATE (nm_rf_kill_state_get_type ()) GType nm_rf_kill_type_get_type (void) G_GNUC_CONST; #define NM_TYPE_RF_KILL_TYPE (nm_rf_kill_type_get_type ()) -GType nm_ethernet_error_get_type (void) G_GNUC_CONST; -#define NM_TYPE_ETHERNET_ERROR (nm_ethernet_error_get_type ()) +GType nm_vlan_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_VLAN_ERROR (nm_vlan_error_get_type ()) GType nm_bt_error_get_type (void) G_GNUC_CONST; #define NM_TYPE_BT_ERROR (nm_bt_error_get_type ()) GType nm_wifi_error_get_type (void) G_GNUC_CONST; #define NM_TYPE_WIFI_ERROR (nm_wifi_error_get_type ()) -GType nm_ip4_config_compare_flags_get_type (void) G_GNUC_CONST; -#define NM_TYPE_IP4_CONFIG_COMPARE_FLAGS (nm_ip4_config_compare_flags_get_type ()) GType nm_bond_error_get_type (void) G_GNUC_CONST; #define NM_TYPE_BOND_ERROR (nm_bond_error_get_type ()) +GType nm_adsl_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_ADSL_ERROR (nm_adsl_error_get_type ()) GType nm_manager_error_get_type (void) G_GNUC_CONST; #define NM_TYPE_MANAGER_ERROR (nm_manager_error_get_type ()) GType nm_act_request_dependency_result_get_type (void) G_GNUC_CONST; @@ -47,6 +47,8 @@ GType nm_nm_nl_prop_get_type (void) G_GNUC_CONST; #define NM_TYPE_NM_NL_PROP (nm_nm_nl_prop_get_type ()) GType nm_netlink_monitor_error_get_type (void) G_GNUC_CONST; #define NM_TYPE_NETLINK_MONITOR_ERROR (nm_netlink_monitor_error_get_type ()) +GType nm_ethernet_error_get_type (void) G_GNUC_CONST; +#define NM_TYPE_ETHERNET_ERROR (nm_ethernet_error_get_type ()) GType nm_logging_error_get_type (void) G_GNUC_CONST; #define NM_TYPE_LOGGING_ERROR (nm_logging_error_get_type ()) GType nm_dns_manager_error_get_type (void) G_GNUC_CONST; @@ -55,10 +57,10 @@ GType nm_dns_ip_config_type_get_type (void) G_GNUC_CONST; #define NM_TYPE_DNS_IP_CONFIG_TYPE (nm_dns_ip_config_type_get_type ()) GType nm_vpn_manager_error_get_type (void) G_GNUC_CONST; #define NM_TYPE_VPN_MANAGER_ERROR (nm_vpn_manager_error_get_type ()) -GType nm_dhcp_state_get_type (void) G_GNUC_CONST; -#define NM_TYPE_DHCP_STATE (nm_dhcp_state_get_type ()) GType nm_dhcp_manager_error_get_type (void) G_GNUC_CONST; #define NM_TYPE_DHCP_MANAGER_ERROR (nm_dhcp_manager_error_get_type ()) +GType nm_dhcp_state_get_type (void) G_GNUC_CONST; +#define NM_TYPE_DHCP_STATE (nm_dhcp_state_get_type ()) GType nm_opt_type_get_type (void) G_GNUC_CONST; #define NM_TYPE_OPT_TYPE (nm_opt_type_get_type ()) GType nm_ppp_status_get_type (void) G_GNUC_CONST; diff --git a/src/generated/nm-marshal.c b/src/generated/nm-marshal.c index 4ba973af..e3d39724 100644 --- a/src/generated/nm-marshal.c +++ b/src/generated/nm-marshal.c @@ -5,7 +5,7 @@ #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_char (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) @@ -163,7 +163,44 @@ _nm_marshal_VOID__INT_UINT_BOOLEAN (GClosure *closure, data2); } -/* VOID:OBJECT,STRING (nm-marshal.list:4) */ +/* VOID:OBJECT,OBJECT (nm-marshal.list:4) */ +void +_nm_marshal_VOID__OBJECT_OBJECT (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__OBJECT_OBJECT) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer data2); + register GMarshalFunc_VOID__OBJECT_OBJECT callback; + register GCClosure *cc = (GCClosure*) closure; + register 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__OBJECT_OBJECT) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_object (param_values + 1), + g_marshal_value_peek_object (param_values + 2), + data2); +} + +/* VOID:OBJECT,STRING (nm-marshal.list:5) */ void _nm_marshal_VOID__OBJECT_STRING (GClosure *closure, GValue *return_value G_GNUC_UNUSED, @@ -200,25 +237,26 @@ _nm_marshal_VOID__OBJECT_STRING (GClosure *closure, data2); } -/* VOID:OBJECT,UINT,UINT (nm-marshal.list:5) */ +/* VOID:OBJECT,UINT,UINT,UINT (nm-marshal.list:6) */ void -_nm_marshal_VOID__OBJECT_UINT_UINT (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) +_nm_marshal_VOID__OBJECT_UINT_UINT_UINT (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__OBJECT_UINT_UINT) (gpointer data1, - gpointer arg_1, - guint arg_2, - guint arg_3, - gpointer data2); - register GMarshalFunc_VOID__OBJECT_UINT_UINT callback; + typedef void (*GMarshalFunc_VOID__OBJECT_UINT_UINT_UINT) (gpointer data1, + gpointer arg_1, + guint arg_2, + guint arg_3, + guint arg_4, + gpointer data2); + register GMarshalFunc_VOID__OBJECT_UINT_UINT_UINT callback; register GCClosure *cc = (GCClosure*) closure; register gpointer data1, data2; - g_return_if_fail (n_param_values == 4); + g_return_if_fail (n_param_values == 5); if (G_CCLOSURE_SWAP_DATA (closure)) { @@ -230,18 +268,19 @@ _nm_marshal_VOID__OBJECT_UINT_UINT (GClosure *closure, data1 = g_value_peek_pointer (param_values + 0); data2 = closure->data; } - callback = (GMarshalFunc_VOID__OBJECT_UINT_UINT) (marshal_data ? marshal_data : cc->callback); + callback = (GMarshalFunc_VOID__OBJECT_UINT_UINT_UINT) (marshal_data ? marshal_data : cc->callback); callback (data1, g_marshal_value_peek_object (param_values + 1), g_marshal_value_peek_uint (param_values + 2), g_marshal_value_peek_uint (param_values + 3), + g_marshal_value_peek_uint (param_values + 4), data2); } -/* VOID:POINTER (nm-marshal.list:6) */ +/* VOID:POINTER (nm-marshal.list:7) */ -/* VOID:POINTER,POINTER,POINTER,POINTER,INT (nm-marshal.list:7) */ +/* VOID:POINTER,POINTER,POINTER,POINTER,INT (nm-marshal.list:8) */ void _nm_marshal_VOID__POINTER_POINTER_POINTER_POINTER_INT (GClosure *closure, GValue *return_value G_GNUC_UNUSED, @@ -284,7 +323,7 @@ _nm_marshal_VOID__POINTER_POINTER_POINTER_POINTER_INT (GClosure *closure, data2); } -/* VOID:POINTER,STRING (nm-marshal.list:8) */ +/* VOID:POINTER,STRING (nm-marshal.list:9) */ void _nm_marshal_VOID__POINTER_STRING (GClosure *closure, GValue *return_value G_GNUC_UNUSED, @@ -321,7 +360,50 @@ _nm_marshal_VOID__POINTER_STRING (GClosure *closure, data2); } -/* VOID:STRING,BOXED (nm-marshal.list:9) */ +/* VOID:POINTER,STRING,BOOLEAN,POINTER,POINTER (nm-marshal.list:10) */ +void +_nm_marshal_VOID__POINTER_STRING_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 void (*GMarshalFunc_VOID__POINTER_STRING_BOOLEAN_POINTER_POINTER) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gboolean arg_3, + gpointer arg_4, + gpointer arg_5, + gpointer data2); + register GMarshalFunc_VOID__POINTER_STRING_BOOLEAN_POINTER_POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 6); + + 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__POINTER_STRING_BOOLEAN_POINTER_POINTER) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + g_marshal_value_peek_pointer (param_values + 1), + g_marshal_value_peek_string (param_values + 2), + g_marshal_value_peek_boolean (param_values + 3), + g_marshal_value_peek_pointer (param_values + 4), + g_marshal_value_peek_pointer (param_values + 5), + data2); +} + +/* VOID:STRING,BOXED (nm-marshal.list:11) */ void _nm_marshal_VOID__STRING_BOXED (GClosure *closure, GValue *return_value G_GNUC_UNUSED, @@ -358,7 +440,7 @@ _nm_marshal_VOID__STRING_BOXED (GClosure *closure, data2); } -/* VOID:STRING,BOXED,BOXED (nm-marshal.list:10) */ +/* VOID:STRING,BOXED,BOXED (nm-marshal.list:12) */ void _nm_marshal_VOID__STRING_BOXED_BOXED (GClosure *closure, GValue *return_value G_GNUC_UNUSED, @@ -397,7 +479,7 @@ _nm_marshal_VOID__STRING_BOXED_BOXED (GClosure *closure, data2); } -/* VOID:STRING,OBJECT (nm-marshal.list:11) */ +/* VOID:STRING,OBJECT (nm-marshal.list:13) */ void _nm_marshal_VOID__STRING_OBJECT (GClosure *closure, GValue *return_value G_GNUC_UNUSED, @@ -434,7 +516,7 @@ _nm_marshal_VOID__STRING_OBJECT (GClosure *closure, data2); } -/* VOID:STRING,OBJECT,POINTER (nm-marshal.list:12) */ +/* VOID:STRING,OBJECT,POINTER (nm-marshal.list:14) */ void _nm_marshal_VOID__STRING_OBJECT_POINTER (GClosure *closure, GValue *return_value G_GNUC_UNUSED, @@ -473,7 +555,7 @@ _nm_marshal_VOID__STRING_OBJECT_POINTER (GClosure *closure, data2); } -/* VOID:STRING,POINTER (nm-marshal.list:13) */ +/* VOID:STRING,POINTER (nm-marshal.list:15) */ void _nm_marshal_VOID__STRING_POINTER (GClosure *closure, GValue *return_value G_GNUC_UNUSED, @@ -510,7 +592,7 @@ _nm_marshal_VOID__STRING_POINTER (GClosure *closure, data2); } -/* VOID:STRING,STRING (nm-marshal.list:14) */ +/* VOID:STRING,STRING (nm-marshal.list:16) */ void _nm_marshal_VOID__STRING_STRING (GClosure *closure, GValue *return_value G_GNUC_UNUSED, @@ -547,7 +629,7 @@ _nm_marshal_VOID__STRING_STRING (GClosure *closure, data2); } -/* VOID:STRING,STRING,STRING (nm-marshal.list:15) */ +/* VOID:STRING,STRING,STRING (nm-marshal.list:17) */ void _nm_marshal_VOID__STRING_STRING_STRING (GClosure *closure, GValue *return_value G_GNUC_UNUSED, @@ -586,7 +668,7 @@ _nm_marshal_VOID__STRING_STRING_STRING (GClosure *closure, data2); } -/* VOID:STRING,STRING,STRING,UINT (nm-marshal.list:16) */ +/* VOID:STRING,STRING,STRING,UINT (nm-marshal.list:18) */ void _nm_marshal_VOID__STRING_STRING_STRING_UINT (GClosure *closure, GValue *return_value G_GNUC_UNUSED, @@ -627,7 +709,7 @@ _nm_marshal_VOID__STRING_STRING_STRING_UINT (GClosure *closure, data2); } -/* VOID:UINT,UINT (nm-marshal.list:17) */ +/* VOID:UINT,UINT (nm-marshal.list:19) */ void _nm_marshal_VOID__UINT_UINT (GClosure *closure, GValue *return_value G_GNUC_UNUSED, @@ -664,7 +746,7 @@ _nm_marshal_VOID__UINT_UINT (GClosure *closure, data2); } -/* VOID:UINT,UINT,UINT (nm-marshal.list:18) */ +/* VOID:UINT,UINT,UINT (nm-marshal.list:20) */ void _nm_marshal_VOID__UINT_UINT_UINT (GClosure *closure, GValue *return_value G_GNUC_UNUSED, diff --git a/src/generated/nm-marshal.h b/src/generated/nm-marshal.h index 9f9ea6ad..61ef6479 100644 --- a/src/generated/nm-marshal.h +++ b/src/generated/nm-marshal.h @@ -30,7 +30,15 @@ extern void _nm_marshal_VOID__INT_UINT_BOOLEAN (GClosure *closure, gpointer invocation_hint, gpointer marshal_data); -/* VOID:OBJECT,STRING (nm-marshal.list:4) */ +/* VOID:OBJECT,OBJECT (nm-marshal.list:4) */ +extern void _nm_marshal_VOID__OBJECT_OBJECT (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +/* VOID:OBJECT,STRING (nm-marshal.list:5) */ extern void _nm_marshal_VOID__OBJECT_STRING (GClosure *closure, GValue *return_value, guint n_param_values, @@ -38,18 +46,18 @@ extern void _nm_marshal_VOID__OBJECT_STRING (GClosure *closure, gpointer invocation_hint, gpointer marshal_data); -/* VOID:OBJECT,UINT,UINT (nm-marshal.list:5) */ -extern void _nm_marshal_VOID__OBJECT_UINT_UINT (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data); +/* VOID:OBJECT,UINT,UINT,UINT (nm-marshal.list:6) */ +extern void _nm_marshal_VOID__OBJECT_UINT_UINT_UINT (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); -/* VOID:POINTER (nm-marshal.list:6) */ +/* VOID:POINTER (nm-marshal.list:7) */ #define _nm_marshal_VOID__POINTER g_cclosure_marshal_VOID__POINTER -/* VOID:POINTER,POINTER,POINTER,POINTER,INT (nm-marshal.list:7) */ +/* VOID:POINTER,POINTER,POINTER,POINTER,INT (nm-marshal.list:8) */ extern void _nm_marshal_VOID__POINTER_POINTER_POINTER_POINTER_INT (GClosure *closure, GValue *return_value, guint n_param_values, @@ -57,7 +65,7 @@ extern void _nm_marshal_VOID__POINTER_POINTER_POINTER_POINTER_INT (GClosure gpointer invocation_hint, gpointer marshal_data); -/* VOID:POINTER,STRING (nm-marshal.list:8) */ +/* VOID:POINTER,STRING (nm-marshal.list:9) */ extern void _nm_marshal_VOID__POINTER_STRING (GClosure *closure, GValue *return_value, guint n_param_values, @@ -65,7 +73,15 @@ extern void _nm_marshal_VOID__POINTER_STRING (GClosure *closure, gpointer invocation_hint, gpointer marshal_data); -/* VOID:STRING,BOXED (nm-marshal.list:9) */ +/* VOID:POINTER,STRING,BOOLEAN,POINTER,POINTER (nm-marshal.list:10) */ +extern void _nm_marshal_VOID__POINTER_STRING_BOOLEAN_POINTER_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +/* VOID:STRING,BOXED (nm-marshal.list:11) */ extern void _nm_marshal_VOID__STRING_BOXED (GClosure *closure, GValue *return_value, guint n_param_values, @@ -73,7 +89,7 @@ extern void _nm_marshal_VOID__STRING_BOXED (GClosure *closure, gpointer invocation_hint, gpointer marshal_data); -/* VOID:STRING,BOXED,BOXED (nm-marshal.list:10) */ +/* VOID:STRING,BOXED,BOXED (nm-marshal.list:12) */ extern void _nm_marshal_VOID__STRING_BOXED_BOXED (GClosure *closure, GValue *return_value, guint n_param_values, @@ -81,7 +97,7 @@ extern void _nm_marshal_VOID__STRING_BOXED_BOXED (GClosure *closure, gpointer invocation_hint, gpointer marshal_data); -/* VOID:STRING,OBJECT (nm-marshal.list:11) */ +/* VOID:STRING,OBJECT (nm-marshal.list:13) */ extern void _nm_marshal_VOID__STRING_OBJECT (GClosure *closure, GValue *return_value, guint n_param_values, @@ -89,7 +105,7 @@ extern void _nm_marshal_VOID__STRING_OBJECT (GClosure *closure, gpointer invocation_hint, gpointer marshal_data); -/* VOID:STRING,OBJECT,POINTER (nm-marshal.list:12) */ +/* VOID:STRING,OBJECT,POINTER (nm-marshal.list:14) */ extern void _nm_marshal_VOID__STRING_OBJECT_POINTER (GClosure *closure, GValue *return_value, guint n_param_values, @@ -97,7 +113,7 @@ extern void _nm_marshal_VOID__STRING_OBJECT_POINTER (GClosure *closure, gpointer invocation_hint, gpointer marshal_data); -/* VOID:STRING,POINTER (nm-marshal.list:13) */ +/* VOID:STRING,POINTER (nm-marshal.list:15) */ extern void _nm_marshal_VOID__STRING_POINTER (GClosure *closure, GValue *return_value, guint n_param_values, @@ -105,7 +121,7 @@ extern void _nm_marshal_VOID__STRING_POINTER (GClosure *closure, gpointer invocation_hint, gpointer marshal_data); -/* VOID:STRING,STRING (nm-marshal.list:14) */ +/* VOID:STRING,STRING (nm-marshal.list:16) */ extern void _nm_marshal_VOID__STRING_STRING (GClosure *closure, GValue *return_value, guint n_param_values, @@ -113,7 +129,7 @@ extern void _nm_marshal_VOID__STRING_STRING (GClosure *closure, gpointer invocation_hint, gpointer marshal_data); -/* VOID:STRING,STRING,STRING (nm-marshal.list:15) */ +/* VOID:STRING,STRING,STRING (nm-marshal.list:17) */ extern void _nm_marshal_VOID__STRING_STRING_STRING (GClosure *closure, GValue *return_value, guint n_param_values, @@ -121,7 +137,7 @@ extern void _nm_marshal_VOID__STRING_STRING_STRING (GClosure *closure, gpointer invocation_hint, gpointer marshal_data); -/* VOID:STRING,STRING,STRING,UINT (nm-marshal.list:16) */ +/* VOID:STRING,STRING,STRING,UINT (nm-marshal.list:18) */ extern void _nm_marshal_VOID__STRING_STRING_STRING_UINT (GClosure *closure, GValue *return_value, guint n_param_values, @@ -129,7 +145,7 @@ extern void _nm_marshal_VOID__STRING_STRING_STRING_UINT (GClosure *closure, gpointer invocation_hint, gpointer marshal_data); -/* VOID:UINT,UINT (nm-marshal.list:17) */ +/* VOID:UINT,UINT (nm-marshal.list:19) */ extern void _nm_marshal_VOID__UINT_UINT (GClosure *closure, GValue *return_value, guint n_param_values, @@ -137,7 +153,7 @@ extern void _nm_marshal_VOID__UINT_UINT (GClosure *closure, gpointer invocation_hint, gpointer marshal_data); -/* VOID:UINT,UINT,UINT (nm-marshal.list:18) */ +/* VOID:UINT,UINT,UINT (nm-marshal.list:20) */ extern void _nm_marshal_VOID__UINT_UINT_UINT (GClosure *closure, GValue *return_value, guint n_param_values, diff --git a/src/ip6-manager/Makefile.in b/src/ip6-manager/Makefile.in index 59c2e7b4..d0d3129b 100644 --- a/src/ip6-manager/Makefile.in +++ b/src/ip6-manager/Makefile.in @@ -47,7 +47,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -169,6 +169,10 @@ 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@ @@ -264,6 +268,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -302,6 +309,8 @@ 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@ diff --git a/src/ip6-manager/nm-ip6-manager.c b/src/ip6-manager/nm-ip6-manager.c index 99f85ede..e452c18e 100644 --- a/src/ip6-manager/nm-ip6-manager.c +++ b/src/ip6-manager/nm-ip6-manager.c @@ -18,8 +18,12 @@ * Copyright (C) 2009 - 2010 Red Hat, Inc. */ +#define _GNU_SOURCE /* for struct in6_pktinfo */ + #include <errno.h> +#include <unistd.h> #include <netinet/icmp6.h> +#include <netinet/in.h> #include <netlink/route/addr.h> #include <netlink/route/rtnl.h> @@ -32,6 +36,7 @@ #include "NetworkManagerUtils.h" #include "nm-marshal.h" #include "nm-logging.h" +#include "nm-utils.h" /* Pre-DHCP addrconf timeout, in seconds */ #define NM_IP6_TIMEOUT 20 @@ -89,6 +94,10 @@ typedef struct { char *iface; int ifindex; + gboolean has_linklocal; + gboolean has_nonlinklocal; + guint dhcp_opts; + char *disable_ip6_path; gboolean disable_ip6_save_valid; gint32 disable_ip6_save; @@ -102,9 +111,13 @@ typedef struct { GArray *rdnss_servers; guint rdnss_timeout_id; + guint32 rdnss_timeout; GArray *dnssl_domains; guint dnssl_timeout_id; + guint32 dnssl_timeout; + + time_t last_solicitation; guint ip6flags_poll_id; @@ -209,11 +222,221 @@ nm_ip6_manager_get_device (NMIP6Manager *manager, int ifindex) return g_hash_table_lookup (priv->devices, GINT_TO_POINTER (ifindex)); } +static int +get_hwaddr (int ifindex, guint8 *buf) +{ + struct rtnl_link *lk; + struct nl_addr *addr; + int len; + + lk = nm_netlink_index_to_rtnl_link (ifindex); + if (!lk) + return -1; + + addr = rtnl_link_get_addr (lk); + len = nl_addr_get_len (addr); + if (len > NM_UTILS_HWADDR_LEN_MAX) + len = -1; + else + memcpy (buf, nl_addr_get_binary_addr (addr), len); + + rtnl_link_put (lk); + return len; +} + +static void +device_send_router_solicitation (NMIP6Device *device, const char *why) +{ + int sock, hops; + struct sockaddr_in6 sin6; + struct nd_router_solicit rs; + struct nd_opt_hdr lladdr_hdr; + guint8 hwaddr[NM_UTILS_HWADDR_LEN_MAX + 7]; + int hwaddr_len; + static const guint8 local_routers_addr[] = + { 0xFF, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 }; + struct msghdr mhdr; + struct iovec iov[3]; + struct cmsghdr *cmsg; + struct in6_pktinfo *ipi; + guint8 cmsgbuf[128]; + int cmsglen = 0; + time_t now; + + now = time (NULL); + if (device->last_solicitation > now - 5) + return; + device->last_solicitation = now; + + nm_log_dbg (LOGD_IP6, "(%s): %s: sending router solicitation", + device->iface, why); + + sock = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); + if (sock < 0) { + nm_log_dbg (LOGD_IP6, "(%s): could not create ICMPv6 socket: %s", + device->iface, g_strerror (errno)); + return; + } + + hops = 255; + if ( setsockopt (sock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hops, sizeof (hops)) == -1 + || setsockopt (sock, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hops, sizeof (hops)) == -1) { + nm_log_dbg (LOGD_IP6, "(%s): could not set hop limit on ICMPv6 socket: %s", + device->iface, g_strerror (errno)); + close (sock); + return; + } + + /* Use the "all link-local routers" multicast address */ + memset (&sin6, 0, sizeof (sin6)); + memcpy (&sin6.sin6_addr, local_routers_addr, sizeof (sin6.sin6_addr)); + mhdr.msg_name = &sin6; + mhdr.msg_namelen = sizeof (sin6); + + /* Build the router solicitation */ + mhdr.msg_iov = iov; + memset (&rs, 0, sizeof (rs)); + rs.nd_rs_type = ND_ROUTER_SOLICIT; + iov[0].iov_len = sizeof (rs); + iov[0].iov_base = &rs; + + memset (hwaddr, 0, sizeof (hwaddr)); + hwaddr_len = get_hwaddr (device->ifindex, hwaddr); + + if (hwaddr_len > 0) { + memset (&lladdr_hdr, 0, sizeof (lladdr_hdr)); + lladdr_hdr.nd_opt_type = ND_OPT_SOURCE_LINKADDR; + lladdr_hdr.nd_opt_len = (sizeof (lladdr_hdr) + hwaddr_len + 7) % 8; + iov[1].iov_len = sizeof (lladdr_hdr); + iov[1].iov_base = &lladdr_hdr; + + iov[2].iov_len = (lladdr_hdr.nd_opt_len * 8) - 2; + iov[2].iov_base = hwaddr; + + mhdr.msg_iovlen = 3; + } else + mhdr.msg_iovlen = 1; + + /* Force this to go on the right device */ + memset (cmsgbuf, 0, sizeof (cmsgbuf)); + cmsg = (struct cmsghdr *) cmsgbuf; + cmsglen = CMSG_SPACE (sizeof (*ipi)); + cmsg->cmsg_len = CMSG_LEN (sizeof (*ipi)); + cmsg->cmsg_level = SOL_IPV6; + cmsg->cmsg_type = IPV6_PKTINFO; + ipi = (struct in6_pktinfo *) CMSG_DATA (cmsg); + ipi->ipi6_ifindex = device->ifindex; + + mhdr.msg_control = cmsg; + mhdr.msg_controllen = cmsglen; + + if (sendmsg (sock, &mhdr, 0) == -1) { + nm_log_dbg (LOGD_IP6, "(%s): could not send router solicitation: %s", + device->iface, g_strerror (errno)); + } + + close (sock); +} + +static char * +device_get_iface (NMIP6Device *device) +{ + return device ? device->iface : "unknown"; +} + +static const char * +state_to_string (NMIP6DeviceState state) +{ + switch (state) { + case NM_IP6_DEVICE_UNCONFIGURED: + return "unconfigured"; + case NM_IP6_DEVICE_GOT_LINK_LOCAL: + return "got-link-local"; + case NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT: + return "got-ra"; + case NM_IP6_DEVICE_GOT_ADDRESS: + return "got-address"; + case NM_IP6_DEVICE_TIMED_OUT: + return "timed-out"; + default: + return "unknown"; + } +} + +static gboolean +device_set_state (NMIP6Device *device, NMIP6DeviceState state) +{ + NMIP6DeviceState old_state; + + g_return_val_if_fail (device != NULL, FALSE); + + if (state == device->state) + return FALSE; + + old_state = device->state; + device->state = state; + nm_log_dbg (LOGD_IP6, "(%s) IP6 device state: %s -> %s", + device_get_iface (device), + state_to_string (old_state), + state_to_string (state)); + return TRUE; +} + +static char * +ra_flags_to_string (guint32 ra_flags) +{ + GString *s = g_string_sized_new (20); + + g_string_append (s, " ("); + if (ra_flags & IF_RS_SENT) + g_string_append_c (s, 'S'); + + if (ra_flags & IF_RA_RCVD) + g_string_append_c (s, 'R'); + + if (ra_flags & IF_RA_MANAGED) + g_string_append_c (s, 'M'); + + if (ra_flags & IF_RA_OTHERCONF) + g_string_append_c (s, 'O'); + + g_string_append_c (s, ')'); + return g_string_free (s, FALSE); +} + +static gboolean +device_set_ra_flags (NMIP6Device *device, guint ra_flags) +{ + guint old_ra_flags; + gchar *ra_flags_str, *old_ra_flags_str; + + g_return_val_if_fail (device != NULL, FALSE); + + if (ra_flags == device->ra_flags) + return FALSE; + + old_ra_flags = device->ra_flags; + device->ra_flags = ra_flags; + + if (nm_logging_level_enabled (LOGL_DEBUG)) { + ra_flags_str = ra_flags_to_string (ra_flags); + old_ra_flags_str = ra_flags_to_string (old_ra_flags); + nm_log_dbg (LOGD_IP6, "(%s) IP6 device ra_flags: 0x%08x %s -> 0x%08x %s", + device_get_iface (device), + old_ra_flags, old_ra_flags_str, + ra_flags, ra_flags_str); + g_free (ra_flags_str); + g_free (old_ra_flags_str); + } + + return TRUE; +} + /******************************************************************/ typedef struct { NMIP6Device *device; - guint dhcp_opts; gboolean success; } CallbackInfo; @@ -238,14 +461,14 @@ finish_addrconf (gpointer user_data) /* And tell listeners that addrconf is complete */ if (info->success) { g_signal_emit (manager, signals[ADDRCONF_COMPLETE], 0, - ifindex, info->dhcp_opts, TRUE); + ifindex, device->dhcp_opts, TRUE); } else { nm_log_info (LOGD_IP6, "(%s): IP6 addrconf timed out or failed.", device->iface); nm_ip6_manager_cancel_addrconf (manager, ifindex); g_signal_emit (manager, signals[ADDRCONF_COMPLETE], 0, - ifindex, info->dhcp_opts, FALSE); + ifindex, device->dhcp_opts, FALSE); } return FALSE; @@ -261,7 +484,7 @@ emit_config_changed (gpointer user_data) device->config_changed_id = 0; g_signal_emit (manager, signals[CONFIG_CHANGED], 0, device->ifindex, - info->dhcp_opts, + device->dhcp_opts, info->success); return FALSE; } @@ -272,7 +495,7 @@ static gboolean rdnss_expired (gpointer user_data) { NMIP6Device *device = user_data; - CallbackInfo info = { device, IP6_DHCP_OPT_NONE, FALSE }; + CallbackInfo info = { device, FALSE }; nm_log_dbg (LOGD_IP6, "(%s): IPv6 RDNSS information expired", device->iface); @@ -282,6 +505,22 @@ rdnss_expired (gpointer user_data) return FALSE; } +static gboolean +rdnss_needs_refresh (gpointer user_data) +{ + NMIP6Device *device = user_data; + gchar *msg; + + msg = g_strdup_printf ("IPv6 RDNSS due to expire in %d seconds", + device->rdnss_timeout); + device_send_router_solicitation (device, msg); + g_free (msg); + + set_rdnss_timeout (device); + + return FALSE; +} + static void set_rdnss_timeout (NMIP6Device *device) { @@ -320,9 +559,23 @@ set_rdnss_timeout (NMIP6Device *device) } if (expires) { - device->rdnss_timeout_id = g_timeout_add_seconds (MIN (expires - now, G_MAXUINT32 - 1), - rdnss_expired, - device); + gchar *msg; + + device->rdnss_timeout = MIN (expires - now, G_MAXUINT32 - 1); + + if (device->rdnss_timeout <= 5) { + msg = g_strdup_printf ("IPv6 RDNSS about to expire in %d seconds", + device->rdnss_timeout); + device_send_router_solicitation (device, msg); + g_free (msg); + device->rdnss_timeout_id = g_timeout_add_seconds (device->rdnss_timeout, + rdnss_expired, + device); + } else { + device->rdnss_timeout_id = g_timeout_add_seconds (device->rdnss_timeout / 2, + rdnss_needs_refresh, + device); + } } } @@ -332,7 +585,7 @@ static gboolean dnssl_expired (gpointer user_data) { NMIP6Device *device = user_data; - CallbackInfo info = { device, IP6_DHCP_OPT_NONE, FALSE }; + CallbackInfo info = { device, FALSE }; nm_log_dbg (LOGD_IP6, "(%s): IPv6 DNSSL information expired", device->iface); @@ -342,6 +595,22 @@ dnssl_expired (gpointer user_data) return FALSE; } +static gboolean +dnssl_needs_refresh (gpointer user_data) +{ + NMIP6Device *device = user_data; + gchar *msg; + + msg = g_strdup_printf ("IPv6 DNSSL due to expire in %d seconds", + device->dnssl_timeout); + device_send_router_solicitation (device, msg); + g_free (msg); + + set_dnssl_timeout (device); + + return FALSE; +} + static void set_dnssl_timeout (NMIP6Device *device) { @@ -376,59 +645,49 @@ set_dnssl_timeout (NMIP6Device *device) } if (expires) { - device->dnssl_timeout_id = g_timeout_add_seconds (MIN (expires - now, G_MAXUINT32 - 1), - dnssl_expired, - device); + gchar *msg; + + device->dnssl_timeout = MIN (expires - now, G_MAXUINT32 - 1); + + if (device->dnssl_timeout <= 5) { + msg = g_strdup_printf ("IPv6 DNSSL about to expire in %d seconds", + device->dnssl_timeout); + device_send_router_solicitation (device, msg); + g_free (msg); + device->dnssl_timeout_id = g_timeout_add_seconds (device->dnssl_timeout, + dnssl_expired, + device); + } else { + device->dnssl_timeout_id = g_timeout_add_seconds (device->dnssl_timeout / 2, + dnssl_needs_refresh, + device); + } } } static CallbackInfo * -callback_info_new (NMIP6Device *device, guint dhcp_opts, gboolean success) +callback_info_new (NMIP6Device *device, gboolean success) { CallbackInfo *info; info = g_malloc0 (sizeof (CallbackInfo)); info->device = device; - info->dhcp_opts = dhcp_opts; info->success = success; return info; } -static const char * -state_to_string (NMIP6DeviceState state) -{ - switch (state) { - case NM_IP6_DEVICE_UNCONFIGURED: - return "unconfigured"; - case NM_IP6_DEVICE_GOT_LINK_LOCAL: - return "got-link-local"; - case NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT: - return "got-ra"; - case NM_IP6_DEVICE_GOT_ADDRESS: - return "got-address"; - case NM_IP6_DEVICE_TIMED_OUT: - return "timed-out"; - default: - return "unknown"; - } -} - static void -nm_ip6_device_sync_from_netlink (NMIP6Device *device, gboolean config_changed) +check_addresses (NMIP6Device *device) { NMIP6Manager *manager = device->manager; NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager); struct rtnl_addr *rtnladdr; struct nl_addr *nladdr; struct in6_addr *addr; - CallbackInfo *info; - guint dhcp_opts = IP6_DHCP_OPT_NONE; - gboolean found_linklocal = FALSE, found_other = FALSE; - nm_log_dbg (LOGD_IP6, "(%s): syncing with netlink (ra_flags 0x%X) (state/target '%s'/'%s')", - device->iface, device->ra_flags, - state_to_string (device->state), - state_to_string (device->target_state)); + /* Reset address information */ + device->has_linklocal = FALSE; + device->has_nonlinklocal = FALSE; /* Look for any IPv6 addresses the kernel may have set for the device */ for (rtnladdr = (struct rtnl_addr *) nl_cache_get_first (priv->addr_cache); @@ -453,12 +712,12 @@ nm_ip6_device_sync_from_netlink (NMIP6Device *device, gboolean config_changed) if (IN6_IS_ADDR_LINKLOCAL (addr)) { if (device->state == NM_IP6_DEVICE_UNCONFIGURED) - device->state = NM_IP6_DEVICE_GOT_LINK_LOCAL; - found_linklocal = TRUE; + device_set_state (device, NM_IP6_DEVICE_GOT_LINK_LOCAL); + device->has_linklocal = TRUE; } else { if (device->state < NM_IP6_DEVICE_GOT_ADDRESS) - device->state = NM_IP6_DEVICE_GOT_ADDRESS; - found_other = TRUE; + device_set_state (device, NM_IP6_DEVICE_GOT_ADDRESS); + device->has_nonlinklocal = TRUE; } } @@ -466,27 +725,41 @@ nm_ip6_device_sync_from_netlink (NMIP6Device *device, gboolean config_changed) * before in the initial run, but if it goes away later, make sure we * regress from GOT_LINK_LOCAL back to UNCONFIGURED. */ - if ((device->state == NM_IP6_DEVICE_GOT_LINK_LOCAL) && !found_linklocal) - device->state = NM_IP6_DEVICE_UNCONFIGURED; + if ((device->state == NM_IP6_DEVICE_GOT_LINK_LOCAL) && !device->has_linklocal) + device_set_state (device, NM_IP6_DEVICE_UNCONFIGURED); - nm_log_dbg (LOGD_IP6, "(%s): addresses synced (state %s)", - device->iface, state_to_string (device->state)); + nm_log_dbg (LOGD_IP6, "(%s): addresses checked (state %s)", + device->iface, state_to_string (device->state)); +} + +static void +check_ra_flags (NMIP6Device *device) +{ + device->dhcp_opts = IP6_DHCP_OPT_NONE; /* We only care about router advertisements if we want a real IPv6 address */ if ( (device->target_state == NM_IP6_DEVICE_GOT_ADDRESS) && (device->ra_flags & IF_RA_RCVD)) { if (device->state < NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT) - device->state = NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT; + device_set_state (device, NM_IP6_DEVICE_GOT_ROUTER_ADVERTISEMENT); if (device->ra_flags & IF_RA_MANAGED) { - dhcp_opts = IP6_DHCP_OPT_MANAGED; + device->dhcp_opts = IP6_DHCP_OPT_MANAGED; nm_log_dbg (LOGD_IP6, "router advertisement deferred to DHCPv6"); } else if (device->ra_flags & IF_RA_OTHERCONF) { - dhcp_opts = IP6_DHCP_OPT_OTHERCONF; + device->dhcp_opts = IP6_DHCP_OPT_OTHERCONF; nm_log_dbg (LOGD_IP6, "router advertisement requests parallel DHCPv6"); } } + nm_log_dbg (LOGD_IP6, "(%s): router advertisement checked (state %s)", + device->iface, state_to_string (device->state)); +} + +static void +check_addrconf_complete (NMIP6Device *device) +{ + CallbackInfo *info; if (!device->addrconf_complete) { /* Managed mode (ie DHCP only) short-circuits automatic addrconf, so @@ -494,7 +767,7 @@ nm_ip6_device_sync_from_netlink (NMIP6Device *device, gboolean config_changed) * when the RA requests managed mode. */ if ( (device->state >= device->target_state) - || (dhcp_opts == IP6_DHCP_OPT_MANAGED)) { + || (device->dhcp_opts == IP6_DHCP_OPT_MANAGED)) { /* device->finish_addrconf_id may currently be a timeout * rather than an idle, so we remove the existing source. */ @@ -503,15 +776,15 @@ nm_ip6_device_sync_from_netlink (NMIP6Device *device, gboolean config_changed) nm_log_dbg (LOGD_IP6, "(%s): reached target state or Managed-mode requested (state '%s') (dhcp opts 0x%X)", device->iface, state_to_string (device->state), - dhcp_opts); + device->dhcp_opts); - info = callback_info_new (device, dhcp_opts, TRUE); + info = callback_info_new (device, TRUE); device->finish_addrconf_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, finish_addrconf, info, (GDestroyNotify) g_free); } - } else if (config_changed) { + } else { if (!device->config_changed_id) { gboolean success = TRUE; @@ -520,19 +793,35 @@ nm_ip6_device_sync_from_netlink (NMIP6Device *device, gboolean config_changed) */ if ( (device->state == NM_IP6_DEVICE_GOT_ADDRESS) && (device->target_state == NM_IP6_DEVICE_GOT_ADDRESS) - && !found_other) { - nm_log_dbg (LOGD_IP6, "(%s): RA-provided address no longer valid", + && !device->has_nonlinklocal) { + nm_log_dbg (LOGD_IP6, "(%s): RA-provided address no longer found", device->iface); success = FALSE; } - info = callback_info_new (device, dhcp_opts, success); + info = callback_info_new (device, success); device->config_changed_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, emit_config_changed, info, (GDestroyNotify) g_free); } } + + nm_log_dbg (LOGD_IP6, "(%s): dhcp_opts checked (state %s)", + device->iface, state_to_string (device->state)); +} + +static void +nm_ip6_device_sync_from_netlink (NMIP6Device *device) +{ + nm_log_dbg (LOGD_IP6, "(%s): syncing with netlink (ra_flags 0x%X) (state/target '%s'/'%s')", + device->iface, device->ra_flags, + state_to_string (device->state), + state_to_string (device->target_state)); + + check_addresses (device); + check_ra_flags (device); + check_addrconf_complete (device); } static void @@ -544,16 +833,51 @@ ref_object (struct nl_object *obj, void *data) *out = obj; } +static void +dump_address_change (NMIP6Device *device, struct nlmsghdr *hdr, struct rtnl_addr *rtnladdr) +{ + char *event; + struct nl_addr *addr; + char addr_str[40] = "none"; + + event = hdr->nlmsg_type == RTM_NEWADDR ? "new" : "lost"; + addr = rtnl_addr_get_local (rtnladdr); + if (addr) + nl_addr2str (addr, addr_str, 40); + + nm_log_dbg (LOGD_IP6, "(%s) %s address: %s", device_get_iface (device), event, addr_str); +} + +static void +dump_route_change (NMIP6Device *device, struct nlmsghdr *hdr, struct rtnl_route *rtnlroute) +{ + char *event; + struct nl_addr *dst; + char dst_str[40] = "none"; + struct nl_addr *gateway; + char gateway_str[40] = "none"; + + event = hdr->nlmsg_type == RTM_NEWROUTE ? "new" : "lost"; + dst = rtnl_route_get_dst (rtnlroute); + gateway = rtnl_route_get_gateway (rtnlroute); + if (dst) + nl_addr2str (dst, dst_str, 40); + if (gateway) + nl_addr2str (gateway, gateway_str, 40); + + nm_log_dbg (LOGD_IP6, "(%s) %s route: %s via %s",device_get_iface (device), event, dst_str, gateway_str); +} + static NMIP6Device * -process_addr (NMIP6Manager *manager, struct nl_msg *msg) +process_address_change (NMIP6Manager *manager, struct nl_msg *msg) { NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager); NMIP6Device *device; + struct nlmsghdr *hdr; struct rtnl_addr *rtnladdr; int old_size; - nm_log_dbg (LOGD_IP6, "processing netlink new/del address message"); - + hdr = nlmsg_hdr (msg); rtnladdr = NULL; nl_msg_parse (msg, ref_object, &rtnladdr); if (!rtnladdr) { @@ -562,39 +886,34 @@ process_addr (NMIP6Manager *manager, struct nl_msg *msg) } device = nm_ip6_manager_get_device (manager, rtnl_addr_get_ifindex (rtnladdr)); - if (!device) { - nm_log_dbg (LOGD_IP6, "ignoring message for unknown device"); - rtnl_addr_put (rtnladdr); - return NULL; - } old_size = nl_cache_nitems (priv->addr_cache); nl_cache_include (priv->addr_cache, (struct nl_object *)rtnladdr, NULL, NULL); - rtnl_addr_put (rtnladdr); /* The kernel will re-notify us of automatically-added addresses * every time it gets another router advertisement. We only want * to notify higher levels if we actually changed something. */ - if (nl_cache_nitems (priv->addr_cache) == old_size) { - nm_log_dbg (LOGD_IP6, "(%s): address cache unchanged, ignoring message", - device->iface); + nm_log_dbg (LOGD_IP6, "(%s): address cache size: %d -> %d:", + device_get_iface (device), old_size, nl_cache_nitems (priv->addr_cache)); + dump_address_change (device, hdr, rtnladdr); + rtnl_addr_put (rtnladdr); + if (nl_cache_nitems (priv->addr_cache) == old_size) return NULL; - } return device; } static NMIP6Device * -process_route (NMIP6Manager *manager, struct nl_msg *msg) +process_route_change (NMIP6Manager *manager, struct nl_msg *msg) { NMIP6ManagerPrivate *priv = NM_IP6_MANAGER_GET_PRIVATE (manager); NMIP6Device *device; + struct nlmsghdr *hdr; struct rtnl_route *rtnlroute; int old_size; - nm_log_dbg (LOGD_IP6, "processing netlink new/del route message"); - + hdr = nlmsg_hdr (msg); rtnlroute = NULL; nl_msg_parse (msg, ref_object, &rtnlroute); if (!rtnlroute) { @@ -603,53 +922,17 @@ process_route (NMIP6Manager *manager, struct nl_msg *msg) } device = nm_ip6_manager_get_device (manager, rtnl_route_get_oif (rtnlroute)); - if (!device) { - nm_log_dbg (LOGD_IP6, "ignoring message for unknown device"); - rtnl_route_put (rtnlroute); - return NULL; - } old_size = nl_cache_nitems (priv->route_cache); nl_cache_include (priv->route_cache, (struct nl_object *)rtnlroute, NULL, NULL); - rtnl_route_put (rtnlroute); - - /* As above in process_addr */ - if (nl_cache_nitems (priv->route_cache) == old_size) { - nm_log_dbg (LOGD_IP6, "(%s): route cache unchanged, ignoring message", - device->iface); - return NULL; - } - return device; -} - -static NMIP6Device * -process_prefix (NMIP6Manager *manager, struct nl_msg *msg) -{ - struct prefixmsg *pmsg; - NMIP6Device *device; - - /* We don't care about the prefix itself, but if we receive a - * router advertisement telling us to use DHCP, we might not - * get any RTM_NEWADDRs or RTM_NEWROUTEs, so this is our only - * way to notice immediately that an RA was received. - */ - - nm_log_dbg (LOGD_IP6, "processing netlink new prefix message"); - - if (!nlmsg_valid_hdr (nlmsg_hdr (msg), sizeof(*pmsg))) { - nm_log_dbg (LOGD_IP6, "ignoring invalid prefix message"); - return NULL; - } - - pmsg = (struct prefixmsg *) NLMSG_DATA (nlmsg_hdr (msg)); - device = nm_ip6_manager_get_device (manager, pmsg->prefix_ifindex); - - if (!device || device->addrconf_complete) { - nm_log_dbg (LOGD_IP6, "(%s): ignoring unknown or completed device", - device ? device->iface : "(none)"); + /* As above in process_address_change */ + nm_log_dbg (LOGD_IP6, "(%s): route cache size: %d -> %d:", + device_get_iface (device), old_size, nl_cache_nitems (priv->route_cache)); + dump_route_change (device, hdr, rtnlroute); + rtnl_route_put (rtnlroute); + if (nl_cache_nitems (priv->route_cache) == old_size) return NULL; - } return device; } @@ -705,7 +988,9 @@ process_nduseropt_rdnss (NMIP6Device *device, struct nd_opt_hdr *opt) */ server.expires = ntohl (rdnss_opt->nd_opt_rdnss_lifetime); if (server.expires > 0) - server.expires += now + 10; + if (server.expires < 7200) + server.expires = 7200; + server.expires += now; for (addr = (struct in6_addr *) (rdnss_opt + 1); opt_len >= 2; addr++, opt_len -= 2) { char buf[INET6_ADDRSTRLEN + 1]; @@ -836,7 +1121,9 @@ process_nduseropt_dnssl (NMIP6Device *device, struct nd_opt_hdr *opt) */ domain.expires = ntohl (dnssl_opt->nd_opt_dnssl_lifetime); if (domain.expires > 0) - domain.expires += now + 10; + if (domain.expires < 7200) + domain.expires = 7200; + domain.expires += now; while (opt_len) { const char *domain_str; @@ -985,28 +1272,6 @@ static struct nla_policy link_prot_policy[IFLA_INET6_MAX + 1] = { [IFLA_INET6_FLAGS] = { .type = NLA_U32 }, }; -static char * -ra_flags_to_string (guint32 ra_flags) -{ - GString *s = g_string_sized_new (20); - - g_string_append (s, " ("); - if (ra_flags & IF_RS_SENT) - g_string_append_c (s, 'S'); - - if (ra_flags & IF_RA_RCVD) - g_string_append_c (s, 'R'); - - if (ra_flags & IF_RA_OTHERCONF) - g_string_append_c (s, 'O'); - - if (ra_flags & IF_RA_MANAGED) - g_string_append_c (s, 'M'); - - g_string_append_c (s, ')'); - return g_string_free (s, FALSE); -} - static NMIP6Device * process_newlink (NMIP6Manager *manager, struct nl_msg *msg) { @@ -1016,7 +1281,6 @@ process_newlink (NMIP6Manager *manager, struct nl_msg *msg) struct nlattr *tb[IFLA_MAX + 1]; struct nlattr *pi[IFLA_INET6_MAX + 1]; int err; - char *flags_str = NULL; /* FIXME: we have to do this manually for now since libnl doesn't yet * support the IFLA_PROTINFO attribute of NEWLINK messages. When it does, @@ -1059,13 +1323,7 @@ process_newlink (NMIP6Manager *manager, struct nl_msg *msg) return NULL; } - device->ra_flags = nla_get_u32 (pi[IFLA_INET6_FLAGS]); - - if (nm_logging_level_enabled (LOGL_DEBUG)) - flags_str = ra_flags_to_string (device->ra_flags); - nm_log_dbg (LOGD_IP6, "(%s): got IPv6 flags 0x%X%s", - device->iface, device->ra_flags, flags_str ? flags_str : ""); - g_free (flags_str); + device_set_ra_flags (device, nla_get_u32 (pi[IFLA_INET6_FLAGS])); return device; } @@ -1076,39 +1334,30 @@ netlink_notification (NMNetlinkMonitor *monitor, struct nl_msg *msg, gpointer us NMIP6Manager *manager = (NMIP6Manager *) user_data; NMIP6Device *device; struct nlmsghdr *hdr; - gboolean config_changed = FALSE; hdr = nlmsg_hdr (msg); nm_log_dbg (LOGD_HW, "netlink event type %d", hdr->nlmsg_type); switch (hdr->nlmsg_type) { case RTM_NEWADDR: case RTM_DELADDR: - device = process_addr (manager, msg); - config_changed = TRUE; + device = process_address_change (manager, msg); break; case RTM_NEWROUTE: case RTM_DELROUTE: - device = process_route (manager, msg); - config_changed = TRUE; - break; - case RTM_NEWPREFIX: - device = process_prefix (manager, msg); + device = process_route_change (manager, msg); break; case RTM_NEWNDUSEROPT: device = process_nduseropt (manager, msg); - config_changed = TRUE; break; case RTM_NEWLINK: device = process_newlink (manager, msg); - config_changed = TRUE; break; default: return; } if (device) { - nm_log_dbg (LOGD_IP6, "(%s): syncing device with netlink changes", device->iface); - nm_ip6_device_sync_from_netlink (device, config_changed); + nm_ip6_device_sync_from_netlink (device); } } @@ -1179,7 +1428,7 @@ nm_ip6_manager_begin_addrconf (NMIP6Manager *manager, int ifindex) device->ra_flags = 0; /* Set up a timeout on the transaction to kill it after the timeout */ - info = callback_info_new (device, 0, FALSE); + info = callback_info_new (device, FALSE); device->finish_addrconf_id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, NM_IP6_TIMEOUT, finish_addrconf, @@ -1204,7 +1453,7 @@ nm_ip6_manager_begin_addrconf (NMIP6Manager *manager, int ifindex) * device is already fully configured and schedule the * ADDRCONF_COMPLETE signal in that case. */ - nm_ip6_device_sync_from_netlink (device, FALSE); + nm_ip6_device_sync_from_netlink (device); } void @@ -1235,9 +1484,7 @@ nm_ip6_manager_get_ip6_config (NMIP6Manager *manager, int ifindex) NMIP6Address *ip6addr; struct rtnl_route *rtnlroute; struct nl_addr *nldest, *nlgateway; - struct in6_addr *dest, *gateway; - gboolean defgw_set = FALSE; - struct in6_addr defgw; + const struct in6_addr *dest, *gateway; uint32_t metric; NMIP6Route *ip6route; int i; @@ -1287,11 +1534,9 @@ nm_ip6_manager_get_ip6_config (NMIP6Manager *manager, int ifindex) gateway = nl_addr_get_binary_addr (nlgateway); if (rtnl_route_get_dst_len (rtnlroute) == 0) { - /* Default gateway route; don't add to normal routes but to each address */ - if (!defgw_set) { - memcpy (&defgw, gateway, sizeof (defgw)); - defgw_set = TRUE; - } + /* Default gateway route; cache the router's address for later */ + if (!nm_ip6_config_get_gateway (config)) + nm_ip6_config_set_gateway (config, gateway); continue; } @@ -1326,8 +1571,9 @@ nm_ip6_manager_get_ip6_config (NMIP6Manager *manager, int ifindex) nm_ip6_address_set_prefix (ip6addr, rtnl_addr_get_prefixlen (rtnladdr)); nm_ip6_address_set_address (ip6addr, addr); nm_ip6_config_take_address (config, ip6addr); - if (defgw_set) - nm_ip6_address_set_gateway (ip6addr, &defgw); + gateway = nm_ip6_config_get_gateway (config); + if (gateway) + nm_ip6_address_set_gateway (ip6addr, gateway); } /* Add DNS servers */ diff --git a/src/logging/Makefile.in b/src/logging/Makefile.in index c73f71b4..45f84326 100644 --- a/src/logging/Makefile.in +++ b/src/logging/Makefile.in @@ -47,7 +47,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -165,6 +165,10 @@ 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@ @@ -260,6 +264,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -298,6 +305,8 @@ 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@ diff --git a/src/logging/nm-logging.c b/src/logging/nm-logging.c index a2b0ebaf..f54adcdd 100644 --- a/src/logging/nm-logging.c +++ b/src/logging/nm-logging.c @@ -46,7 +46,7 @@ static guint32 log_domains = \ LOGD_DHCP4 | LOGD_DHCP6 | LOGD_PPP | LOGD_IP4 | LOGD_IP6 | LOGD_AUTOIP4 | \ LOGD_DNS | LOGD_VPN | LOGD_SHARING | LOGD_SUPPLICANT | LOGD_AGENTS | \ LOGD_SETTINGS | LOGD_SUSPEND | LOGD_CORE | LOGD_DEVICE | LOGD_OLPC_MESH | \ - LOGD_WIMAX | LOGD_INFINIBAND | LOGD_FIREWALL; + LOGD_WIMAX | LOGD_INFINIBAND | LOGD_FIREWALL | LOGD_ADSL; typedef struct { guint32 num; @@ -89,6 +89,7 @@ static const LogDesc domain_descs[] = { { LOGD_WIMAX, "WIMAX" }, { LOGD_INFINIBAND,"INFINIBAND" }, { LOGD_FIREWALL, "FIREWALL" }, + { LOGD_ADSL, "ADSL" }, { 0, NULL } }; diff --git a/src/logging/nm-logging.h b/src/logging/nm-logging.h index 7e27f311..b3595d18 100644 --- a/src/logging/nm-logging.h +++ b/src/logging/nm-logging.h @@ -54,6 +54,7 @@ enum { LOGD_WIMAX = 0x00800000, LOGD_INFINIBAND = 0x01000000, LOGD_FIREWALL = 0x02000000, + LOGD_ADSL = 0x04000000, }; #define LOGD_DHCP (LOGD_DHCP4 | LOGD_DHCP6) diff --git a/src/main.c b/src/main.c index 4a21959f..e8ff2e4c 100644 --- a/src/main.c +++ b/src/main.c @@ -29,6 +29,7 @@ #include <errno.h> #include <stdlib.h> #include <signal.h> +#include <pthread.h> #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> @@ -53,6 +54,7 @@ #include "nm-logging.h" #include "nm-policy-hosts.h" #include "nm-config.h" +#include "nm-posix-signals.h" #if !defined(NM_DIST_VERSION) # define NM_DIST_VERSION VERSION @@ -66,101 +68,107 @@ */ static NMManager *manager = NULL; static GMainLoop *main_loop = NULL; -static int quit_pipe[2] = { -1, -1 }; - static gboolean quit_early = FALSE; +static sigset_t signal_set; -static void -nm_signal_handler (int signo) +void *signal_handling_thread (void *arg); +/* + * Thread function waiting for signals and processing them. + * Wait for signals in signal set. The semantics of sigwait() require that all + * threads (including the thread calling sigwait()) have the signal masked, for + * reliable operation. Otherwise, a signal that arrives while this thread is + * not blocked in sigwait() might be delivered to another thread. + */ +void * +signal_handling_thread (void *arg) { - static int in_fatal = 0, x; - - /* avoid loops */ - if (in_fatal > 0) - return; - ++in_fatal; - - switch (signo) { - case SIGSEGV: - case SIGBUS: - case SIGILL: - case SIGABRT: - nm_log_warn (LOGD_CORE, "caught signal %d. Generating backtrace...", signo); - nm_logging_backtrace (); - exit (1); - break; - case SIGFPE: - case SIGPIPE: - /* let the fatal signals interrupt us */ - --in_fatal; - nm_log_warn (LOGD_CORE, "caught signal %d, shutting down abnormally. Generating backtrace...", signo); - nm_logging_backtrace (); - x = write (quit_pipe[1], "X", 1); - break; - case SIGINT: - case SIGTERM: - /* let the fatal signals interrupt us */ - --in_fatal; - nm_log_info (LOGD_CORE, "caught signal %d, shutting down normally.", signo); - quit_early = TRUE; - x = write (quit_pipe[1], "X", 1); - break; - case SIGHUP: - --in_fatal; - /* Reread config stuff like system config files, VPN service files, etc */ - break; - case SIGUSR1: - --in_fatal; - /* Play with log levels or something */ - break; - default: - signal (signo, nm_signal_handler); - break; - } + int signo; + + while (1) { + sigwait (&signal_set, &signo); + + switch (signo) { + case SIGSEGV: + case SIGBUS: + case SIGILL: + case SIGABRT: + case SIGQUIT: + nm_log_warn (LOGD_CORE, "caught signal %d. Generating backtrace...", signo); + nm_logging_backtrace (); + exit (1); + break; + case SIGFPE: + case SIGPIPE: + nm_log_warn (LOGD_CORE, "caught signal %d, shutting down abnormally. Generating backtrace...", signo); + nm_logging_backtrace (); + quit_early = TRUE; /* for quitting before entering the main loop */ + g_main_loop_quit (main_loop); + break; + case SIGINT: + case SIGTERM: + nm_log_info (LOGD_CORE, "caught signal %d, shutting down normally.", signo); + quit_early = TRUE; /* for quitting before entering the main loop */ + g_main_loop_quit (main_loop); + break; + case SIGHUP: + /* Reread config stuff like system config files, VPN service files, etc */ + nm_log_info (LOGD_CORE, "caught signal %d, not supported yet.", signo); + break; + case SIGUSR1: + /* Play with log levels or something */ + nm_log_info (LOGD_CORE, "caught signal %d, not supported yet.", signo); + break; + default: + nm_log_err (LOGD_CORE, "caught unexpected signal %d", signo); + break; + } + } + return NULL; } +/* + * Mask the signals we are interested in and create a signal handling thread. + * Because all threads inherit the signal mask from their creator, all threads + * in the process will have the signals masked. That's why setup_signals() has + * to be called before creating other threads. + */ static gboolean -quit_watch (GIOChannel *src, GIOCondition condition, gpointer user_data) -{ - - if (condition & G_IO_IN) { - nm_log_warn (LOGD_CORE, "quit request received, terminating..."); - g_main_loop_quit (main_loop); - } - - return FALSE; -} - -static void setup_signals (void) { - struct sigaction action; - sigset_t mask; - GIOChannel *quit_channel; + pthread_t signal_thread_id; + sigset_t old_sig_mask; + int status; + + sigemptyset (&signal_set); + sigaddset (&signal_set, SIGHUP); + sigaddset (&signal_set, SIGINT); + sigaddset (&signal_set, SIGQUIT); + sigaddset (&signal_set, SIGILL); + sigaddset (&signal_set, SIGABRT); + sigaddset (&signal_set, SIGFPE); + sigaddset (&signal_set, SIGBUS); + sigaddset (&signal_set, SIGSEGV); + sigaddset (&signal_set, SIGPIPE); + sigaddset (&signal_set, SIGTERM); + sigaddset (&signal_set, SIGUSR1); + + /* Block all signals of interest. */ + status = pthread_sigmask (SIG_BLOCK, &signal_set, &old_sig_mask); + if (status != 0) { + fprintf (stderr, _("Failed to set signal mask: %d"), status); + return FALSE; + } + /* Save original mask so that we could use it for child processes. */ + nm_save_original_signal_mask (old_sig_mask); - /* Set up our quit pipe */ - if (pipe (quit_pipe) < 0) { - fprintf (stderr, _("Failed to initialize SIGTERM pipe: %d"), errno); - exit (1); + /* Create the signal handling thread. */ + status = pthread_create (&signal_thread_id, NULL, signal_handling_thread, NULL); + if (status != 0) { + fprintf (stderr, _("Failed to create signal handling thread: %d"), status); + return FALSE; } - fcntl (quit_pipe[1], F_SETFL, O_NONBLOCK | fcntl (quit_pipe[1], F_GETFL)); - - quit_channel = g_io_channel_unix_new (quit_pipe[0]); - g_io_add_watch_full (quit_channel, G_PRIORITY_HIGH, G_IO_IN | G_IO_ERR, quit_watch, NULL, NULL); - - sigemptyset (&mask); - action.sa_handler = nm_signal_handler; - action.sa_mask = mask; - action.sa_flags = 0; - sigaction (SIGTERM, &action, NULL); - sigaction (SIGINT, &action, NULL); - sigaction (SIGILL, &action, NULL); - sigaction (SIGBUS, &action, NULL); - sigaction (SIGFPE, &action, NULL); - sigaction (SIGHUP, &action, NULL); - sigaction (SIGSEGV, &action, NULL); - sigaction (SIGABRT, &action, NULL); - sigaction (SIGUSR1, &action, NULL); + + return TRUE; } static gboolean @@ -380,7 +388,7 @@ main (int argc, char *argv[]) " [NONE,HW,RFKILL,ETHER,WIFI,BT,MB,DHCP4,DHCP6,PPP,\n" " WIFI_SCAN,IP4,IP6,AUTOIP4,DNS,VPN,SHARING,SUPPLICANT,\n" " AGENTS,SETTINGS,SUSPEND,CORE,DEVICE,OLPC,WIMAX,\n" - " INFINIBAND,FIREWALL]"), + " INFINIBAND,FIREWALL,ADSL]"), "HW,RFKILL,WIFI" }, { "connectivity-uri", 0, 0, G_OPTION_ARG_STRING, &connectivity_uri, "A http(s) address to check internet connectivity" }, { "connectivity-interval", 0, 0, G_OPTION_ARG_INT, &connectivity_interval, "the interval in seconds how often a connectivity check will be done" }, @@ -393,6 +401,10 @@ main (int argc, char *argv[]) exit (1); } + /* Set up unix signal handling */ + if (!setup_signals ()) + exit (1); + /* Set locale to be able to use environment variables */ setlocale (LC_ALL, ""); @@ -529,14 +541,19 @@ main (int argc, char *argv[]) dbus_glib_global_set_disable_legacy_property_access (); #endif - setup_signals (); - nm_logging_start (become_daemon); nm_log_info (LOGD_CORE, "NetworkManager (version " NM_DIST_VERSION ") is starting..."); success = FALSE; nm_log_info (LOGD_CORE, "Read config file %s", nm_config_get_path (config)); + nm_log_info (LOGD_CORE, "WEXT support is %s", +#if HAVE_WEXT + "enabled" +#else + "disabled" +#endif + ); main_loop = g_main_loop_new (NULL, FALSE); diff --git a/src/modem-manager/Makefile.in b/src/modem-manager/Makefile.in index 87afed0c..31209330 100644 --- a/src/modem-manager/Makefile.in +++ b/src/modem-manager/Makefile.in @@ -47,7 +47,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -171,6 +171,10 @@ 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@ @@ -266,6 +270,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -304,6 +311,8 @@ 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@ diff --git a/src/modem-manager/nm-modem.c b/src/modem-manager/nm-modem.c index 91c0b06d..c9c9e9a4 100644 --- a/src/modem-manager/nm-modem.c +++ b/src/modem-manager/nm-modem.c @@ -591,7 +591,7 @@ real_deactivate (NMModem *self, NMDevice *device) case MM_MODEM_IP_METHOD_STATIC: case MM_MODEM_IP_METHOD_DHCP: ifindex = nm_device_get_ip_ifindex (device); - if (ifindex >= 0) { + if (ifindex > 0) { /* FIXME: use AF_UNSPEC here when we have IPv6 support */ nm_system_iface_flush_routes (ifindex, AF_INET); nm_system_iface_flush_addresses (ifindex, AF_UNSPEC); @@ -614,8 +614,9 @@ static void disconnect_done (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_data) { GError *error = NULL; + gboolean warn = GPOINTER_TO_UINT (user_data); - if (!dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID)) { + if (!dbus_g_proxy_end_call (proxy, call_id, &error, G_TYPE_INVALID) && warn) { nm_log_info (LOGD_MB, "disconnect failed: (%d) %s", error ? error->code : -1, error && error->message ? error->message : "(unknown)"); @@ -628,7 +629,7 @@ nm_modem_device_state_changed (NMModem *self, NMDeviceState old_state, NMDeviceStateReason reason) { - gboolean was_connected = FALSE; + gboolean was_connected = FALSE, warn = TRUE; NMModemPrivate *priv; g_return_if_fail (self != NULL); @@ -658,10 +659,13 @@ nm_modem_device_state_changed (NMModem *self, } if (was_connected) { + /* Don't bother warning on FAILED since the modem is already gone */ + if (new_state == NM_DEVICE_STATE_FAILED) + warn = FALSE; dbus_g_proxy_begin_call (nm_modem_get_proxy (self, MM_DBUS_INTERFACE_MODEM), "Disconnect", disconnect_done, - self, + GUINT_TO_POINTER (warn), NULL, G_TYPE_INVALID); } diff --git a/src/nm-activation-request.c b/src/nm-activation-request.c index 3fc7b538..1a3cb77a 100644 --- a/src/nm-activation-request.c +++ b/src/nm-activation-request.c @@ -36,6 +36,7 @@ #include "nm-device.h" #include "nm-active-connection.h" #include "nm-settings-connection.h" +#include "nm-posix-signals.h" G_DEFINE_TYPE (NMActRequest, nm_act_request, NM_TYPE_ACTIVE_CONNECTION) @@ -129,6 +130,9 @@ nm_act_request_get_secrets (NMActRequest *self, info->callback = callback; info->callback_data = callback_data; + if (priv->user_requested) + flags |= NM_SETTINGS_GET_SECRETS_FLAG_USER_REQUESTED; + call_id = nm_settings_connection_get_secrets (NM_SETTINGS_CONNECTION (priv->connection), priv->user_requested, priv->user_uid, @@ -261,6 +265,8 @@ share_child_setup (gpointer user_data G_GNUC_UNUSED) /* We are in the child process at this point */ pid_t pid = getpid (); setpgid (pid, pid); + + nm_unblock_posix_signals (NULL); } void diff --git a/src/nm-connection-provider.c b/src/nm-connection-provider.c new file mode 100644 index 00000000..401f8dab --- /dev/null +++ b/src/nm-connection-provider.c @@ -0,0 +1,112 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2012 Red Hat, Inc. + */ + +#include "nm-connection-provider.h" + +GSList * +nm_connection_provider_get_best_connections (NMConnectionProvider *self, + guint max_requested, + const char *ctype1, + const char *ctype2, + NMConnectionFilterFunc func, + gpointer func_data) +{ + g_return_val_if_fail (NM_IS_CONNECTION_PROVIDER (self), NULL); + + if (NM_CONNECTION_PROVIDER_GET_INTERFACE (self)->get_best_connections) + return NM_CONNECTION_PROVIDER_GET_INTERFACE (self)->get_best_connections (self, max_requested, ctype1, ctype2, func, func_data); + return NULL; +} + +const GSList * +nm_connection_provider_get_connections (NMConnectionProvider *self) +{ + g_return_val_if_fail (NM_IS_CONNECTION_PROVIDER (self), NULL); + + if (NM_CONNECTION_PROVIDER_GET_INTERFACE (self)->get_connections) + return NM_CONNECTION_PROVIDER_GET_INTERFACE (self)->get_connections (self); + return NULL; +} + +/*****************************************************************************/ + +static void +nm_connection_provider_init (gpointer g_iface) +{ + GType iface_type = G_TYPE_FROM_INTERFACE (g_iface); + static gboolean initialized = FALSE; + + if (initialized) + return; + initialized = TRUE; + + /* Signals */ + g_signal_new (NM_CP_SIGNAL_CONNECTION_ADDED, + iface_type, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMConnectionProvider, connection_added), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, G_TYPE_OBJECT); + + g_signal_new (NM_CP_SIGNAL_CONNECTION_UPDATED, + iface_type, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMConnectionProvider, connection_updated), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, G_TYPE_OBJECT); + + g_signal_new (NM_CP_SIGNAL_CONNECTION_REMOVED, + iface_type, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMConnectionProvider, connection_removed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, G_TYPE_OBJECT); + + g_signal_new (NM_CP_SIGNAL_CONNECTIONS_LOADED, + iface_type, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMConnectionProvider, connections_loaded), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +GType +nm_connection_provider_get_type (void) +{ + static GType cp_type = 0; + + if (!G_UNLIKELY (cp_type)) { + const GTypeInfo cp_info = { + sizeof (NMConnectionProvider), /* class_size */ + nm_connection_provider_init, /* base_init */ + NULL, /* base_finalize */ + NULL, + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, + 0, /* n_preallocs */ + NULL + }; + + cp_type = g_type_register_static (G_TYPE_INTERFACE, "NMConnectionProvider", &cp_info, 0); + g_type_interface_add_prerequisite (cp_type, G_TYPE_OBJECT); + } + + return cp_type; +} diff --git a/src/nm-connection-provider.h b/src/nm-connection-provider.h new file mode 100644 index 00000000..942651f7 --- /dev/null +++ b/src/nm-connection-provider.h @@ -0,0 +1,106 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2012 Red Hat, Inc. + */ + +#ifndef NM_CONNECTION_PROVIDER_H +#define NM_CONNECTION_PROVIDER_H + +#include <glib-object.h> +#include <nm-connection.h> + +#define NM_TYPE_CONNECTION_PROVIDER (nm_connection_provider_get_type ()) +#define NM_CONNECTION_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_CONNECTION_PROVIDER, NMConnectionProvider)) +#define NM_IS_CONNECTION_PROVIDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_CONNECTION_PROVIDER)) +#define NM_CONNECTION_PROVIDER_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_CONNECTION_PROVIDER, NMConnectionProvider)) + +typedef struct _NMConnectionProvider NMConnectionProvider; + +#define NM_CP_SIGNAL_CONNECTION_ADDED "cp-connection-added" +#define NM_CP_SIGNAL_CONNECTION_UPDATED "cp-connection-updated" +#define NM_CP_SIGNAL_CONNECTION_REMOVED "cp-connection-removed" +#define NM_CP_SIGNAL_CONNECTIONS_LOADED "cp-connections-loaded" + + +/** + * NMConnectionFilterFunc: + * @provider: The provider requesting the filtering + * @connection: the connection to be filtered + * @func_data: the caller-provided data pointer + * + * Returns: %TRUE to allow the connection, %FALSE to ignore it + */ +typedef gboolean (*NMConnectionFilterFunc) (NMConnectionProvider *provider, + NMConnection *connection, + gpointer func_data); + + +struct _NMConnectionProvider { + GTypeInterface g_iface; + + /* Methods */ + GSList * (*get_best_connections) (NMConnectionProvider *self, + guint max_requested, + const char *ctype1, + const char *ctype2, + NMConnectionFilterFunc func, + gpointer func_data); + + const GSList * (*get_connections) (NMConnectionProvider *self); + + /* Signals */ + void (*connection_added) (NMConnectionProvider *self, NMConnection *connection); + + void (*connection_updated) (NMConnectionProvider *self, NMConnection *connection); + + void (*connection_removed) (NMConnectionProvider *self, NMConnection *connection); + + void (*connections_loaded) (NMConnectionProvider *self); +}; + +GType nm_connection_provider_get_type (void); + +/** + * nm_connection_provider_get_best_connections: + * @self: the #NMConnectionProvider + * @max_requested: if non-zero, the maximum number of connections to return + * @ctype1: an #NMSetting base type (eg NM_SETTING_WIRELESS_SETTING_NAME) to + * filter connections against + * @ctype2: a second #NMSetting base type (eg NM_SETTING_WIRELESS_SETTING_NAME) + * to filter connections against + * @func: caller-supplied function for filtering connections + * @func_data: caller-supplied data passed to @func + * + * Returns: a #GSList of #NMConnection objects in sorted order representing the + * "best" or highest-priority connections filtered by @ctype1 and/or @ctype2, + * and/or @func. Caller is responsible for freeing the returned #GSList, but + * the contained values do not need to be unreffed. + */ +GSList *nm_connection_provider_get_best_connections (NMConnectionProvider *self, + guint max_requested, + const char *ctype1, + const char *ctype2, + NMConnectionFilterFunc func, + gpointer func_data); + +/** + * nm_connection_provider_get_connections: + * @self: the #NMConnectionProvider + * + * Returns: a #GSList of #NMConnection objects representing all known + * connections. Returned list is owned by the connection provider and must + * not be freed. + */ +const GSList *nm_connection_provider_get_connections (NMConnectionProvider *self); + +#endif /* NM_CONNECTION_PROVIDER_H */ diff --git a/src/nm-device-adsl.c b/src/nm-device-adsl.c new file mode 100644 index 00000000..e171b46e --- /dev/null +++ b/src/nm-device-adsl.c @@ -0,0 +1,841 @@ +/* -*- 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. + * + * Pantelis Koukousoulas <pktoss@gmail.com> + */ + +#include <config.h> + +#include <sys/socket.h> +#include <linux/atmdev.h> +#include <linux/atmbr2684.h> + +#include <errno.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <unistd.h> + +#include <glib.h> +#include <glib/gi18n.h> +#include <stdlib.h> +#include <string.h> + +#include "nm-device-adsl.h" +#include "nm-device-private.h" +#include "nm-properties-changed-signal.h" +#include "NetworkManagerUtils.h" +#include "nm-logging.h" +#include "nm-enum-types.h" +#include "nm-system.h" +#include "nm-netlink-monitor.h" + +#include "ppp-manager/nm-ppp-manager.h" +#include "nm-setting-adsl.h" + +#include "nm-device-adsl-glue.h" + +G_DEFINE_TYPE (NMDeviceAdsl, nm_device_adsl, NM_TYPE_DEVICE) + +#define NM_DEVICE_ADSL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_ADSL, NMDeviceAdslPrivate)) + +#define NM_ADSL_ERROR (nm_adsl_error_quark ()) + +static GQuark +nm_adsl_error_quark (void) +{ + static GQuark quark = 0; + if (!quark) + quark = g_quark_from_static_string ("nm-adsl-error"); + return quark; +} + +/**********************************************/ + +typedef struct { + gboolean disposed; + gboolean carrier; + guint carrier_poll_id; + int atm_index; + + /* Watch for 'nas' interfaces going away */ + NMNetlinkMonitor *monitor; + guint netlink_id; + + /* PPP */ + NMPPPManager *ppp_manager; + + /* RFC 2684 bridging (PPPoE over ATM) */ + int brfd; + int nas_ifindex; + char * nas_ifname; +} NMDeviceAdslPrivate; + +enum { + PROPERTIES_CHANGED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +enum { + PROP_0, + PROP_CARRIER, + + LAST_PROP +}; + +/**************************************************************/ + +static guint32 +real_get_generic_capabilities (NMDevice *dev) +{ + guint32 caps = NM_DEVICE_CAP_NM_SUPPORTED; + caps |= NM_DEVICE_CAP_CARRIER_DETECT; + return caps; +} + +static gboolean +real_can_interrupt_activation (NMDevice *dev) +{ + NMDeviceAdsl *self = NM_DEVICE_ADSL (dev); + gboolean interrupt = FALSE; + + /* Devices that support carrier detect can interrupt activation + * if the link becomes inactive. + */ + if (NM_DEVICE_ADSL_GET_PRIVATE (self)->carrier == FALSE) + interrupt = TRUE; + + return interrupt; +} + +static gboolean +real_is_available (NMDevice *dev) +{ + NMDeviceAdsl *self = NM_DEVICE_ADSL (dev); + + /* Can't do anything if there isn't a carrier */ + if (!NM_DEVICE_ADSL_GET_PRIVATE (self)->carrier) + return FALSE; + + return TRUE; +} + +static gboolean +real_check_connection_compatible (NMDevice *device, + NMConnection *connection, + GError **error) +{ + NMSettingAdsl *s_adsl; + const char *protocol; + + if (!nm_connection_is_type (connection, NM_SETTING_ADSL_SETTING_NAME)) { + g_set_error (error, + NM_ADSL_ERROR, NM_ADSL_ERROR_CONNECTION_NOT_ADSL, + "The connection was not an ADSL connection."); + return FALSE; + } + + s_adsl = nm_connection_get_setting_adsl (connection); + if (!s_adsl) { + g_set_error (error, + NM_ADSL_ERROR, NM_ADSL_ERROR_CONNECTION_INVALID, + "The connection was not a valid ADSL connection."); + return FALSE; + } + + /* FIXME: we don't yet support IPoATM */ + protocol = nm_setting_adsl_get_protocol (s_adsl); + if (g_strcmp0 (protocol, NM_SETTING_ADSL_PROTOCOL_IPOATM) == 0) { + g_set_error (error, + NM_ADSL_ERROR, NM_ADSL_ERROR_CONNECTION_INVALID, + "IPoATM connections are not yet supported."); + return FALSE; + } + + return TRUE; +} + +static gboolean +real_complete_connection (NMDevice *device, + NMConnection *connection, + const char *specific_object, + const GSList *existing_connections, + GError **error) +{ + NMSettingAdsl *s_adsl; + + /* + * We can't telepathically figure out the username, so if + * it wasn't given, we can't complete the connection. + */ + s_adsl = nm_connection_get_setting_adsl (connection); + if (s_adsl && !nm_setting_verify (NM_SETTING (s_adsl), NULL, error)) + return FALSE; + + nm_utils_complete_generic (connection, + NM_SETTING_ADSL_SETTING_NAME, + existing_connections, + _("ADSL connection %d"), + NULL, + FALSE); /* No IPv6 yet by default */ + + + return TRUE; +} + +static NMConnection * +real_get_best_auto_connection (NMDevice *dev, + GSList *connections, + char **specific_object) +{ + GSList *iter; + + for (iter = connections; iter; iter = g_slist_next (iter)) { + NMConnection *connection = NM_CONNECTION (iter->data); + NMSettingConnection *s_con; + NMSettingAdsl *s_adsl; + + if (!nm_connection_is_type (connection, NM_SETTING_ADSL_SETTING_NAME)) + continue; + + s_adsl = nm_connection_get_setting_adsl (connection); + if (!s_adsl) + continue; + + s_con = nm_connection_get_setting_connection (connection); + g_assert (s_con); + if (!nm_setting_connection_get_autoconnect (s_con)) + continue; + + return connection; + } + return NULL; +} + +/**************************************************************/ + +static void +set_nas_iface (NMDeviceAdsl *self, int idx, const char *name) +{ + NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); + + g_return_if_fail (name != NULL); + + g_warn_if_fail (priv->nas_ifindex <= 0); + if (idx > 0) + priv->nas_ifindex = idx; + else + priv->nas_ifindex = nm_netlink_iface_to_index (name); + g_warn_if_fail (priv->nas_ifindex > 0); + + g_warn_if_fail (priv->nas_ifname == NULL); + priv->nas_ifname = g_strdup (name); +} + +static gboolean +br2684_create_iface (NMDeviceAdsl *self, NMSettingAdsl *s_adsl) +{ + NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); + const char *iface = nm_device_get_iface (NM_DEVICE (self)); + struct atm_newif_br2684 ni; + int err, fd; + gboolean success = FALSE; + guint num = 0; + + g_return_val_if_fail (s_adsl != NULL, FALSE); + + fd = socket (PF_ATMPVC, SOCK_DGRAM, ATM_AAL5); + if (fd < 0) { + nm_log_err (LOGD_ADSL, "(%s): failed to open ATM control socket (%d)", + iface, errno); + return FALSE; + } + + memset (&ni, 0, sizeof (ni)); + ni.backend_num = ATM_BACKEND_BR2684; + ni.media = BR2684_MEDIA_ETHERNET; + ni.mtu = 1500; + + /* Loop attempting to create an interface that doesn't exist yet. The + * kernel can create one for us automatically, but due to API issues it + * cannot return that name to us. Since we want to know the name right + * away, just brute-force it. + */ + while (num < 10000) { + memset (&ni.ifname, 0, sizeof (ni.ifname)); + snprintf (ni.ifname, sizeof (ni.ifname), "nas%d", num); + + err = ioctl (fd, ATM_NEWBACKENDIF, &ni); + if (err == 0) { + set_nas_iface (self, -1, ni.ifname); + nm_log_info (LOGD_ADSL, "(%s): using NAS interface %s (%d)", + iface, priv->nas_ifname, priv->nas_ifindex); + success = TRUE; + break; + } else if (errno == -EEXIST) { + /* Try again */ + num++; + } else { + nm_log_warn (LOGD_ADSL, "(%s): failed to create br2684 interface (%d)", + iface, errno); + break; + } + } + + close (fd); + return success; +} + +static gboolean +br2684_assign_vcc (NMDeviceAdsl *self, NMSettingAdsl *s_adsl) +{ + NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); + const char *iface = nm_device_get_iface (NM_DEVICE (self)); + struct sockaddr_atmpvc addr; + struct atm_backend_br2684 be; + struct atm_qos qos; + int err, bufsize = 8192; + const char *encapsulation; + gboolean is_llc; + + g_return_val_if_fail (priv->brfd == -1, FALSE); + g_return_val_if_fail (priv->nas_ifname != NULL, FALSE); + + priv->brfd = socket (PF_ATMPVC, SOCK_DGRAM, ATM_AAL5); + if (priv->brfd < 0) { + nm_log_err (LOGD_ADSL, "(%s): failed to open ATM control socket (%d)", + iface, errno); + return FALSE; + } + + err = setsockopt (priv->brfd, SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof (bufsize)); + if (err != 0) { + nm_log_err (LOGD_ADSL, "(%s): failed to set SNDBUF option (%d)", + iface, errno); + goto error; + } + + /* QoS */ + memset (&qos, 0, sizeof (qos)); + qos.aal = ATM_AAL5; + qos.txtp.traffic_class = ATM_UBR; + qos.txtp.max_sdu = 1524; + qos.txtp.pcr = ATM_MAX_PCR; + qos.rxtp = qos.txtp; + + err = setsockopt (priv->brfd, SOL_ATM, SO_ATMQOS, &qos, sizeof (qos)); + if (err != 0) { + nm_log_err (LOGD_ADSL, "(%s): failed to set QoS (%d)", + iface, errno); + goto error; + } + + encapsulation = nm_setting_adsl_get_encapsulation (s_adsl); + + /* VPI/VCI */ + memset (&addr, 0, sizeof (addr)); + addr.sap_family = AF_ATMPVC; + addr.sap_addr.itf = priv->atm_index; + addr.sap_addr.vpi = (guint16) nm_setting_adsl_get_vpi (s_adsl); + addr.sap_addr.vci = (int) nm_setting_adsl_get_vci (s_adsl); + + nm_log_dbg (LOGD_ADSL, "(%s): assigning address %d.%d.%d encapsulation %s", + nm_device_get_iface (NM_DEVICE (self)), + priv->atm_index, addr.sap_addr.vpi, addr.sap_addr.vci, + encapsulation); + + err = connect (priv->brfd, (struct sockaddr*) &addr, sizeof (addr)); + if (err != 0) { + nm_log_err (LOGD_ADSL, "(%s): failed to set VPI/VCI (%d)", + iface, errno); + goto error; + } + + /* And last attach the VCC to the interface */ + is_llc = (g_strcmp0 (encapsulation, "llc") == 0); + + memset (&be, 0, sizeof (be)); + be.backend_num = ATM_BACKEND_BR2684; + be.ifspec.method = BR2684_FIND_BYIFNAME; + strcpy (be.ifspec.spec.ifname, priv->nas_ifname); + be.fcs_in = BR2684_FCSIN_NO; + be.fcs_out = BR2684_FCSOUT_NO; + be.encaps = is_llc ? BR2684_ENCAPS_LLC : BR2684_ENCAPS_VC; + err = ioctl (priv->brfd, ATM_SETBACKEND, &be); + if (err != 0) { + nm_log_err (LOGD_ADSL, "(%s): failed to attach VCC (%d)", + iface, errno); + goto error; + } + + return TRUE; + +error: + close (priv->brfd); + priv->brfd = -1; + return FALSE; +} + +static void +netlink_notification (NMNetlinkMonitor *monitor, + struct nl_msg *msg, + gpointer user_data) +{ + NMDeviceAdsl *self = NM_DEVICE_ADSL (user_data); + NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); + NMDevice *device = NM_DEVICE (user_data); + struct nlmsghdr *hdr = nlmsg_hdr (msg); + const char *iface = nm_device_get_iface (device); + + /* This only gets called for PPPoE connections and "nas" interfaces */ + + if ((hdr->nlmsg_type == RTM_DELLINK) && (priv->nas_ifindex >= 0)) { + struct ifinfomsg *ifi = nlmsg_data (hdr); + + if (ifi->ifi_index == priv->nas_ifindex) { + /* NAS device went away for some reason; kill the connection */ + nm_log_dbg (LOGD_ADSL, "(%s): NAS interface disappeared", iface); + nm_device_state_changed (device, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_BR2684_FAILED); + } + } +} + +static NMActStageReturn +real_act_stage2_config (NMDevice *device, NMDeviceStateReason *out_reason) +{ + NMDeviceAdsl *self = NM_DEVICE_ADSL (device); + NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); + NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; + NMSettingAdsl *s_adsl; + const char *protocol; + + g_assert (out_reason); + + s_adsl = nm_connection_get_setting_adsl (nm_device_get_connection (device)); + g_assert (s_adsl); + + protocol = nm_setting_adsl_get_protocol (s_adsl); + nm_log_dbg (LOGD_ADSL, "(%s): using ADSL protocol '%s'", + nm_device_get_iface (device), protocol); + + if (g_strcmp0 (protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE) == 0) { + + /* PPPoE needs RFC2684 bridging before we can do PPP over it */ + if (!br2684_create_iface (self, s_adsl)) { + *out_reason = NM_DEVICE_STATE_REASON_BR2684_FAILED; + goto done; + } + + /* Set up the VCC */ + if (!br2684_assign_vcc (self, s_adsl)) { + *out_reason = NM_DEVICE_STATE_REASON_BR2684_FAILED; + goto done; + } + + /* Watch for the 'nas' interface going away */ + priv->netlink_id = g_signal_connect (priv->monitor, "notification", + G_CALLBACK (netlink_notification), + self); + + nm_log_dbg (LOGD_ADSL, "(%s): ATM setup successful", nm_device_get_iface (device)); + + /* otherwise we're good for stage3 */ + nm_system_iface_set_up (priv->nas_ifindex, TRUE, NULL); + ret = NM_ACT_STAGE_RETURN_SUCCESS; + + } else if (g_strcmp0 (protocol, NM_SETTING_ADSL_PROTOCOL_PPPOA) == 0) { + /* PPPoA doesn't need anything special */ + ret = NM_ACT_STAGE_RETURN_SUCCESS; + } else { + nm_log_warn (LOGD_ADSL, "(%s): unhandled ADSL protocol '%s'", + nm_device_get_iface (device), protocol); + } + +done: + return ret; +} + +static void +ppp_state_changed (NMPPPManager *ppp_manager, NMPPPStatus status, gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + + switch (status) { + case NM_PPP_STATUS_DISCONNECT: + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_DISCONNECT); + break; + case NM_PPP_STATUS_DEAD: + nm_device_state_changed (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_PPP_FAILED); + break; + default: + break; + } +} + +static void +ppp_ip4_config (NMPPPManager *ppp_manager, + const char *iface, + NMIP4Config *config, + gpointer user_data) +{ + NMDevice *device = NM_DEVICE (user_data); + + /* Ignore PPP IP4 events that come in after initial configuration */ + if (nm_device_activate_ip4_state_in_conf (device)) { + nm_device_set_ip_iface (device, iface); + nm_device_activate_schedule_ip4_config_result (device, config); + } +} + +static NMActStageReturn +real_act_stage3_ip4_config_start (NMDevice *device, + NMIP4Config **out_config, + NMDeviceStateReason *reason) +{ + NMDeviceAdsl *self = NM_DEVICE_ADSL (device); + NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); + NMConnection *connection; + NMSettingAdsl *s_adsl; + NMActRequest *req; + GError *err = NULL; + NMActStageReturn ret = NM_ACT_STAGE_RETURN_FAILURE; + const char *iface = nm_device_get_iface (device); + const char *ppp_iface; + + req = nm_device_get_act_request (device); + g_assert (req); + + connection = nm_act_request_get_connection (req); + g_assert (req); + + s_adsl = nm_connection_get_setting_adsl (connection); + g_assert (s_adsl); + + /* PPPoE uses the NAS inteface, not the ATM interface */ + if (g_strcmp0 (nm_setting_adsl_get_protocol (s_adsl), NM_SETTING_ADSL_PROTOCOL_PPPOE) == 0) { + g_assert (priv->nas_ifname); + ppp_iface = priv->nas_ifname; + + nm_log_dbg (LOGD_ADSL, "(%s): starting PPPoE on NAS interface %s", + iface, priv->nas_ifname); + } else { + ppp_iface = iface; + nm_log_dbg (LOGD_ADSL, "(%s): starting PPPoA", iface); + } + + 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_CALLBACK (ppp_state_changed), + self); + g_signal_connect (priv->ppp_manager, "ip4-config", + G_CALLBACK (ppp_ip4_config), + self); + ret = NM_ACT_STAGE_RETURN_POSTPONE; + } else { + nm_log_warn (LOGD_ADSL, "(%s): PPP failed to start: %s", iface, err->message); + g_error_free (err); + + g_object_unref (priv->ppp_manager); + priv->ppp_manager = NULL; + + *reason = NM_DEVICE_STATE_REASON_PPP_START_FAILED; + } + + return ret; +} + +static void +real_deactivate (NMDevice *device) +{ + NMDeviceAdsl *self = NM_DEVICE_ADSL (device); + NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); + + if (priv->ppp_manager) { + g_object_unref (priv->ppp_manager); + priv->ppp_manager = NULL; + } + + if (priv->netlink_id) { + g_signal_handler_disconnect (priv->monitor, priv->netlink_id); + priv->netlink_id = 0; + } + + if (priv->brfd >= 0) { + close (priv->brfd); + priv->brfd = -1; + } + + /* FIXME: kernel has no way of explicitly deleting the 'nasX' interface yet, + * so it gets leaked. It does get destroyed when it's no longer in use, + * but we have no control over that. + */ + if (priv->nas_ifindex >= 0) + priv->nas_ifindex = -1; + g_free (priv->nas_ifname); + priv->nas_ifname = NULL; +} + +/**************************************************************/ + +static void +set_carrier (NMDeviceAdsl *self, const gboolean carrier) +{ + NMDeviceAdslPrivate *priv; + NMDeviceState state; + + g_return_if_fail (NM_IS_DEVICE (self)); + + priv = NM_DEVICE_ADSL_GET_PRIVATE (self); + + if (priv->carrier == carrier) + return; + + priv->carrier = carrier; + g_object_notify (G_OBJECT (self), NM_DEVICE_ADSL_CARRIER); + + state = nm_device_get_state (NM_DEVICE (self)); + nm_log_info (LOGD_HW, "(%s): carrier now %s (device state %d)", + nm_device_get_iface (NM_DEVICE (self)), + carrier ? "ON" : "OFF", + state); + + if (state == NM_DEVICE_STATE_UNAVAILABLE) { + if (priv->carrier) + nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_CARRIER); + } else if (state >= NM_DEVICE_STATE_DISCONNECTED) { + if (!priv->carrier) + nm_device_state_changed (NM_DEVICE (self), NM_DEVICE_STATE_UNAVAILABLE, NM_DEVICE_STATE_REASON_CARRIER); + } +} + +static gboolean +carrier_update_cb (gpointer user_data) +{ + NMDeviceAdsl *self = NM_DEVICE_ADSL (user_data); + GError *error = NULL; + gboolean carrier = FALSE; + char *path, *contents; + const char *iface; + gboolean success; + + iface = nm_device_get_iface (NM_DEVICE (self)); + + path = g_strdup_printf ("/sys/class/atm/%s/carrier", iface); + success = g_file_get_contents (path, &contents, NULL, &error); + g_free (path); + + if (!success) { + nm_log_dbg (LOGD_ADSL, "error reading %s: (%d) %s", + path, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + return TRUE; + } + + carrier = (gboolean) atoi (contents); + g_free (contents); + set_carrier (self, carrier); + return TRUE; +} + +/**************************************************************/ + +NMDevice * +nm_device_adsl_new (const char *udi, + const char *iface, + const char *driver) +{ + g_return_val_if_fail (udi != NULL, NULL); + + return (NMDevice *) g_object_new (NM_TYPE_DEVICE_ADSL, + NM_DEVICE_UDI, udi, + NM_DEVICE_IFACE, iface, + NM_DEVICE_DRIVER, driver, + NM_DEVICE_TYPE_DESC, "ADSL", + NM_DEVICE_DEVICE_TYPE, NM_DEVICE_TYPE_ADSL, + NULL); +} + +static int +get_atm_index (const char *iface, GError **error) +{ + char *path, *contents; + int idx = -1; + + path = g_strdup_printf ("/sys/class/atm/%s/atmindex", iface); + if (g_file_get_contents (path, &contents, NULL, error)) + idx = atoi (contents); + g_free (path); + g_free (contents); + return idx; +} + +static GObject* +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *object; + NMDeviceAdslPrivate *priv; + GError *error = NULL; + + object = G_OBJECT_CLASS (nm_device_adsl_parent_class)->constructor (type, + n_construct_params, + construct_params); + if (!object) + return NULL; + + priv = NM_DEVICE_ADSL_GET_PRIVATE (object); + + priv->atm_index = get_atm_index (nm_device_get_iface (NM_DEVICE (object)), &error); + if (priv->atm_index < 0) { + nm_log_dbg (LOGD_ADSL, "error reading ATM device index: (%d) %s", + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + g_object_unref (object); + return NULL; + } else { + nm_log_dbg (LOGD_ADSL, "(%s): ATM device index %d", + nm_device_get_iface (NM_DEVICE (object)), priv->atm_index); + } + + /* Poll the carrier */ + priv->carrier_poll_id = g_timeout_add_seconds (5, carrier_update_cb, object); + + return object; +} + +static void +dispose (GObject *object) +{ + NMDeviceAdsl *self = NM_DEVICE_ADSL (object); + NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); + + if (priv->disposed) { + G_OBJECT_CLASS (nm_device_adsl_parent_class)->dispose (object); + return; + } + + priv->disposed = TRUE; + + if (priv->carrier_poll_id) { + g_source_remove (priv->carrier_poll_id); + priv->carrier_poll_id = 0; + } + + if (priv->netlink_id) { + g_source_remove (priv->netlink_id); + priv->netlink_id = 0; + } + + if (priv->monitor) { + nm_netlink_monitor_unsubscribe (priv->monitor, RTNLGRP_LINK); + g_object_unref (priv->monitor); + priv->monitor = NULL; + } + + g_free (priv->nas_ifname); + priv->nas_ifname = NULL; + + G_OBJECT_CLASS (nm_device_adsl_parent_class)->dispose (object); +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMDeviceAdsl *self = NM_DEVICE_ADSL (object); + NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE(self); + + switch (prop_id) { + case PROP_CARRIER: + g_value_set_boolean (value, priv->carrier); + 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 +nm_device_adsl_init (NMDeviceAdsl *self) +{ + NMDeviceAdslPrivate *priv = NM_DEVICE_ADSL_GET_PRIVATE (self); + + priv->monitor = nm_netlink_monitor_get (); + nm_netlink_monitor_subscribe (priv->monitor, RTNLGRP_LINK, NULL); +} + +static void +nm_device_adsl_class_init (NMDeviceAdslClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + NMDeviceClass *parent_class = NM_DEVICE_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (NMDeviceAdslPrivate)); + + object_class->constructor = constructor; + object_class->dispose = dispose; + object_class->get_property = get_property; + object_class->set_property = set_property; + + parent_class->get_generic_capabilities = real_get_generic_capabilities; + parent_class->can_interrupt_activation = real_can_interrupt_activation; + parent_class->is_available = real_is_available; + + parent_class->check_connection_compatible = real_check_connection_compatible; + parent_class->get_best_auto_connection = real_get_best_auto_connection; + parent_class->complete_connection = real_complete_connection; + + parent_class->act_stage2_config = real_act_stage2_config; + parent_class->act_stage3_ip4_config_start = real_act_stage3_ip4_config_start; + parent_class->deactivate = real_deactivate; + + /* properties */ + g_object_class_install_property + (object_class, PROP_CARRIER, + g_param_spec_boolean (NM_DEVICE_ADSL_CARRIER, + "Carrier", + "Carrier", + FALSE, + G_PARAM_READABLE)); + + /* Signals */ + signals[PROPERTIES_CHANGED] = + nm_properties_changed_signal_new (object_class, + G_STRUCT_OFFSET (NMDeviceAdslClass, properties_changed)); + + dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), + &dbus_glib_nm_device_adsl_object_info); +} diff --git a/src/nm-device-adsl.h b/src/nm-device-adsl.h new file mode 100644 index 00000000..50ea43e3 --- /dev/null +++ b/src/nm-device-adsl.h @@ -0,0 +1,66 @@ +/* -*- 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. + * + * Author: Pantelis Koukousoulas <pktoss@gmail.com> + * Copyright (C) 2009 - 2011 Red Hat Inc. + */ + +#ifndef NM_DEVICE_ADSL_H +#define NM_DEVICE_ADSL_H + +#include <glib-object.h> + +// Parent class +#include "nm-device.h" + +G_BEGIN_DECLS + +#define NM_TYPE_DEVICE_ADSL (nm_device_adsl_get_type ()) +#define NM_DEVICE_ADSL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_ADSL, NMDeviceAdsl)) +#define NM_DEVICE_ADSL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_ADSL, NMDeviceAdslClass)) +#define NM_IS_DEVICE_ADSL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_ADSL)) +#define NM_IS_DEVICE_ADSL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_ADSL)) +#define NM_DEVICE_ADSL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_ADSL, NMDeviceAdslClass)) + +typedef enum { + NM_ADSL_ERROR_CONNECTION_NOT_ADSL = 0, + NM_ADSL_ERROR_CONNECTION_INVALID, + NM_ADSL_ERROR_CONNECTION_INCOMPATIBLE, +} NMAdslError; + +#define NM_DEVICE_ADSL_CARRIER "carrier" + +typedef struct { + NMDevice parent; +} NMDeviceAdsl; + +typedef struct { + NMDeviceClass parent; + + /* Signals */ + void (*properties_changed) (NMDeviceAdsl *device, GHashTable *properties); +} NMDeviceAdslClass; + +GType nm_device_adsl_get_type (void); + +NMDevice *nm_device_adsl_new (const char *udi, + const char *iface, + const char *driver); + +G_END_DECLS + +#endif /* NM_DEVICE_ADSL_H */ diff --git a/src/nm-device-bt.c b/src/nm-device-bt.c index 726762b6..f61aeb57 100644 --- a/src/nm-device-bt.c +++ b/src/nm-device-bt.c @@ -668,14 +668,18 @@ nm_device_bt_modem_removed (NMDeviceBt *self, NMModem *modem) if (modem != priv->modem) return FALSE; + /* Fail the device if the modem was removed while active */ state = nm_device_get_state (NM_DEVICE (self)); - nm_modem_device_state_changed (priv->modem, - NM_DEVICE_STATE_DISCONNECTED, - state, - NM_DEVICE_STATE_REASON_USER_REQUESTED); + if ( state == NM_DEVICE_STATE_ACTIVATED + || nm_device_is_activating (NM_DEVICE (self))) { + nm_device_state_changed (NM_DEVICE (self), + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_BT_FAILED); + } else { + g_object_unref (priv->modem); + priv->modem = NULL; + } - g_object_unref (priv->modem); - priv->modem = NULL; return TRUE; } diff --git a/src/nm-device-ethernet.c b/src/nm-device-ethernet.c index df0ae94f..ede31cc1 100644 --- a/src/nm-device-ethernet.c +++ b/src/nm-device-ethernet.c @@ -753,8 +753,9 @@ link_timeout_cb (gpointer user_data) req = nm_device_get_act_request (dev); if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED) { - nm_device_state_changed (dev, NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_SUPPLICANT_DISCONNECT); + nm_device_state_changed (dev, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT); return FALSE; } diff --git a/src/nm-device-modem.c b/src/nm-device-modem.c index 7f81e981..e7cd9259 100644 --- a/src/nm-device-modem.c +++ b/src/nm-device-modem.c @@ -311,11 +311,12 @@ real_set_enabled (NMDevice *device, gboolean enabled) nm_modem_set_mm_enabled (priv->modem, enabled); if (enabled == FALSE) { - state = nm_device_get_state (NM_DEVICE (device)); - if (state == NM_DEVICE_STATE_ACTIVATED) { - nm_device_state_changed (NM_DEVICE (device), + state = nm_device_get_state (device); + if (nm_device_is_activating (device) || state == NM_DEVICE_STATE_ACTIVATED) { + /* user-initiated action, hence DISCONNECTED not FAILED */ + nm_device_state_changed (device, NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_NONE); + NM_DEVICE_STATE_REASON_USER_REQUESTED); } } } diff --git a/src/nm-device-olpc-mesh.c b/src/nm-device-olpc-mesh.c index f6390c16..8e3cb952 100644 --- a/src/nm-device-olpc-mesh.c +++ b/src/nm-device-olpc-mesh.c @@ -55,6 +55,9 @@ #include "nm-manager.h" #include "nm-enum-types.h" #include "wifi-utils.h" +#if HAVE_WEXT +#include "wifi-utils-wext.h" +#endif /* This is a bug; but we can't really change API now... */ #include "NetworkManagerVPN.h" @@ -153,9 +156,16 @@ constructor (GType type, nm_device_get_iface (NM_DEVICE (self)), nm_device_get_ifindex (NM_DEVICE (self))); - priv->wifi_data = wifi_utils_init (nm_device_get_iface (NM_DEVICE (self)), - nm_device_get_ifindex (NM_DEVICE (self)), - FALSE); + /* + * The kernel driver now uses nl80211, but we force use of WEXT because + * the cfg80211 interactions are not quite ready to support access to + * mesh control through nl80211 just yet. + */ +#if HAVE_WEXT + priv->wifi_data = wifi_wext_init (nm_device_get_iface (NM_DEVICE (self)), + nm_device_get_ifindex (NM_DEVICE (self)), + FALSE); +#endif if (priv->wifi_data == NULL) { nm_log_warn (LOGD_HW | LOGD_OLPC_MESH, "(%s): failed to initialize WiFi driver", nm_device_get_iface (NM_DEVICE (self))); diff --git a/src/nm-device-private.h b/src/nm-device-private.h index 9b78db12..824beb5a 100644 --- a/src/nm-device-private.h +++ b/src/nm-device-private.h @@ -67,4 +67,6 @@ gboolean nm_device_dhcp4_renew (NMDevice *device, gboolean release); gboolean nm_device_match_ip_config (NMDevice *device, NMConnection *connection); +NMConnectionProvider *nm_device_get_connection_provider (NMDevice *device); + #endif /* NM_DEVICE_PRIVATE_H */ diff --git a/src/nm-device-vlan.c b/src/nm-device-vlan.c index 14be849f..b9c93234 100644 --- a/src/nm-device-vlan.c +++ b/src/nm-device-vlan.c @@ -643,17 +643,17 @@ nm_device_vlan_new (const char *udi, const char *iface, NMDevice *parent) g_object_unref (device); return NULL; } - priv->vlan_id = vlan_id; if ( parent_ifindex < 0 || parent_ifindex != nm_device_get_ip_ifindex (parent) - || priv->vlan_id < 0) { + || vlan_id < 0) { nm_log_warn (LOGD_DEVICE, "(%s): VLAN parent ifindex (%d) or VLAN ID (%d) invalid.", iface, parent_ifindex, priv->vlan_id); g_object_unref (device); return NULL; } + priv->vlan_id = vlan_id; priv->parent = g_object_ref (parent); priv->parent_state_id = g_signal_connect (priv->parent, "state-changed", diff --git a/src/nm-device-wifi.c b/src/nm-device-wifi.c index ed964a57..5fbbac7a 100644 --- a/src/nm-device-wifi.c +++ b/src/nm-device-wifi.c @@ -56,6 +56,7 @@ #include "nm-setting-ip4-config.h" #include "nm-setting-ip6-config.h" #include "nm-system.h" +#include "nm-manager-auth.h" #include "nm-settings-connection.h" #include "nm-enum-types.h" #include "wifi-utils.h" @@ -64,11 +65,15 @@ static gboolean impl_device_get_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" /* All of these are in seconds */ -#define SCAN_INTERVAL_MIN 0 +#define SCAN_INTERVAL_MIN 3 #define SCAN_INTERVAL_STEP 20 #define SCAN_INTERVAL_MAX 120 @@ -138,7 +143,7 @@ struct _NMDeviceWifiPrivate { guint32 rate; gboolean enabled; /* rfkilled or not */ - glong scheduled_scan_time; + time_t scheduled_scan_time; guint8 scan_interval; /* seconds */ guint pending_scan_id; guint scanlist_cull_id; @@ -153,7 +158,7 @@ struct _NMDeviceWifiPrivate { NMDeviceWifiCapabilities capabilities; }; -static gboolean request_wireless_scan (gpointer user_data); +static gboolean check_scanning_allowed (NMDeviceWifi *self); static void schedule_scan (NMDeviceWifi *self, gboolean backoff); @@ -193,6 +198,8 @@ static void supplicant_iface_notify_scanning_cb (NMSupplicantInterface * iface, static void schedule_scanlist_cull (NMDeviceWifi *self); +static gboolean request_wireless_scan (gpointer user_data); + /*****************************************************************/ #define NM_WIFI_ERROR (nm_wifi_error_quark ()) @@ -1014,14 +1021,6 @@ real_check_connection_compatible (NMDevice *device, const GByteArray *mac; const GSList *mac_blacklist, *mac_blacklist_iter; - if (is_adhoc_wpa (connection)) { - g_set_error_literal (error, - NM_WIFI_ERROR, - NM_WIFI_ERROR_CONNECTION_INCOMPATIBLE, - "WPA Ad-Hoc disabled due to kernel bugs"); - return FALSE; - } - s_con = nm_connection_get_setting_connection (connection); g_assert (s_con); @@ -1040,6 +1039,7 @@ real_check_connection_compatible (NMDevice *device, return FALSE; } + mac = nm_setting_wireless_get_mac_address (s_wireless); if (mac && memcmp (mac->data, &priv->perm_hw_addr, ETH_ALEN)) { g_set_error (error, @@ -1067,6 +1067,14 @@ real_check_connection_compatible (NMDevice *device, } } + if (is_adhoc_wpa (connection)) { + g_set_error_literal (error, + NM_WIFI_ERROR, + NM_WIFI_ERROR_CONNECTION_INCOMPATIBLE, + "WPA Ad-Hoc disabled due to kernel bugs"); + return FALSE; + } + // FIXME: check channel/freq/band against bands the hardware supports // FIXME: check encryption against device capabilities // FIXME: check bitrate against device capabilities @@ -1233,9 +1241,9 @@ real_complete_connection (NMDevice *device, */ if (is_adhoc_wpa (connection)) { g_set_error_literal (error, - NM_SETTING_WIRELESS_ERROR, - NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY, - "WPA Ad-Hoc disabled due to kernel bugs"); + NM_SETTING_WIRELESS_ERROR, + NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY, + "WPA Ad-Hoc disabled due to kernel bugs"); return FALSE; } @@ -1257,9 +1265,9 @@ real_complete_connection (NMDevice *device, /* Make sure the setting MAC (if any) matches the device's permanent MAC */ if (memcmp (setting_mac->data, priv->perm_hw_addr, ETH_ALEN)) { g_set_error (error, - NM_SETTING_WIRELESS_ERROR, - NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY, - NM_SETTING_WIRELESS_MAC_ADDRESS); + NM_SETTING_WIRELESS_ERROR, + NM_SETTING_WIRELESS_ERROR_INVALID_PROPERTY, + NM_SETTING_WIRELESS_MAC_ADDRESS); return FALSE; } } else { @@ -1442,6 +1450,80 @@ impl_device_get_access_points (NMDeviceWifi *self, return TRUE; } +static void +request_scan_cb (NMDevice *device, + DBusGMethodInvocation *context, + GError *error, + gpointer user_data) +{ + NMDeviceWifi *self = NM_DEVICE_WIFI (device); + + if (error) { + dbus_g_method_return_error (context, error); + g_clear_error (&error); + } else if (!check_scanning_allowed (self)) { + error = g_error_new_literal (NM_WIFI_ERROR, + NM_WIFI_ERROR_SCAN_NOT_ALLOWED, + "Scanning not allowed at this time"); + dbus_g_method_return_error (context, error); + g_error_free (error); + } else { + cancel_pending_scan (self); + request_wireless_scan (self); + dbus_g_method_return (context); + } +} + +static void +impl_device_request_scan (NMDeviceWifi *self, + GHashTable *options, + DBusGMethodInvocation *context) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + NMDevice *device = NM_DEVICE (self); + time_t last_scan; + GError *error; + + if ( !priv->enabled + || !priv->supplicant.iface + || nm_device_get_state (device) < NM_DEVICE_STATE_DISCONNECTED + || nm_device_is_activating (device)) { + error = g_error_new_literal (NM_WIFI_ERROR, + NM_WIFI_ERROR_SCAN_NOT_ALLOWED, + "Scanning not allowed while unavailable or activating"); + goto error; + } + + if (nm_supplicant_interface_get_scanning (priv->supplicant.iface)) { + error = g_error_new_literal (NM_WIFI_ERROR, + NM_WIFI_ERROR_SCAN_NOT_ALLOWED, + "Scanning not allowed while already scanning"); + goto error; + } + + last_scan = nm_supplicant_interface_get_last_scan_time (priv->supplicant.iface); + if ((time (NULL) - last_scan) < 10) { + error = g_error_new_literal (NM_WIFI_ERROR, + NM_WIFI_ERROR_SCAN_NOT_ALLOWED, + "Scanning not allowed immediately following previous scan"); + goto error; + } + + /* Ask the manager to authenticate this request for us */ + g_signal_emit_by_name (device, + NM_DEVICE_AUTH_REQUEST, + context, + NM_AUTH_PERMISSION_NETWORK_CONTROL, + TRUE, + request_scan_cb, + NULL); + return; + +error: + dbus_g_method_return_error (context, error); + g_error_free (error); +} + static gboolean scanning_allowed (NMDeviceWifi *self) { @@ -1544,20 +1626,102 @@ check_scanning_allowed (NMDeviceWifi *self) } static gboolean +hidden_filter_func (NMConnectionProvider *provider, + NMConnection *connection, + gpointer user_data) +{ + NMSettingWireless *s_wifi; + + s_wifi = (NMSettingWireless *) nm_connection_get_setting_wireless (connection); + return s_wifi ? nm_setting_wireless_get_hidden (s_wifi) : FALSE; +} + +static GPtrArray * +build_hidden_probe_list (NMDeviceWifi *self) +{ + NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); + guint max_scan_ssids = nm_supplicant_interface_get_max_scan_ssids (priv->supplicant.iface); + NMConnectionProvider *provider = nm_device_get_connection_provider (NM_DEVICE (self)); + GSList *connections, *iter; + GPtrArray *ssids = NULL; + static GByteArray *nullssid = NULL; + + /* Need at least two: wildcard SSID and one or more hidden SSIDs */ + if (max_scan_ssids < 2) + return NULL; + + /* Static wildcard SSID used for every scan */ + if (G_UNLIKELY (nullssid == NULL)) + nullssid = g_byte_array_new (); + + connections = nm_connection_provider_get_best_connections (provider, + max_scan_ssids - 1, + NM_SETTING_WIRELESS_SETTING_NAME, + NULL, + hidden_filter_func, + NULL); + if (connections && connections->data) { + ssids = g_ptr_array_sized_new (max_scan_ssids - 1); + g_ptr_array_add (ssids, nullssid); /* Add wildcard SSID */ + } + + for (iter = connections; iter; iter = g_slist_next (iter)) { + NMConnection *connection = iter->data; + NMSettingWireless *s_wifi; + const GByteArray *ssid; + + s_wifi = (NMSettingWireless *) nm_connection_get_setting_wireless (connection); + g_assert (s_wifi); + ssid = nm_setting_wireless_get_ssid (s_wifi); + g_assert (ssid); + g_ptr_array_add (ssids, (gpointer) ssid); + } + g_slist_free (connections); + + return ssids; +} + +static gboolean request_wireless_scan (gpointer user_data) { NMDeviceWifi *self = NM_DEVICE_WIFI (user_data); NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); gboolean backoff = FALSE; + GPtrArray *ssids = NULL; if (check_scanning_allowed (self)) { nm_log_dbg (LOGD_WIFI_SCAN, "(%s): scanning requested", nm_device_get_iface (NM_DEVICE (self))); - if (nm_supplicant_interface_request_scan (priv->supplicant.iface)) { + ssids = build_hidden_probe_list (self); + + if (nm_logging_level_enabled (LOGL_DEBUG)) { + if (ssids) { + guint i; + char *foo; + + for (i = 0; i < ssids->len; i++) { + foo = nm_utils_ssid_to_utf8 (g_ptr_array_index (ssids, i)); + nm_log_dbg (LOGD_WIFI_SCAN, "(%s): (%d) probe scanning SSID '%s'", + nm_device_get_iface (NM_DEVICE (self)), + i, foo ? foo : "<hidden>"); + g_free (foo); + } + } else { + nm_log_dbg (LOGD_WIFI_SCAN, "(%s): no SSIDs to probe scan", + nm_device_get_iface (NM_DEVICE (self))); + } + } + + if (nm_supplicant_interface_request_scan (priv->supplicant.iface, ssids)) { /* success */ backoff = TRUE; } + + if (ssids) { + /* Elements owned by the connections, so we don't free them here */ + g_ptr_array_free (ssids, TRUE); + } } else { nm_log_dbg (LOGD_WIFI_SCAN, "(%s): scan requested but not allowed at this time", nm_device_get_iface (NM_DEVICE (self))); @@ -1579,13 +1743,11 @@ static void schedule_scan (NMDeviceWifi *self, gboolean backoff) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - GTimeVal now; - - g_get_current_time (&now); + time_t now = time (NULL); /* Cancel the pending scan if it would happen later than (now + the scan_interval) */ if (priv->pending_scan_id) { - if (now.tv_sec + priv->scan_interval < priv->scheduled_scan_time) + if (now + priv->scan_interval < priv->scheduled_scan_time) cancel_pending_scan (self); } @@ -1600,7 +1762,7 @@ schedule_scan (NMDeviceWifi *self, gboolean backoff) request_wireless_scan, self); - priv->scheduled_scan_time = now.tv_sec + priv->scan_interval; + priv->scheduled_scan_time = now + priv->scan_interval; if (backoff && (priv->scan_interval < (SCAN_INTERVAL_MAX / factor))) { priv->scan_interval += (SCAN_INTERVAL_STEP / factor); /* Ensure the scan interval will never be less than 20s... */ @@ -1643,8 +1805,7 @@ supplicant_iface_scan_done_cb (NMSupplicantInterface *iface, nm_device_get_iface (NM_DEVICE (self)), success ? "successful" : "failed"); - if (check_scanning_allowed (self)) - schedule_scan (self, TRUE); + schedule_scan (self, success); /* Ensure that old APs get removed, which otherwise only * happens when there are new BSSes. @@ -1763,7 +1924,7 @@ static gboolean cull_scan_list (NMDeviceWifi *self) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self); - GTimeVal now; + time_t now = time (NULL); GSList *outdated_list = NULL; GSList *elt; guint32 removed = 0, total = 0; @@ -1776,7 +1937,6 @@ cull_scan_list (NMDeviceWifi *self) /* Walk the access point list and remove any access points older than * three times the inactive scan interval. */ - g_get_current_time (&now); 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; @@ -1796,7 +1956,7 @@ cull_scan_list (NMDeviceWifi *self) && g_object_get_data (G_OBJECT (ap), WPAS_REMOVED_TAG) == NULL) continue; - if (nm_ap_get_last_seen (ap) + prune_interval_s < now.tv_sec) + if (nm_ap_get_last_seen (ap) + prune_interval_s < now) outdated_list = g_slist_append (outdated_list, ap); } @@ -1886,7 +2046,6 @@ supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface, { NMDeviceState state; NMAccessPoint *ap; - GTimeVal now; g_return_if_fail (self != NULL); g_return_if_fail (object_path != NULL); @@ -1899,10 +2058,8 @@ supplicant_iface_bss_updated_cb (NMSupplicantInterface *iface, /* Update the AP's last-seen property */ ap = get_ap_by_supplicant_path (self, object_path); - if (ap) { - g_get_current_time (&now); - nm_ap_set_last_seen (ap, now.tv_sec); - } + if (ap) + nm_ap_set_last_seen (ap, (guint32) time (NULL)); /* Remove outdated access points */ schedule_scanlist_cull (self); @@ -1991,8 +2148,11 @@ link_timeout_cb (gpointer user_data) * to reassociate within the timeout period, so the connection must * fail. */ - if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED) - nm_device_state_changed (dev, NM_DEVICE_STATE_DISCONNECTED, NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT); + if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED) { + nm_device_state_changed (dev, + NM_DEVICE_STATE_FAILED, + NM_DEVICE_STATE_REASON_SUPPLICANT_TIMEOUT); + } return FALSE; } @@ -3365,7 +3525,7 @@ get_property (GObject *object, guint prop_id, static void set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) + const GValue *value, GParamSpec *pspec) { NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (object); @@ -3409,7 +3569,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass) parent_class->is_available = real_is_available; parent_class->check_connection_compatible = real_check_connection_compatible; parent_class->complete_connection = real_complete_connection; - parent_class->set_enabled = real_set_enabled; + parent_class->set_enabled = real_set_enabled; parent_class->act_stage1_prepare = real_act_stage1_prepare; parent_class->act_stage2_config = real_act_stage2_config; diff --git a/src/nm-device-wifi.h b/src/nm-device-wifi.h index 1e665fc3..b22c78b3 100644 --- a/src/nm-device-wifi.h +++ b/src/nm-device-wifi.h @@ -46,6 +46,7 @@ typedef enum { NM_WIFI_ERROR_CONNECTION_INVALID, /*< nick=ConnectionInvalid >*/ NM_WIFI_ERROR_CONNECTION_INCOMPATIBLE, /*< nick=ConnectionIncompatible >*/ NM_WIFI_ERROR_ACCESS_POINT_NOT_FOUND, /*< nick=AccessPointNotFound >*/ + NM_WIFI_ERROR_SCAN_NOT_ALLOWED, /*< nick=ScanNotAllowed >*/ } NMWifiError; #define NM_DEVICE_WIFI_HW_ADDRESS "hw-address" diff --git a/src/nm-device-wired.c b/src/nm-device-wired.c index a476faad..60e5f262 100644 --- a/src/nm-device-wired.c +++ b/src/nm-device-wired.c @@ -162,6 +162,7 @@ set_carrier (NMDeviceWired *self, { NMDeviceWiredPrivate *priv; NMDeviceState state; + guint32 caps; g_return_if_fail (NM_IS_DEVICE (self)); @@ -172,16 +173,25 @@ set_carrier (NMDeviceWired *self, /* Clear any previous deferred action */ carrier_action_defer_clear (self); + /* Warn if we try to set carrier down on a device that + * doesn't support carrier detect. These devices assume + * the carrier is always up. + */ + caps = nm_device_get_capabilities (NM_DEVICE (self)); + g_return_if_fail (caps & NM_DEVICE_CAP_CARRIER_DETECT); + priv->carrier = carrier; g_object_notify (G_OBJECT (self), "carrier"); state = nm_device_get_state (NM_DEVICE (self)); - nm_log_info (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (NM_DEVICE (self)), - "(%s): carrier now %s (device state %d%s)", - nm_device_get_iface (NM_DEVICE (self)), - carrier ? "ON" : "OFF", - state, - defer_action ? ", deferring action for 4 seconds" : ""); + if (state >= NM_DEVICE_STATE_UNAVAILABLE) { + nm_log_info (LOGD_HW | NM_DEVICE_WIRED_LOG_LEVEL (NM_DEVICE (self)), + "(%s): carrier now %s (device state %d%s)", + nm_device_get_iface (NM_DEVICE (self)), + carrier ? "ON" : "OFF", + state, + defer_action ? ", deferring action for 4 seconds" : ""); + } if (defer_action) priv->carrier_action_defer_id = g_timeout_add_seconds (4, carrier_action_defer_cb, self); @@ -200,10 +210,8 @@ carrier_on (NMNetlinkMonitor *monitor, /* Make sure signal is for us */ if (idx == nm_device_get_ifindex (device)) { - /* Ignore spurious netlink messages */ caps = nm_device_get_capabilities (device); - if (!(caps & NM_DEVICE_CAP_CARRIER_DETECT)) - return; + g_return_if_fail (caps & NM_DEVICE_CAP_CARRIER_DETECT); set_carrier (self, TRUE, FALSE); set_speed (self, ethtool_get_speed (self)); @@ -224,10 +232,8 @@ carrier_off (NMNetlinkMonitor *monitor, NMDeviceState state; gboolean defer = FALSE; - /* Ignore spurious netlink messages */ caps = nm_device_get_capabilities (device); - if (!(caps & NM_DEVICE_CAP_CARRIER_DETECT)) - return; + g_return_if_fail (caps & NM_DEVICE_CAP_CARRIER_DETECT); /* Defer carrier-off event actions while connected by a few seconds * so that tripping over a cable, power-cycling a switch, or breaking @@ -350,11 +356,15 @@ static gboolean real_hw_bring_up (NMDevice *dev, gboolean *no_firmware) { gboolean success, carrier; + guint32 caps; success = nm_system_iface_set_up (nm_device_get_ip_ifindex (dev), TRUE, no_firmware); if (success) { - carrier = get_carrier_sync (NM_DEVICE_WIRED (dev)); - set_carrier (NM_DEVICE_WIRED (dev), carrier, carrier ? FALSE : TRUE); + caps = nm_device_get_capabilities (dev); + if (caps & NM_DEVICE_CAP_CARRIER_DETECT) { + carrier = get_carrier_sync (NM_DEVICE_WIRED (dev)); + set_carrier (NM_DEVICE_WIRED (dev), carrier, carrier ? FALSE : TRUE); + } } return success; } diff --git a/src/nm-device.c b/src/nm-device.c index 1dc94ee9..cf01003c 100644 --- a/src/nm-device.c +++ b/src/nm-device.c @@ -27,6 +27,8 @@ #include <string.h> #include <unistd.h> #include <errno.h> +#include <linux/sockios.h> +#include <linux/ethtool.h> #include <sys/ioctl.h> #include <signal.h> #include <sys/types.h> @@ -43,7 +45,6 @@ #include "nm-system.h" #include "nm-dhcp-manager.h" #include "nm-dbus-manager.h" -#include "nm-dns-manager.h" #include "nm-utils.h" #include "nm-logging.h" #include "nm-netlink-monitor.h" @@ -61,6 +62,9 @@ #include "nm-properties-changed-signal.h" #include "nm-enum-types.h" #include "nm-settings-connection.h" +#include "nm-connection-provider.h" +#include "nm-posix-signals.h" +#include "nm-manager-auth.h" static void impl_device_disconnect (NMDevice *device, DBusGMethodInvocation *context); @@ -87,8 +91,10 @@ nm_device_error_quark (void) enum { STATE_CHANGED, - DISCONNECT_REQUEST, AUTOCONNECT_ALLOWED, + AUTH_REQUEST, + IP4_CONFIG_CHANGED, + IP6_CONFIG_CHANGED, LAST_SIGNAL, }; static guint signals[LAST_SIGNAL] = { 0 }; @@ -99,6 +105,8 @@ enum { PROP_IFACE, PROP_IP_IFACE, PROP_DRIVER, + PROP_DRIVER_VERSION, + PROP_FIRMWARE_VERSION, PROP_CAPABILITIES, PROP_IP4_ADDRESS, PROP_IP4_CONFIG, @@ -110,6 +118,7 @@ enum { PROP_ACTIVE_CONNECTION, PROP_DEVICE_TYPE, PROP_MANAGED, + PROP_AUTOCONNECT, PROP_FIRMWARE_MISSING, PROP_TYPE_DESC, PROP_RFKILL_TYPE, @@ -117,6 +126,8 @@ enum { LAST_PROP }; +#define DEFAULT_AUTOCONNECT TRUE + /***********************************************************/ G_DEFINE_ABSTRACT_TYPE (NMDevice, nm_device, G_TYPE_OBJECT) @@ -153,6 +164,8 @@ typedef struct { char * type_desc; guint32 capabilities; char * driver; + char * driver_version; + char * firmware_version; gboolean managed; /* whether managed by NM or not */ RfKillType rfkill_type; gboolean firmware_missing; @@ -221,11 +234,13 @@ typedef struct { /* IP6 config from DHCP */ NMIP6Config * dhcp6_ip6_config; - /* inhibit autoconnect feature */ - gboolean autoconnect_inhibit; + /* allow autoconnect feature */ + gboolean autoconnect; /* master interface for bridge, bond, vlan, etc */ NMDevice * master; + + NMConnectionProvider *con_provider; } NMDevicePrivate; static void nm_device_take_down (NMDevice *dev, gboolean wait, NMDeviceStateReason reason); @@ -239,7 +254,6 @@ static gboolean nm_device_set_ip4_config (NMDevice *dev, NMDeviceStateReason *reason); static gboolean nm_device_set_ip6_config (NMDevice *dev, NMIP6Config *config, - gboolean assumed, NMDeviceStateReason *reason); static gboolean nm_device_activate_ip6_config_commit (gpointer user_data); @@ -259,6 +273,7 @@ nm_device_init (NMDevice *self) priv->state_reason = NM_DEVICE_STATE_REASON_NONE; priv->dhcp_timeout = 0; priv->rfkill_type = RFKILL_TYPE_UNKNOWN; + priv->autoconnect = DEFAULT_AUTOCONNECT; } static void @@ -332,18 +347,57 @@ update_ip6_privacy_save (NMDevice *self) } } +/* + * Get driver info from SIOCETHTOOL ioctl() for 'iface' + * Returns driver and firmware versions to 'driver_version and' 'firmware_version' + */ +static gboolean +device_get_driver_info (const char *iface, char **driver_version, char **firmware_version) +{ + struct ethtool_drvinfo drvinfo; + struct ifreq req; + int fd; + + fd = socket (PF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + nm_log_warn (LOGD_HW, "couldn't open control socket."); + return FALSE; + } + + /* Get driver and firmware version info */ + memset (&req, 0, sizeof (struct ifreq)); + strncpy (req.ifr_name, iface, IFNAMSIZ); + drvinfo.cmd = ETHTOOL_GDRVINFO; + req.ifr_data = &drvinfo; + + errno = 0; + if (ioctl (fd, SIOCETHTOOL, &req) < 0) { + nm_log_dbg (LOGD_HW, "SIOCETHTOOL ioctl() failed: cmd=ETHTOOL_GDRVINFO, iface=%s, errno=%d", + iface, errno); + close (fd); + return FALSE; + } + if (driver_version) + *driver_version = g_strdup (drvinfo.version); + if (firmware_version) + *firmware_version = g_strdup (drvinfo.fw_version); + + close (fd); + return TRUE; +} + static GObject* constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) + guint n_construct_params, + GObjectConstructParam *construct_params) { GObject *object; NMDevice *dev; NMDevicePrivate *priv; object = G_OBJECT_CLASS (nm_device_parent_class)->constructor (type, - n_construct_params, - construct_params); + n_construct_params, + construct_params); if (!object) return NULL; @@ -370,6 +424,8 @@ constructor (GType type, priv->fw_manager = nm_firewall_manager_get (); + device_get_driver_info (priv->iface, &priv->driver_version, &priv->firmware_version); + update_accept_ra_save (dev); update_ip6_privacy_save (dev); @@ -503,7 +559,8 @@ nm_device_set_ip_iface (NMDevice *self, const char *iface) priv->ip_iface = g_strdup (iface); if (priv->ip_iface) { priv->ip_ifindex = nm_netlink_iface_to_index (priv->ip_iface); - if (priv->ip_ifindex < 0) { + if (priv->ip_ifindex <= 0) { + /* Device IP interface must always be a kernel network interface */ nm_log_warn (LOGD_HW, "(%s): failed to look up interface index", iface); } } @@ -526,6 +583,22 @@ nm_device_get_driver (NMDevice *self) return NM_DEVICE_GET_PRIVATE (self)->driver; } +const char * +nm_device_get_driver_version (NMDevice *self) +{ + g_return_val_if_fail (self != NULL, NULL); + + return NM_DEVICE_GET_PRIVATE (self)->driver_version; +} + +const char * +nm_device_get_firmware_version (NMDevice *self) +{ + g_return_val_if_fail (self != NULL, NULL); + + return NM_DEVICE_GET_PRIVATE (self)->firmware_version; +} + /* * Get/set functions for type @@ -539,12 +612,52 @@ nm_device_get_device_type (NMDevice *self) } +/** + * nm_device_get_priority(): + * @dev: the #NMDevice + * + * Returns: the device's routing priority. Lower numbers means a "better" + * device, eg higher priority. + */ int nm_device_get_priority (NMDevice *dev) { - g_return_val_if_fail (NM_IS_DEVICE (dev), -1); + g_return_val_if_fail (NM_IS_DEVICE (dev), 100); - return (int) nm_device_get_device_type (dev); + /* Device 'priority' is used for two things: + * + * a) two devices on the same IP subnet: the "better" (ie, lower number) + * device is the default outgoing device for that subnet + * b) default route: the "better" device gets the default route. This can + * always be modified by setting a connection to never-default=TRUE, in + * which case that device will never take the default route when + * it's using that connection. + */ + + switch (nm_device_get_device_type (dev)) { + case NM_DEVICE_TYPE_ETHERNET: + return 1; + case NM_DEVICE_TYPE_INFINIBAND: + return 2; + case NM_DEVICE_TYPE_ADSL: + return 3; + case NM_DEVICE_TYPE_WIMAX: + return 4; + case NM_DEVICE_TYPE_BOND: + return 5; + case NM_DEVICE_TYPE_VLAN: + return 6; + case NM_DEVICE_TYPE_MODEM: + return 7; + case NM_DEVICE_TYPE_BT: + return 8; + case NM_DEVICE_TYPE_WIFI: + return 9; + case NM_DEVICE_TYPE_OLPC_MESH: + return 10; + default: + return 20; + } } @@ -585,6 +698,30 @@ nm_device_get_type_desc (NMDevice *self) return NM_DEVICE_GET_PRIVATE (self)->type_desc; } +void +nm_device_set_connection_provider (NMDevice *device, + NMConnectionProvider *provider) +{ + NMDevicePrivate *priv; + + g_return_if_fail (device != NULL); + g_return_if_fail (provider != NULL); + g_return_if_fail (NM_IS_CONNECTION_PROVIDER (provider)); + + priv = NM_DEVICE_GET_PRIVATE (device); + g_return_if_fail (priv->con_provider == NULL); + + priv->con_provider = provider; +} + +NMConnectionProvider * +nm_device_get_connection_provider (NMDevice *device) +{ + g_return_val_if_fail (device != NULL, NULL); + + return NM_DEVICE_GET_PRIVATE (device)->con_provider; +} + /** * nm_device_enslave_slave: * @dev: the master device @@ -716,10 +853,10 @@ nm_device_autoconnect_allowed (NMDevice *self) g_value_take_object (&instance, self); g_value_init (&retval, G_TYPE_BOOLEAN); - if (priv->autoconnect_inhibit) - g_value_set_boolean (&retval, FALSE); - else + if (priv->autoconnect) g_value_set_boolean (&retval, TRUE); + else + g_value_set_boolean (&retval, FALSE); /* Use g_signal_emitv() rather than g_signal_emit() to avoid the return * value being changed if no handlers are connected */ @@ -776,14 +913,6 @@ nm_device_complete_connection (NMDevice *self, if (success) success = nm_connection_verify (connection, error); - /* If ip6-privacy is unknown, enable it with temporary address preferred */ - if (success) { - NMSettingIP6Config *s_ip6 = nm_connection_get_setting_ip6_config (connection); - if (s_ip6 && nm_setting_ip6_config_get_ip6_privacy (s_ip6) == NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN) - g_object_set (s_ip6, NM_SETTING_IP6_CONFIG_IP6_PRIVACY, - NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR, NULL); - } - return success; } @@ -1311,6 +1440,12 @@ aipd_child_setup (gpointer user_data G_GNUC_UNUSED) */ pid_t pid = getpid (); setpgid (pid, pid); + + /* + * We blocked signals in main(). We need to restore original signal + * mask for avahi-autoipd here so that it can receive signals. + */ + nm_unblock_posix_signals (NULL); } static NMActStageReturn @@ -1715,6 +1850,10 @@ merge_ip6_configs (NMIP6Config *dst, NMIP6Config *src) for (i = 0; i < nm_ip6_config_get_num_nameservers (src); i++) nm_ip6_config_add_nameserver (dst, nm_ip6_config_get_nameserver (src, i)); + /* default gateway */ + if (!nm_ip6_config_get_gateway (dst)) + nm_ip6_config_set_gateway (dst, nm_ip6_config_get_gateway (src)); + /* routes */ for (i = 0; i < nm_ip6_config_get_num_routes (src); i++) nm_ip6_config_add_route (dst, nm_ip6_config_get_route (src, i)); @@ -1738,7 +1877,7 @@ ip6_config_merge_and_apply (NMDevice *self, { NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (self); NMConnection *connection; - gboolean assumed, success; + gboolean success; NMIP6Config *composite; connection = nm_device_get_connection (self); @@ -1761,8 +1900,7 @@ ip6_config_merge_and_apply (NMDevice *self, /* Merge user overrides into the composite config */ nm_utils_merge_ip6_config (composite, nm_connection_get_setting_ip6_config (connection)); - assumed = nm_act_request_get_assumed (priv->act_request); - success = nm_device_set_ip6_config (self, composite, assumed, out_reason); + success = nm_device_set_ip6_config (self, composite, out_reason); g_object_unref (composite); return success; } @@ -2532,6 +2670,8 @@ share_child_setup (gpointer user_data G_GNUC_UNUSED) /* We are in the child process at this point */ pid_t pid = getpid (); setpgid (pid, pid); + + nm_unblock_posix_signals (NULL); } static gboolean @@ -3092,7 +3232,7 @@ nm_device_deactivate (NMDevice *self, NMDeviceStateReason reason) /* Take out any entries in the routing table and any IP address the device had. */ ifindex = nm_device_get_ip_ifindex (self); family = tried_ipv6 ? AF_UNSPEC : AF_INET; - if (ifindex >= 0) { + if (ifindex > 0) { nm_system_iface_flush_routes (ifindex, family); nm_system_iface_flush_addresses (ifindex, family); } @@ -3100,35 +3240,59 @@ nm_device_deactivate (NMDevice *self, NMDeviceStateReason reason) /* Clean up nameservers and addresses */ nm_device_set_ip4_config (self, NULL, FALSE, &ignored); - nm_device_set_ip6_config (self, NULL, FALSE, &ignored); + nm_device_set_ip6_config (self, NULL, &ignored); } -gboolean -nm_device_disconnect (NMDevice *device, GError **error) +static void +disconnect_cb (NMDevice *device, + DBusGMethodInvocation *context, + GError *error, + gpointer user_data) { - NMDevicePrivate *priv; - - g_return_val_if_fail (device != NULL, FALSE); - g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); + NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); + GError *local = NULL; - priv = NM_DEVICE_GET_PRIVATE (device); - if (priv->state <= NM_DEVICE_STATE_DISCONNECTED) { - g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_NOT_ACTIVE, - "Cannot disconnect an inactive device."); - return FALSE; + if (error) + dbus_g_method_return_error (context, error); + else { + /* Authorized */ + if (priv->state <= NM_DEVICE_STATE_DISCONNECTED) { + 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); + } else { + priv->autoconnect = FALSE; + nm_device_state_changed (device, + NM_DEVICE_STATE_DISCONNECTED, + NM_DEVICE_STATE_REASON_USER_REQUESTED); + dbus_g_method_return (context); + } } - - priv->autoconnect_inhibit = TRUE; - nm_device_state_changed (device, - NM_DEVICE_STATE_DISCONNECTED, - NM_DEVICE_STATE_REASON_USER_REQUESTED); - return TRUE; } static void impl_device_disconnect (NMDevice *device, DBusGMethodInvocation *context) { - g_signal_emit (device, signals[DISCONNECT_REQUEST], 0, context); + GError *error = NULL; + + if (NM_DEVICE_GET_PRIVATE (device)->act_request == NULL) { + 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); + return; + } + + /* Ask the manager to authenticate this request for us */ + g_signal_emit (device, signals[AUTH_REQUEST], 0, + context, + NM_AUTH_PERMISSION_NETWORK_CONTROL, + TRUE, + disconnect_cb, + NULL); } static gboolean @@ -3222,6 +3386,7 @@ nm_device_activate (NMDevice *self, NMActRequest *req, GError **error) } priv->act_request = g_object_ref (req); + g_object_notify (G_OBJECT (self), NM_DEVICE_ACTIVE_CONNECTION); if (!nm_act_request_get_assumed (req)) { NMActiveConnection *dep_ac; @@ -3345,7 +3510,6 @@ nm_device_set_ip4_config (NMDevice *self, NMIP4Config *old_config = NULL; gboolean success = TRUE; NMIP4ConfigCompareFlags diff = NM_IP4_COMPARE_FLAG_ALL; - NMDnsManager *dns_mgr; int ip_ifindex; g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); @@ -3353,23 +3517,18 @@ nm_device_set_ip4_config (NMDevice *self, priv = NM_DEVICE_GET_PRIVATE (self); ip_iface = nm_device_get_ip_iface (self); + ip_ifindex = nm_device_get_ip_ifindex (self); old_config = priv->ip4_config; - if (new_config && old_config) + if (new_config && old_config) { diff = nm_ip4_config_diff (new_config, old_config); - - /* No actual change, do nothing */ - if (diff == NM_IP4_COMPARE_FLAG_NONE) + if (diff == NM_IP4_COMPARE_FLAG_NONE) + return TRUE; /* no actual change */ + } else if (!new_config && !old_config) return TRUE; - dns_mgr = nm_dns_manager_get (NULL); - if (old_config) { - /* Remove any previous IP4 Config from the DNS manager */ - nm_dns_manager_remove_ip4_config (dns_mgr, ip_iface, old_config); - g_object_unref (old_config); - priv->ip4_config = NULL; - } + priv->ip4_config = NULL; if (new_config) { priv->ip4_config = g_object_ref (new_config); @@ -3377,25 +3536,22 @@ nm_device_set_ip4_config (NMDevice *self, /* Don't touch the device's actual IP config if the connection is * assumed when NM starts. */ - if (!assumed) { - ip_ifindex = nm_device_get_ip_ifindex (self); + if (!assumed) success = nm_system_apply_ip4_config (ip_ifindex, new_config, nm_device_get_priority (self), diff); - } if (success || assumed) { /* Export over D-Bus */ if (!nm_ip4_config_get_dbus_path (new_config)) nm_ip4_config_export (new_config); - - /* Add the DNS information to the DNS manager */ - nm_dns_manager_add_ip4_config (dns_mgr, ip_iface, new_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT); - _update_ip4_address (self); } } - g_object_unref (dns_mgr); 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) + g_object_unref (old_config); return success; } @@ -3403,7 +3559,6 @@ nm_device_set_ip4_config (NMDevice *self, static gboolean nm_device_set_ip6_config (NMDevice *self, NMIP6Config *new_config, - gboolean assumed, NMDeviceStateReason *reason) { NMDevicePrivate *priv; @@ -3411,7 +3566,6 @@ nm_device_set_ip6_config (NMDevice *self, NMIP6Config *old_config = NULL; gboolean success = TRUE; NMIP6ConfigCompareFlags diff = NM_IP6_COMPARE_FLAG_ALL; - NMDnsManager *dns_mgr; int ip_ifindex; g_return_val_if_fail (NM_IS_DEVICE (self), FALSE); @@ -3423,42 +3577,32 @@ nm_device_set_ip6_config (NMDevice *self, old_config = priv->ip6_config; - if (new_config && old_config) + if (new_config && old_config) { diff = nm_ip6_config_diff (new_config, old_config); - - /* No actual change, do nothing */ - if (diff == NM_IP6_COMPARE_FLAG_NONE) + if (diff == NM_IP6_COMPARE_FLAG_NONE) + return TRUE; /* no actual change */ + } else if (!new_config && !old_config) return TRUE; - dns_mgr = nm_dns_manager_get (NULL); - if (old_config) { - /* Remove any previous IP6 Config from the DNS manager */ - nm_dns_manager_remove_ip6_config (dns_mgr, ip_iface, old_config); - g_object_unref (old_config); - priv->ip6_config = NULL; - } + priv->ip6_config = NULL; if (new_config) { priv->ip6_config = g_object_ref (new_config); - /* Don't touch the device's actual IP config if the connection is - * assumed when NM starts. - */ - if (!assumed) - success = nm_system_apply_ip6_config (ip_ifindex, new_config, nm_device_get_priority (self), diff); + success = nm_system_apply_ip6_config (ip_ifindex, new_config, nm_device_get_priority (self), diff); - if (success || assumed) { + if (success) { /* Export over D-Bus */ if (!nm_ip6_config_get_dbus_path (new_config)) nm_ip6_config_export (new_config); - - /* Add the DNS information to the DNS manager */ - nm_dns_manager_add_ip6_config (dns_mgr, ip_iface, new_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT); } } - g_object_unref (dns_mgr); 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) + g_object_unref (old_config); return success; } @@ -3683,6 +3827,8 @@ finalize (GObject *object) g_free (priv->iface); g_free (priv->ip_iface); g_free (priv->driver); + g_free (priv->driver_version); + g_free (priv->firmware_version); g_free (priv->type_desc); if (priv->dhcp_anycast_address) g_byte_array_free (priv->dhcp_anycast_address, TRUE); @@ -3710,18 +3856,31 @@ set_property (GObject *object, guint prop_id, g_free (priv->iface); priv->ifindex = 0; priv->iface = g_value_dup_string (value); - if (priv->iface) { + + /* Only look up the ifindex if it appears to be an actual kernel + * interface name. eg Bluetooth devices won't have one until we know + * the IP interface. + */ + if (priv->iface && !strchr (priv->iface, ':')) { priv->ifindex = nm_netlink_iface_to_index (priv->iface); - if (priv->ifindex <= 0) { + if (priv->ifindex <= 0) nm_log_warn (LOGD_HW, "(%s): failed to look up interface index", priv->iface); - } } break; case PROP_IP_IFACE: break; case PROP_DRIVER: + g_free (priv->driver); priv->driver = g_strdup (g_value_get_string (value)); break; + case PROP_DRIVER_VERSION: + g_free (priv->driver_version); + priv->driver_version = g_strdup (g_value_get_string (value)); + break; + case PROP_FIRMWARE_VERSION: + g_free (priv->firmware_version); + priv->firmware_version = g_strdup (g_value_get_string (value)); + break; case PROP_CAPABILITIES: priv->capabilities = g_value_get_uint (value); break; @@ -3731,6 +3890,9 @@ set_property (GObject *object, guint prop_id, case PROP_MANAGED: priv->managed = g_value_get_boolean (value); break; + case PROP_AUTOCONNECT: + priv->autoconnect = g_value_get_boolean (value); + break; case PROP_FIRMWARE_MISSING: priv->firmware_missing = g_value_get_boolean (value); break; @@ -3787,6 +3949,12 @@ get_property (GObject *object, guint prop_id, case PROP_DRIVER: g_value_set_string (value, priv->driver); break; + case PROP_DRIVER_VERSION: + g_value_set_string (value, priv->driver_version); + break; + case PROP_FIRMWARE_VERSION: + g_value_set_string (value, priv->firmware_version); + break; case PROP_CAPABILITIES: g_value_set_uint (value, priv->capabilities); break; @@ -3839,6 +4007,9 @@ get_property (GObject *object, guint prop_id, case PROP_MANAGED: g_value_set_boolean (value, priv->managed); break; + case PROP_AUTOCONNECT: + g_value_set_boolean (value, priv->autoconnect); + break; case PROP_FIRMWARE_MISSING: g_value_set_boolean (value, priv->firmware_missing); break; @@ -3913,6 +4084,22 @@ nm_device_class_init (NMDeviceClass *klass) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property + (object_class, PROP_DRIVER_VERSION, + g_param_spec_string (NM_DEVICE_DRIVER_VERSION, + "Driver Version", + "Driver Version", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_FIRMWARE_VERSION, + g_param_spec_string (NM_DEVICE_FIRMWARE_VERSION, + "Firmware Version", + "Firmware Version", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_class, PROP_CAPABILITIES, g_param_spec_uint (NM_DEVICE_CAPABILITIES, "Capabilities", @@ -4000,6 +4187,14 @@ nm_device_class_init (NMDeviceClass *klass) G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property + (object_class, PROP_AUTOCONNECT, + g_param_spec_boolean (NM_DEVICE_AUTOCONNECT, + "Autoconnect", + "Autoconnect", + DEFAULT_AUTOCONNECT, + G_PARAM_READWRITE)); + + g_object_class_install_property (object_class, PROP_FIRMWARE_MISSING, g_param_spec_boolean (NM_DEVICE_FIRMWARE_MISSING, "FirmwareMissing", @@ -4043,14 +4238,6 @@ nm_device_class_init (NMDeviceClass *klass) G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT); - signals[DISCONNECT_REQUEST] = - g_signal_new (NM_DEVICE_DISCONNECT_REQUEST, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER); - signals[AUTOCONNECT_ALLOWED] = g_signal_new ("autoconnect-allowed", G_OBJECT_CLASS_TYPE (object_class), @@ -4060,6 +4247,31 @@ nm_device_class_init (NMDeviceClass *klass) _nm_marshal_BOOLEAN__VOID, G_TYPE_BOOLEAN, 0); + signals[AUTH_REQUEST] = + g_signal_new (NM_DEVICE_AUTH_REQUEST, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + /* dbus-glib context, permission, allow_interaction, callback, user_data */ + _nm_marshal_VOID__POINTER_STRING_BOOLEAN_POINTER_POINTER, + G_TYPE_NONE, 5, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_POINTER, G_TYPE_POINTER); + + signals[IP4_CONFIG_CHANGED] = + g_signal_new (NM_DEVICE_IP4_CONFIG_CHANGED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + _nm_marshal_VOID__OBJECT_OBJECT, + G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT); + + signals[IP6_CONFIG_CHANGED] = + g_signal_new (NM_DEVICE_IP6_CONFIG_CHANGED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + _nm_marshal_VOID__OBJECT_OBJECT, + G_TYPE_NONE, 2, G_TYPE_OBJECT, G_TYPE_OBJECT); + dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (klass), &dbus_glib_nm_device_interface_object_info); @@ -4225,6 +4437,8 @@ reason_to_string (NMDeviceStateReason reason) return "infiniband-mode"; case NM_DEVICE_STATE_REASON_DEPENDENCY_FAILED: return "dependency-failed"; + case NM_DEVICE_STATE_REASON_BR2684_FAILED: + return "br2684 bridge failed"; default: break; } @@ -4307,7 +4521,7 @@ nm_device_state_changed (NMDevice *device, nm_device_deactivate (device, reason); break; default: - priv->autoconnect_inhibit = FALSE; + priv->autoconnect = TRUE; break; } @@ -4627,12 +4841,11 @@ nm_device_set_dhcp_anycast_address (NMDevice *device, guint8 *addr) } } - -void -nm_device_clear_autoconnect_inhibit (NMDevice *device) +gboolean +nm_device_get_autoconnect (NMDevice *device) { - NMDevicePrivate *priv = NM_DEVICE_GET_PRIVATE (device); - g_return_if_fail (priv); - priv->autoconnect_inhibit = FALSE; + g_return_val_if_fail (NM_IS_DEVICE (device), FALSE); + + return NM_DEVICE_GET_PRIVATE (device)->autoconnect; } diff --git a/src/nm-device.h b/src/nm-device.h index bf76ecb5..91d9166a 100644 --- a/src/nm-device.h +++ b/src/nm-device.h @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2005 - 2011 Red Hat, Inc. + * Copyright (C) 2005 - 2012 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. */ @@ -23,7 +23,7 @@ #define NM_DEVICE_H #include <glib-object.h> -#include <dbus/dbus.h> +#include <dbus/dbus-glib.h> #include <netinet/in.h> #include "NetworkManager.h" @@ -34,12 +34,15 @@ #include "nm-dhcp6-config.h" #include "nm-connection.h" #include "nm-rfkill.h" +#include "nm-connection-provider.h" /* Properties */ #define NM_DEVICE_UDI "udi" #define NM_DEVICE_IFACE "interface" #define NM_DEVICE_IP_IFACE "ip-interface" #define NM_DEVICE_DRIVER "driver" +#define NM_DEVICE_DRIVER_VERSION "driver-version" +#define NM_DEVICE_FIRMWARE_VERSION "firmware-version" #define NM_DEVICE_CAPABILITIES "capabilities" #define NM_DEVICE_IP4_ADDRESS "ip4-address" #define NM_DEVICE_IP4_CONFIG "ip4-config" @@ -51,13 +54,16 @@ #define NM_DEVICE_ACTIVE_CONNECTION "active-connection" #define NM_DEVICE_DEVICE_TYPE "device-type" /* ugh */ #define NM_DEVICE_MANAGED "managed" +#define NM_DEVICE_AUTOCONNECT "autoconnect" #define NM_DEVICE_FIRMWARE_MISSING "firmware-missing" #define NM_DEVICE_TYPE_DESC "type-desc" /* Internal only */ #define NM_DEVICE_RFKILL_TYPE "rfkill-type" /* Internal only */ #define NM_DEVICE_IFINDEX "ifindex" /* Internal only */ -/* Internal signal */ -#define NM_DEVICE_DISCONNECT_REQUEST "disconnect-request" +/* Internal signals */ +#define NM_DEVICE_AUTH_REQUEST "auth-request" +#define NM_DEVICE_IP4_CONFIG_CHANGED "ip4-config-changed" +#define NM_DEVICE_IP6_CONFIG_CHANGED "ip6-config-changed" G_BEGIN_DECLS @@ -169,6 +175,11 @@ typedef struct { } NMDeviceClass; +typedef void (*NMDeviceAuthRequestFunc) (NMDevice *device, + DBusGMethodInvocation *context, + GError *error, + gpointer user_data); + GType nm_device_get_type (void); const char * nm_device_get_path (NMDevice *dev); @@ -180,6 +191,8 @@ int nm_device_get_ifindex (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); +const char * nm_device_get_driver_version (NMDevice *dev); +const char * nm_device_get_firmware_version (NMDevice *dev); const char * nm_device_get_type_desc (NMDevice *dev); NMDeviceType nm_device_get_device_type (NMDevice *dev); @@ -243,7 +256,7 @@ void nm_device_set_managed (NMDevice *device, gboolean managed, NMDeviceStateReason reason); -void nm_device_clear_autoconnect_inhibit (NMDevice *device); +gboolean nm_device_get_autoconnect (NMDevice *device); void nm_device_handle_autoip4_event (NMDevice *self, const char *event, @@ -261,7 +274,7 @@ gboolean nm_device_get_firmware_missing (NMDevice *self); gboolean nm_device_activate (NMDevice *device, NMActRequest *req, GError **error); -gboolean nm_device_disconnect (NMDevice *device, GError **error); +void nm_device_set_connection_provider (NMDevice *device, NMConnectionProvider *provider); G_END_DECLS diff --git a/src/nm-ip4-config.c b/src/nm-ip4-config.c index ef284d80..0722981e 100644 --- a/src/nm-ip4-config.c +++ b/src/nm-ip4-config.c @@ -143,11 +143,17 @@ nm_ip4_config_add_address (NMIP4Config *config, NMIP4Address *address) { NMIP4ConfigPrivate *priv; + GSList *iter; g_return_if_fail (NM_IS_IP4_CONFIG (config)); g_return_if_fail (address != NULL); priv = NM_IP4_CONFIG_GET_PRIVATE (config); + for (iter = priv->addresses; iter; iter = g_slist_next (iter)) { + if (nm_ip4_address_compare ((NMIP4Address *) iter->data, address)) + return; + } + priv->addresses = g_slist_append (priv->addresses, nm_ip4_address_dup (address)); } @@ -210,7 +216,8 @@ void nm_ip4_config_add_nameserver (NMIP4Config *config, guint32 nameserver) guint32 s = g_array_index (priv->nameservers, guint32, i); /* No dupes */ - g_return_if_fail (nameserver != s); + if (nameserver == s) + return; } g_array_append_val (priv->nameservers, nameserver); @@ -254,7 +261,8 @@ void nm_ip4_config_add_wins (NMIP4Config *config, guint32 wins) guint32 s = g_array_index (priv->wins, guint32, i); /* No dupes */ - g_return_if_fail (wins != s); + if (wins == s) + return; } g_array_append_val (priv->wins, wins); @@ -301,11 +309,17 @@ void nm_ip4_config_add_route (NMIP4Config *config, NMIP4Route *route) { NMIP4ConfigPrivate *priv; + GSList *iter; g_return_if_fail (NM_IS_IP4_CONFIG (config)); g_return_if_fail (route != NULL); priv = NM_IP4_CONFIG_GET_PRIVATE (config); + for (iter = priv->routes; iter; iter = g_slist_next (iter)) { + if (nm_ip4_route_compare ((NMIP4Route *) iter->data, route)) + return; + } + priv->routes = g_slist_append (priv->routes, nm_ip4_route_dup (route)); } @@ -743,7 +757,7 @@ nm_ip4_config_diff (NMIP4Config *a, NMIP4Config *b) NMIP4ConfigCompareFlags flags = NM_IP4_COMPARE_FLAG_NONE; if ((a && !b) || (b && !a)) - return 0xFFFFFFFF; + return NM_IP4_COMPARE_FLAG_ALL; if (!a && !b) return NM_IP4_COMPARE_FLAG_NONE; @@ -799,6 +813,68 @@ nm_ip4_config_diff (NMIP4Config *a, NMIP4Config *b) return flags; } +static inline void +hash_u32 (GChecksum *sum, guint32 n) +{ + g_checksum_update (sum, (const guint8 *) &n, sizeof (n)); +} + +void +nm_ip4_config_hash (NMIP4Config *config, GChecksum *sum, gboolean dns_only) +{ + guint32 i, n; + const char *s; + + g_return_if_fail (config != NULL); + g_return_if_fail (sum != NULL); + + if (dns_only == FALSE) { + for (i = 0; i < nm_ip4_config_get_num_addresses (config); i++) { + NMIP4Address *a = nm_ip4_config_get_address (config, i); + + hash_u32 (sum, nm_ip4_address_get_address (a)); + hash_u32 (sum, nm_ip4_address_get_prefix (a)); + hash_u32 (sum, nm_ip4_address_get_gateway (a)); + } + + for (i = 0; i < nm_ip4_config_get_num_routes (config); i++) { + NMIP4Route *r = nm_ip4_config_get_route (config, i); + + hash_u32 (sum, nm_ip4_route_get_dest (r)); + hash_u32 (sum, nm_ip4_route_get_prefix (r)); + hash_u32 (sum, nm_ip4_route_get_next_hop (r)); + hash_u32 (sum, nm_ip4_route_get_metric (r)); + } + + n = nm_ip4_config_get_ptp_address (config); + if (n) + hash_u32 (sum, n); + + for (i = 0; i < nm_ip4_config_get_num_nis_servers (config); i++) + hash_u32 (sum, nm_ip4_config_get_nis_server (config, i)); + + s = nm_ip4_config_get_nis_domain (config); + if (s) + g_checksum_update (sum, (const guint8 *) s, strlen (s)); + } + + for (i = 0; i < nm_ip4_config_get_num_nameservers (config); i++) + hash_u32 (sum, nm_ip4_config_get_nameserver (config, i)); + + for (i = 0; i < nm_ip4_config_get_num_wins (config); i++) + hash_u32 (sum, nm_ip4_config_get_wins (config, i)); + + for (i = 0; i < nm_ip4_config_get_num_domains (config); i++) { + s = nm_ip4_config_get_domain (config, i); + g_checksum_update (sum, (const guint8 *) s, strlen (s)); + } + + for (i = 0; i < nm_ip4_config_get_num_searches (config); i++) { + s = nm_ip4_config_get_search (config, i); + g_checksum_update (sum, (const guint8 *) s, strlen (s)); + } +} + static void nm_ip4_config_init (NMIP4Config *config) { diff --git a/src/nm-ip4-config.h b/src/nm-ip4-config.h index 2d27acff..6b86bc47 100644 --- a/src/nm-ip4-config.h +++ b/src/nm-ip4-config.h @@ -139,4 +139,6 @@ typedef enum { /* Returns a bitfield representing how the two IP4 configs differ */ NMIP4ConfigCompareFlags nm_ip4_config_diff (NMIP4Config *a, NMIP4Config *b); +void nm_ip4_config_hash (NMIP4Config *config, GChecksum *sum, gboolean dns_only); + #endif /* NM_IP4_CONFIG_H */ diff --git a/src/nm-ip6-config.c b/src/nm-ip6-config.c index f06e4069..511cbf46 100644 --- a/src/nm-ip6-config.c +++ b/src/nm-ip6-config.c @@ -53,6 +53,8 @@ typedef struct { GPtrArray *domains; GPtrArray *searches; + gboolean gateway_set; + struct in6_addr gateway; GSList *routes; gboolean never_default; @@ -138,11 +140,17 @@ nm_ip6_config_add_address (NMIP6Config *config, NMIP6Address *address) { NMIP6ConfigPrivate *priv; + GSList *iter; g_return_if_fail (NM_IS_IP6_CONFIG (config)); g_return_if_fail (address != NULL); priv = NM_IP6_CONFIG_GET_PRIVATE (config); + for (iter = priv->addresses; iter; iter = g_slist_next (iter)) { + if (nm_ip6_address_compare ((NMIP6Address *) iter->data, address)) + return; + } + priv->addresses = g_slist_append (priv->addresses, nm_ip6_address_dup (address)); } @@ -205,8 +213,10 @@ void nm_ip6_config_add_nameserver (NMIP6Config *config, const struct in6_addr *n /* No dupes */ nameservers = (struct in6_addr *)priv->nameservers->data; - for (i = 0; i < priv->nameservers->len; i++) - g_return_if_fail (IN6_ARE_ADDR_EQUAL (nameserver, &nameservers[i]) == FALSE); + for (i = 0; i < priv->nameservers->len; i++) { + if (IN6_ARE_ADDR_EQUAL (nameserver, &nameservers[i])) + return; + } g_array_append_val (priv->nameservers, *nameserver); } @@ -237,6 +247,30 @@ void nm_ip6_config_reset_nameservers (NMIP6Config *config) } void +nm_ip6_config_set_gateway (NMIP6Config *config, const struct in6_addr *gateway) +{ + NMIP6ConfigPrivate *priv; + + g_return_if_fail (NM_IS_IP6_CONFIG (config)); + + priv = NM_IP6_CONFIG_GET_PRIVATE (config); + if (gateway) + memcpy (&priv->gateway, gateway, sizeof (priv->gateway)); + priv->gateway_set = !!gateway; +} + +const struct in6_addr * +nm_ip6_config_get_gateway (NMIP6Config *config) +{ + NMIP6ConfigPrivate *priv; + + g_return_val_if_fail (NM_IS_IP6_CONFIG (config), NULL); + + priv = NM_IP6_CONFIG_GET_PRIVATE (config); + return priv->gateway_set ? &priv->gateway : NULL; +} + +void nm_ip6_config_take_route (NMIP6Config *config, NMIP6Route *route) { NMIP6ConfigPrivate *priv; @@ -252,11 +286,17 @@ void nm_ip6_config_add_route (NMIP6Config *config, NMIP6Route *route) { NMIP6ConfigPrivate *priv; + GSList *iter; g_return_if_fail (NM_IS_IP6_CONFIG (config)); g_return_if_fail (route != NULL); priv = NM_IP6_CONFIG_GET_PRIVATE (config); + for (iter = priv->routes; iter; iter = g_slist_next (iter)) { + if (nm_ip6_route_compare ((NMIP6Route *) iter->data, route)) + return; + } + priv->routes = g_slist_append (priv->routes, nm_ip6_route_dup (route)); } @@ -598,7 +638,7 @@ nm_ip6_config_diff (NMIP6Config *a, NMIP6Config *b) NMIP6ConfigCompareFlags flags = NM_IP6_COMPARE_FLAG_NONE; if ((a && !b) || (b && !a)) - return 0xFFFFFFFF; + return NM_IP6_COMPARE_FLAG_ALL; if (!a && !b) return NM_IP6_COMPARE_FLAG_NONE; @@ -637,6 +677,65 @@ nm_ip6_config_diff (NMIP6Config *a, NMIP6Config *b) return flags; } +static inline void +hash_u32 (GChecksum *sum, guint32 n) +{ + g_checksum_update (sum, (const guint8 *) &n, sizeof (n)); +} + +static inline void +hash_in6addr (GChecksum *sum, const struct in6_addr *a) +{ + g_checksum_update (sum, (const guint8 *) a, sizeof (*a)); +} + +void +nm_ip6_config_hash (NMIP6Config *config, GChecksum *sum, gboolean dns_only) +{ + guint32 i; + const struct in6_addr *in6a; + const char *s; + + g_return_if_fail (config != NULL); + g_return_if_fail (sum != NULL); + + if (dns_only == FALSE) { + for (i = 0; i < nm_ip6_config_get_num_addresses (config); i++) { + NMIP6Address *a = nm_ip6_config_get_address (config, i); + + hash_in6addr (sum, nm_ip6_address_get_address (a)); + hash_u32 (sum, nm_ip6_address_get_prefix (a)); + hash_in6addr (sum, nm_ip6_address_get_gateway (a)); + } + + for (i = 0; i < nm_ip6_config_get_num_routes (config); i++) { + NMIP6Route *r = nm_ip6_config_get_route (config, i); + + hash_in6addr (sum, nm_ip6_route_get_dest (r)); + hash_u32 (sum, nm_ip6_route_get_prefix (r)); + hash_in6addr (sum, nm_ip6_route_get_next_hop (r)); + hash_u32 (sum, nm_ip6_route_get_metric (r)); + } + + in6a = nm_ip6_config_get_ptp_address (config); + if (in6a) + hash_in6addr (sum, in6a); + } + + for (i = 0; i < nm_ip6_config_get_num_nameservers (config); i++) + hash_in6addr (sum, nm_ip6_config_get_nameserver (config, i)); + + for (i = 0; i < nm_ip6_config_get_num_domains (config); i++) { + s = nm_ip6_config_get_domain (config, i); + g_checksum_update (sum, (const guint8 *) s, strlen (s)); + } + + for (i = 0; i < nm_ip6_config_get_num_searches (config); i++) { + s = nm_ip6_config_get_search (config, i); + g_checksum_update (sum, (const guint8 *) s, strlen (s)); + } +} + static void nm_ip6_config_init (NMIP6Config *config) { @@ -645,6 +744,7 @@ nm_ip6_config_init (NMIP6Config *config) priv->nameservers = g_array_new (FALSE, TRUE, sizeof (struct in6_addr)); priv->domains = g_ptr_array_sized_new (3); priv->searches = g_ptr_array_sized_new (3); + priv->gateway_set = FALSE; } static void diff --git a/src/nm-ip6-config.h b/src/nm-ip6-config.h index 1e75a121..2e8ae18f 100644 --- a/src/nm-ip6-config.h +++ b/src/nm-ip6-config.h @@ -67,6 +67,9 @@ const struct in6_addr *nm_ip6_config_get_nameserver (NMIP6Config *config, g guint32 nm_ip6_config_get_num_nameservers (NMIP6Config *config); void nm_ip6_config_reset_nameservers (NMIP6Config *config); +void nm_ip6_config_set_gateway (NMIP6Config *config, const struct in6_addr *gateway); +const struct in6_addr *nm_ip6_config_get_gateway (NMIP6Config *config); + void nm_ip6_config_take_route (NMIP6Config *config, NMIP6Route *route); void nm_ip6_config_add_route (NMIP6Config *config, NMIP6Route *route); void nm_ip6_config_replace_route (NMIP6Config *config, guint32 i, NMIP6Route *new_route); @@ -117,4 +120,6 @@ typedef enum { /* Returns a bitfield representing how the two IP6 configs differ */ NMIP6ConfigCompareFlags nm_ip6_config_diff (NMIP6Config *a, NMIP6Config *b); +void nm_ip6_config_hash (NMIP6Config *config, GChecksum *sum, gboolean dns_only); + #endif /* NM_IP6_CONFIG_H */ diff --git a/src/nm-manager.c b/src/nm-manager.c index 7c812bdc..f2816cd7 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -48,6 +48,7 @@ #include "nm-device-infiniband.h" #include "nm-device-bond.h" #include "nm-device-vlan.h" +#include "nm-device-adsl.h" #include "nm-system.h" #include "nm-properties-changed-signal.h" #include "nm-setting-bluetooth.h" @@ -127,18 +128,16 @@ static gboolean impl_manager_set_logging (NMManager *manager, #include "nm-manager-glue.h" static void bluez_manager_bdaddr_added_cb (NMBluezManager *bluez_mgr, - const char *bdaddr, - const char *name, - const char *object_path, - guint32 uuids, - NMManager *manager); + const char *bdaddr, + const char *name, + const char *object_path, + guint32 uuids, + NMManager *manager); static void bluez_manager_bdaddr_removed_cb (NMBluezManager *bluez_mgr, - const char *bdaddr, - const char *object_path, - gpointer user_data); - -static void bluez_manager_resync_devices (NMManager *self); + const char *bdaddr, + const char *object_path, + gpointer user_data); static void add_device (NMManager *self, NMDevice *device); @@ -356,19 +355,20 @@ manager_sleeping (NMManager *self) static void vpn_manager_connection_activated_cb (NMVPNManager *manager, NMVPNConnection *vpn, - NMVPNConnectionState state, - NMVPNConnectionStateReason reason, gpointer user_data) { + NMConnection *connection = nm_vpn_connection_get_connection (vpn); + /* Update timestamp for the VPN connection */ - nm_settings_connection_update_timestamp (NM_SETTINGS_CONNECTION (nm_vpn_connection_get_connection (vpn)), + nm_settings_connection_update_timestamp (NM_SETTINGS_CONNECTION (connection), (guint64) time (NULL), TRUE); } static void vpn_manager_connection_deactivated_cb (NMVPNManager *manager, NMVPNConnection *vpn, - NMVPNConnectionState state, + NMVPNConnectionState new_state, + NMVPNConnectionState old_state, NMVPNConnectionStateReason reason, gpointer user_data) { @@ -1160,8 +1160,6 @@ connection_added (NMSettings *settings, NMSettingsConnection *connection, NMManager *manager) { - bluez_manager_resync_devices (manager); - if (connection_needs_virtual_device (NM_CONNECTION (connection))) system_create_virtual_device (manager, NM_CONNECTION (connection)); } @@ -1171,8 +1169,6 @@ connection_changed (NMSettings *settings, NMSettingsConnection *connection, NMManager *manager) { - bluez_manager_resync_devices (manager); - /* FIXME: Some virtual devices may need to be updated in the future. */ } @@ -1181,8 +1177,6 @@ connection_removed (NMSettings *settings, NMSettingsConnection *connection, NMManager *manager) { - bluez_manager_resync_devices (manager); - /* * Do not delete existing virtual devices to keep connectivity up. * Virtual devices are reused when NetworkManager is restarted. @@ -1539,111 +1533,96 @@ manager_modem_enabled_changed (NMModem *device, gpointer user_data) nm_manager_rfkill_update (NM_MANAGER (user_data), RFKILL_TYPE_WWAN); } -static GError * -deactivate_disconnect_check_error (GError *auth_error, - NMAuthCallResult result, - const char *detail) -{ - if (auth_error) { - nm_log_dbg (LOGD_CORE, "%s request failed: %s", detail, auth_error->message); - return g_error_new (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - "%s request failed: %s", - detail, auth_error->message); - } else if (result != NM_AUTH_CALL_RESULT_YES) { - return g_error_new (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_PERMISSION_DENIED, - "Not authorized to %s connections", - detail); - } - return NULL; -} - static void -disconnect_net_auth_done_cb (NMAuthChain *chain, - GError *auth_error, - DBusGMethodInvocation *context, - gpointer user_data) +device_auth_done_cb (NMAuthChain *chain, + GError *auth_error, + DBusGMethodInvocation *context, + gpointer user_data) { NMManager *self = NM_MANAGER (user_data); NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); GError *error = NULL; NMAuthCallResult result; NMDevice *device; + const char *permission; + NMDeviceAuthRequestFunc callback; priv->auth_chains = g_slist_remove (priv->auth_chains, chain); - result = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL)); - error = deactivate_disconnect_check_error (auth_error, result, "Disconnect"); - if (!error) { - device = nm_auth_chain_get_data (chain, "device"); - if (!nm_device_disconnect (device, &error)) - g_assert (error); + permission = nm_auth_chain_get_data (chain, "requested-permission"); + g_assert (permission); + callback = nm_auth_chain_get_data (chain, "callback"); + g_assert (callback); + device = nm_auth_chain_get_data (chain, "device"); + g_assert (device); + + result = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, permission)); + if (auth_error) { + /* translate the auth error into a manager permission denied error */ + nm_log_dbg (LOGD_CORE, "%s request failed: %s", permission, auth_error->message); + error = g_error_new (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "%s request failed: %s", + permission, auth_error->message); + } else if (result != NM_AUTH_CALL_RESULT_YES) { + nm_log_dbg (LOGD_CORE, "%s request failed: not authorized", permission); + error = g_error_new (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "%s request failed: not authorized", + permission); } - if (error) - dbus_g_method_return_error (context, error); - else - dbus_g_method_return (context); + g_assert (error || (result == NM_AUTH_CALL_RESULT_YES)); + + callback (device, + context, + error, + nm_auth_chain_get_data (chain, "user-data")); g_clear_error (&error); nm_auth_chain_unref (chain); } static void -manager_device_disconnect_request (NMDevice *device, - DBusGMethodInvocation *context, - NMManager *self) +device_auth_request_cb (NMDevice *device, + DBusGMethodInvocation *context, + const char *permission, + gboolean allow_interaction, + NMDeviceAuthRequestFunc callback, + gpointer user_data, + NMManager *self) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - NMActRequest *req; GError *error = NULL; gulong sender_uid = G_MAXULONG; char *error_desc = NULL; + NMAuthChain *chain; - req = nm_device_get_act_request (device); - if (!req) { - error = g_error_new_literal (NM_MANAGER_ERROR, - NM_MANAGER_ERROR_UNKNOWN_CONNECTION, - "This device is not active"); - dbus_g_method_return_error (context, error); - g_error_free (error); - return; - } - - /* Need to check the caller's permissions and stuff before we can - * deactivate the connection. - */ - if (!nm_auth_get_caller_uid (context, - priv->dbus_mgr, - &sender_uid, - &error_desc)) { + /* Get the caller's UID for the root check */ + if (!nm_auth_get_caller_uid (context, priv->dbus_mgr, &sender_uid, &error_desc)) { error = g_error_new_literal (NM_MANAGER_ERROR, NM_MANAGER_ERROR_PERMISSION_DENIED, error_desc); - dbus_g_method_return_error (context, error); + callback (device, context, error, user_data); g_error_free (error); g_free (error_desc); return; } /* Yay for root */ - if (0 == sender_uid) { - if (!nm_device_disconnect (device, &error)) { - dbus_g_method_return_error (context, error); - g_clear_error (&error); - } else - dbus_g_method_return (context); - } else { - NMAuthChain *chain; - - /* Otherwise validate the user request */ - chain = nm_auth_chain_new (context, NULL, disconnect_net_auth_done_cb, self); + if (0 == sender_uid) + callback (device, context, NULL, user_data); + else { + /* Otherwise validate the non-root request */ + chain = nm_auth_chain_new (context, NULL, device_auth_done_cb, self); g_assert (chain); priv->auth_chains = g_slist_append (priv->auth_chains, chain); nm_auth_chain_set_data (chain, "device", g_object_ref (device), g_object_unref); - nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, TRUE); + nm_auth_chain_set_data (chain, "requested-permission", g_strdup (permission), g_free); + nm_auth_chain_set_data (chain, "callback", callback, NULL); + nm_auth_chain_set_data (chain, "user-data", user_data, NULL); + nm_auth_chain_add_call (chain, permission, allow_interaction); } } @@ -1678,15 +1657,17 @@ add_device (NMManager *self, NMDevice *device) return; } + nm_device_set_connection_provider (device, NM_CONNECTION_PROVIDER (priv->settings)); + priv->devices = g_slist_append (priv->devices, device); g_signal_connect (device, "state-changed", G_CALLBACK (manager_device_state_changed), self); - g_signal_connect (device, NM_DEVICE_DISCONNECT_REQUEST, - G_CALLBACK (manager_device_disconnect_request), - self); + g_signal_connect (device, NM_DEVICE_AUTH_REQUEST, + G_CALLBACK (device_auth_request_cb), + self); if (devtype == NM_DEVICE_TYPE_WIFI) { /* Attach to the access-point-added signal so that the manager can fill @@ -1791,120 +1772,6 @@ add_device (NMManager *self, NMDevice *device) } } -static gboolean -bdaddr_matches_connection (NMSettingBluetooth *s_bt, const char *bdaddr) -{ - const GByteArray *arr; - gboolean ret = FALSE; - - arr = nm_setting_bluetooth_get_bdaddr (s_bt); - - if ( arr != NULL - && arr->len == ETH_ALEN) { - char *str; - - str = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", - arr->data[0], - arr->data[1], - arr->data[2], - arr->data[3], - arr->data[4], - arr->data[5]); - ret = g_str_equal (str, bdaddr); - g_free (str); - } - - return ret; -} - -static NMConnection * -bluez_manager_find_connection (NMManager *manager, - const char *bdaddr, - guint32 capabilities) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - NMConnection *found = NULL; - GSList *connections, *l; - - connections = nm_settings_get_connections (priv->settings); - - for (l = connections; l != NULL; l = l->next) { - NMConnection *candidate = NM_CONNECTION (l->data); - NMSettingConnection *s_con; - NMSettingBluetooth *s_bt; - const char *con_type; - const char *bt_type; - - s_con = nm_connection_get_setting_connection (candidate); - g_assert (s_con); - con_type = nm_setting_connection_get_connection_type (s_con); - g_assert (con_type); - if (!g_str_equal (con_type, NM_SETTING_BLUETOOTH_SETTING_NAME)) - continue; - - s_bt = nm_connection_get_setting_bluetooth (candidate); - if (!s_bt) - continue; - - if (!bdaddr_matches_connection (s_bt, bdaddr)) - continue; - - bt_type = nm_setting_bluetooth_get_connection_type (s_bt); - if ( g_str_equal (bt_type, NM_SETTING_BLUETOOTH_TYPE_DUN) - && !(capabilities & NM_BT_CAPABILITY_DUN)) - continue; - if ( g_str_equal (bt_type, NM_SETTING_BLUETOOTH_TYPE_PANU) - && !(capabilities & NM_BT_CAPABILITY_NAP)) - continue; - - found = candidate; - break; - } - - g_slist_free (connections); - return found; -} - -static void -bluez_manager_resync_devices (NMManager *self) -{ - NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - GSList *iter, *gone = NULL, *keep = NULL; - - /* Remove devices from the device list that don't have a corresponding connection */ - for (iter = priv->devices; iter; iter = g_slist_next (iter)) { - NMDevice *candidate = NM_DEVICE (iter->data); - guint32 uuids; - const char *bdaddr; - - if (nm_device_get_device_type (candidate) == NM_DEVICE_TYPE_BT) { - uuids = nm_device_bt_get_capabilities (NM_DEVICE_BT (candidate)); - bdaddr = nm_device_bt_get_hw_address (NM_DEVICE_BT (candidate)); - - if (bluez_manager_find_connection (self, bdaddr, uuids)) - keep = g_slist_prepend (keep, candidate); - else - gone = g_slist_prepend (gone, candidate); - } else - keep = g_slist_prepend (keep, candidate); - } - - /* Only touch the device list if anything actually changed */ - if (g_slist_length (gone)) { - g_slist_free (priv->devices); - priv->devices = keep; - - while (g_slist_length (gone)) - gone = remove_one_device (self, gone, NM_DEVICE (gone->data), FALSE); - } else { - g_slist_free (keep); - g_slist_free (gone); - } - - /* Now look for devices without connections */ - nm_bluez_manager_query_devices (priv->bluez_mgr); -} - static void bluez_manager_bdaddr_added_cb (NMBluezManager *bluez_mgr, const char *bdaddr, @@ -1926,12 +1793,6 @@ bluez_manager_bdaddr_added_cb (NMBluezManager *bluez_mgr, if (nm_manager_get_device_by_udi (manager, object_path)) return; - if (has_dun == FALSE && has_nap == FALSE) - return; - - if (!bluez_manager_find_connection (manager, bdaddr, capabilities)) - return; - device = nm_device_bt_new (object_path, bdaddr, name, capabilities, FALSE); if (device) { nm_log_info (LOGD_HW, "BT device %s (%s) added (%s%s%s)", @@ -1953,19 +1814,15 @@ bluez_manager_bdaddr_removed_cb (NMBluezManager *bluez_mgr, { NMManager *self = NM_MANAGER (user_data); NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self); - GSList *iter; + NMDevice *device; g_return_if_fail (bdaddr != NULL); g_return_if_fail (object_path != NULL); - for (iter = priv->devices; iter; iter = iter->next) { - NMDevice *device = NM_DEVICE (iter->data); - - if (!strcmp (nm_device_get_udi (device), object_path)) { - nm_log_info (LOGD_HW, "BT device %s removed", bdaddr); - priv->devices = remove_one_device (self, priv->devices, device, FALSE); - break; - } + device = nm_manager_get_device_by_udi (self, object_path); + if (device) { + nm_log_info (LOGD_HW, "BT device %s removed", bdaddr); + priv->devices = remove_one_device (self, priv->devices, device, FALSE); } } @@ -2155,6 +2012,12 @@ is_vlan (int ifindex) return (nm_system_get_iface_type (ifindex, NULL) == NM_IFACE_TYPE_VLAN); } +static gboolean +is_adsl (GUdevDevice *device) +{ + return (g_strcmp0 (g_udev_device_get_subsystem (device), "atm") == 0); +} + static void udev_device_added_cb (NMUdevManager *udev_mgr, GUdevDevice *udev_device, @@ -2174,14 +2037,22 @@ udev_device_added_cb (NMUdevManager *udev_mgr, g_return_if_fail (iface != NULL); g_return_if_fail (sysfs_path != NULL); g_return_if_fail (driver != NULL); - g_return_if_fail (ifindex >= 0); - device = find_device_by_ifindex (self, ifindex); - if (device) { - /* If it's a virtual device we may need to update its UDI */ - if (nm_system_get_iface_type (ifindex, iface) != NM_IFACE_TYPE_UNSPEC) - g_object_set (G_OBJECT (device), NM_DEVICE_UDI, sysfs_path, NULL); - return; + /* Most devices will have an ifindex here */ + if (ifindex > 0) { + device = find_device_by_ifindex (self, ifindex); + if (device) { + /* If it's a virtual device we may need to update its UDI */ + if (nm_system_get_iface_type (ifindex, iface) != NM_IFACE_TYPE_UNSPEC) + g_object_set (G_OBJECT (device), NM_DEVICE_UDI, sysfs_path, NULL); + return; + } + } else { + /* But ATM/ADSL devices don't */ + g_return_if_fail (is_adsl (udev_device)); + device = find_device_by_ip_iface (self, iface); + if (device) + return; } /* Try registered device factories */ @@ -2233,7 +2104,9 @@ udev_device_added_cb (NMUdevManager *udev_mgr, } } else nm_log_err (LOGD_HW, "(%s): failed to get VLAN parent ifindex", iface); - } else + } else if (is_adsl (udev_device)) + device = nm_device_adsl_new (sysfs_path, iface, driver); + else device = nm_device_ethernet_new (sysfs_path, iface, driver); } @@ -3098,8 +2971,18 @@ deactivate_net_auth_done_cb (NMAuthChain *chain, priv->auth_chains = g_slist_remove (priv->auth_chains, chain); result = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL)); - error = deactivate_disconnect_check_error (auth_error, result, "Deactivate"); - if (!error) { + if (auth_error) { + nm_log_dbg (LOGD_CORE, "Disconnect request failed: %s", auth_error->message); + error = g_error_new (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Deactivate request failed: %s", + auth_error->message); + } else if (result != NM_AUTH_CALL_RESULT_YES) { + error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_PERMISSION_DENIED, + "Not authorized to deactivate connections"); + } else { + /* success; deactivation allowed */ active_path = nm_auth_chain_get_data (chain, "path"); if (!nm_manager_deactivate_connection (self, active_path, @@ -3246,15 +3129,13 @@ do_sleep_wake (NMManager *self) nm_device_set_enabled (device, enabled); } - nm_device_clear_autoconnect_inhibit (device); + g_object_set (G_OBJECT (device), NM_DEVICE_AUTOCONNECT, TRUE, NULL); + if (nm_device_spec_match_list (device, unmanaged_specs)) nm_device_set_managed (device, FALSE, NM_DEVICE_STATE_REASON_NOW_UNMANAGED); else nm_device_set_managed (device, TRUE, NM_DEVICE_STATE_REASON_NOW_MANAGED); } - - /* Ask for new bluetooth devices */ - bluez_manager_resync_devices (self); } nm_manager_update_state (self); @@ -3671,7 +3552,7 @@ nm_manager_start (NMManager *self) system_hostname_changed_cb (priv->settings, NULL, self); nm_udev_manager_query_devices (priv->udev_mgr); - bluez_manager_resync_devices (self); + nm_bluez_manager_query_devices (priv->bluez_mgr); /* Query devices again to ensure that we catch all virtual interfaces (like * VLANs) that require a parent. If during the first pass the VLAN @@ -3766,7 +3647,8 @@ firmware_dir_changed (GFileMonitor *monitor, } } -#define PERM_DENIED_ERROR "org.freedesktop.NetworkManager.PermissionDenied" +#define NM_PERM_DENIED_ERROR "org.freedesktop.NetworkManager.PermissionDenied" +#define DEV_PERM_DENIED_ERROR "org.freedesktop.NetworkManager.Device.PermissionDenied" static void prop_set_auth_done_cb (NMAuthChain *chain, @@ -3779,9 +3661,13 @@ prop_set_auth_done_cb (NMAuthChain *chain, DBusGConnection *bus; DBusConnection *dbus_connection; NMAuthCallResult result; - DBusMessage *reply, *request; - const char *permission, *prop; + DBusMessage *reply = NULL, *request; + GError *ret_error; + const char *permission, *prop, *objpath; gboolean set_enabled = TRUE; + gboolean is_device = FALSE; + size_t objpath_len; + size_t devpath_len; priv->auth_chains = g_slist_remove (priv->auth_chains, chain); @@ -3789,9 +3675,16 @@ prop_set_auth_done_cb (NMAuthChain *chain, permission = nm_auth_chain_get_data (chain, "permission"); prop = nm_auth_chain_get_data (chain, "prop"); set_enabled = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "enabled")); + objpath = nm_auth_chain_get_data (chain, "objectpath"); + + objpath_len = strlen (objpath); + devpath_len = strlen (NM_DBUS_PATH "/Devices"); + if ( strncmp (objpath, NM_DBUS_PATH "/Devices", devpath_len) == 0 + && objpath_len > devpath_len) + is_device = TRUE; if (error) { - reply = dbus_message_new_error (request, PERM_DENIED_ERROR, + reply = dbus_message_new_error (request, is_device ? DEV_PERM_DENIED_ERROR : NM_PERM_DENIED_ERROR, "Not authorized to perform this operation"); } else { /* Caller has had a chance to obtain authorization, so we only need to @@ -3799,11 +3692,27 @@ prop_set_auth_done_cb (NMAuthChain *chain, */ result = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, permission)); if (result != NM_AUTH_CALL_RESULT_YES) { - reply = dbus_message_new_error (request, PERM_DENIED_ERROR, - "Not authorized to perform this operation"); + reply = dbus_message_new_error (request, is_device ? DEV_PERM_DENIED_ERROR : NM_PERM_DENIED_ERROR, + "Not authorized to perform this operation"); } else { - g_object_set (self, prop, set_enabled, NULL); - reply = dbus_message_new_method_return (request); + if (is_device) { + /* Find the device */ + NMDevice *device = nm_manager_get_device_by_path (self, objpath); + if (device) { + g_object_set (device, prop, set_enabled, NULL); + reply = dbus_message_new_method_return (request); + } + else { + ret_error = g_error_new_literal (NM_MANAGER_ERROR, + NM_MANAGER_ERROR_UNKNOWN_DEVICE, + "Can't find device for this operation"); + dbus_g_method_return_error (context, ret_error); + g_error_free (ret_error); + } + } else { + g_object_set (self, prop, set_enabled, NULL); + reply = dbus_message_new_method_return (request); + } } } @@ -3831,6 +3740,7 @@ prop_filter (DBusConnection *connection, const char *propiface = NULL; const char *propname = NULL; const char *sender = NULL; + const char *objpath = NULL; const char *glib_propname = NULL, *permission = NULL; DBusError dbus_error; gulong uid = G_MAXULONG; @@ -3852,7 +3762,7 @@ prop_filter (DBusConnection *connection, if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRING) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; dbus_message_iter_get_basic (&iter, &propiface); - if (!propiface || strcmp (propiface, NM_DBUS_INTERFACE)) + if (!propiface || (strcmp (propiface, NM_DBUS_INTERFACE) && strcmp (propiface, NM_DBUS_INTERFACE_DEVICE))) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; dbus_message_iter_next (&iter); @@ -3871,6 +3781,9 @@ prop_filter (DBusConnection *connection, } else if (!strcmp (propname, "WimaxEnabled")) { glib_propname = NM_MANAGER_WIMAX_ENABLED; permission = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX; + } else if (!strcmp (propname, "Autoconnect")) { + glib_propname = NM_DEVICE_AUTOCONNECT; + permission = NM_AUTH_PERMISSION_NETWORK_CONTROL; } else return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; @@ -3884,15 +3797,22 @@ prop_filter (DBusConnection *connection, sender = dbus_message_get_sender (message); if (!sender) { - reply = dbus_message_new_error (message, PERM_DENIED_ERROR, + reply = dbus_message_new_error (message, NM_PERM_DENIED_ERROR, "Could not determine D-Bus requestor"); goto out; } + objpath = dbus_message_get_path (message); + if (!objpath) { + reply = dbus_message_new_error (message, NM_PERM_DENIED_ERROR, + "Could not determine D-Bus object path"); + goto out; + } + dbus_error_init (&dbus_error); uid = dbus_bus_get_unix_user (connection, sender, &dbus_error); if (dbus_error_is_set (&dbus_error)) { - reply = dbus_message_new_error (message, PERM_DENIED_ERROR, + reply = dbus_message_new_error (message, NM_PERM_DENIED_ERROR, "Could not determine the user ID of the requestor"); dbus_error_free (&dbus_error); goto out; @@ -3907,6 +3827,7 @@ prop_filter (DBusConnection *connection, nm_auth_chain_set_data (chain, "permission", g_strdup (permission), g_free); nm_auth_chain_set_data (chain, "enabled", GUINT_TO_POINTER (set_enabled), NULL); nm_auth_chain_set_data (chain, "message", dbus_message_ref (message), (GDestroyNotify) dbus_message_unref); + nm_auth_chain_set_data (chain, "objectpath", g_strdup (objpath), g_free); nm_auth_chain_add_call (chain, permission, TRUE); } else { /* Yay for root */ @@ -4013,17 +3934,17 @@ nm_manager_new (NMSettings *settings, G_CALLBACK (udev_manager_rfkill_changed_cb), singleton); - priv->bluez_mgr = nm_bluez_manager_get (); + priv->bluez_mgr = nm_bluez_manager_get (NM_CONNECTION_PROVIDER (priv->settings)); g_signal_connect (priv->bluez_mgr, - "bdaddr-added", - G_CALLBACK (bluez_manager_bdaddr_added_cb), - singleton); + NM_BLUEZ_MANAGER_BDADDR_ADDED, + G_CALLBACK (bluez_manager_bdaddr_added_cb), + singleton); g_signal_connect (priv->bluez_mgr, - "bdaddr-removed", - G_CALLBACK (bluez_manager_bdaddr_removed_cb), - singleton); + NM_BLUEZ_MANAGER_BDADDR_REMOVED, + G_CALLBACK (bluez_manager_bdaddr_removed_cb), + singleton); return singleton; } diff --git a/src/nm-netlink-compat.c b/src/nm-netlink-compat.c index 974121ad..e30ec37a 100644 --- a/src/nm-netlink-compat.c +++ b/src/nm-netlink-compat.c @@ -121,7 +121,7 @@ rtnl_link_vlan_get_id (struct rtnl_link *l) if ((if_name = rtnl_link_get_name (l)) == NULL) return -1; - strcpy (if_request.device1, if_name); + g_strlcpy (if_request.device1, if_name, sizeof (if_request.device1)); if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0) { nm_log_err (LOGD_DEVICE, "couldn't open control socket."); @@ -158,7 +158,7 @@ rtnl_link_vlan_set_flags (struct rtnl_link *l, unsigned int flags) } memset (&if_request, 0, sizeof (struct vlan_ioctl_args)); - strcpy (if_request.device1, if_name); + g_strlcpy (if_request.device1, if_name, sizeof (if_request.device1)); if_request.cmd = SET_VLAN_FLAG_CMD; if_request.u.flag = flags; @@ -190,7 +190,7 @@ rtnl_link_vlan_set_ingress_map (struct rtnl_link *l, int from, uint32_t to) } memset (&if_request, 0, sizeof (struct vlan_ioctl_args)); - strcpy (if_request.device1, if_name); + g_strlcpy (if_request.device1, if_name, sizeof (if_request.device1)); if_request.cmd = SET_VLAN_INGRESS_PRIORITY_CMD; if_request.u.skb_priority = from; if_request.vlan_qos = to; @@ -223,7 +223,7 @@ rtnl_link_vlan_set_egress_map (struct rtnl_link *l, int from, uint32_t to) } memset (&if_request, 0, sizeof (struct vlan_ioctl_args)); - strcpy (if_request.device1, if_name); + g_strlcpy (if_request.device1, if_name, sizeof (if_request.device1)); if_request.cmd = SET_VLAN_EGRESS_PRIORITY_CMD; if_request.u.skb_priority = from; if_request.vlan_qos = to; diff --git a/src/nm-netlink-utils.c b/src/nm-netlink-utils.c index 99aebcb8..be8c17ed 100644 --- a/src/nm-netlink-utils.c +++ b/src/nm-netlink-utils.c @@ -136,7 +136,7 @@ nm_netlink_route_new (int ifindex, route = rtnl_route_alloc (); g_return_val_if_fail (route != NULL, NULL); - if (ifindex >= 0) + if (ifindex > 0) rtnl_route_set_oif (route, ifindex); if (family != AF_UNSPEC) rtnl_route_set_family (route, family); @@ -385,7 +385,7 @@ foreach_route_cb (struct nl_object *object, void *user_data) if (nm_logging_level_enabled (LOGL_DEBUG)) dump_route (route); - if ( info->ifindex >= 0 + if ( info->ifindex > 0 && rtnl_route_get_oif (route) != info->ifindex) return; diff --git a/src/nm-policy.c b/src/nm-policy.c index babf1649..57b1ee36 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2004 - 2011 Red Hat, Inc. + * Copyright (C) 2004 - 2012 Red Hat, Inc. * Copyright (C) 2007 - 2008 Novell, Inc. */ @@ -81,7 +81,7 @@ static void schedule_activate_all (NMPolicy *policy); static NMDevice * -get_best_ip4_device (NMManager *manager, NMActRequest **out_req) +get_best_ip4_device (NMManager *manager) { GSList *devices, *iter; NMDevice *best = NULL; @@ -89,8 +89,6 @@ get_best_ip4_device (NMManager *manager, NMActRequest **out_req) g_return_val_if_fail (manager != NULL, NULL); g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); - g_return_val_if_fail (out_req != NULL, NULL); - g_return_val_if_fail (*out_req == NULL, NULL); devices = nm_manager_get_devices (manager); for (iter = devices; iter; iter = g_slist_next (iter)) { @@ -148,7 +146,6 @@ get_best_ip4_device (NMManager *manager, NMActRequest **out_req) if (prio > 0 && prio < best_prio) { best = dev; best_prio = prio; - *out_req = req; } } @@ -156,7 +153,7 @@ get_best_ip4_device (NMManager *manager, NMActRequest **out_req) } static NMDevice * -get_best_ip6_device (NMManager *manager, NMActRequest **out_req) +get_best_ip6_device (NMManager *manager) { GSList *devices, *iter; NMDevice *best = NULL; @@ -164,8 +161,6 @@ get_best_ip6_device (NMManager *manager, NMActRequest **out_req) g_return_val_if_fail (manager != NULL, NULL); g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); - g_return_val_if_fail (out_req != NULL, NULL); - g_return_val_if_fail (*out_req == NULL, NULL); devices = nm_manager_get_devices (manager); for (iter = devices; iter; iter = g_slist_next (iter)) { @@ -222,7 +217,6 @@ get_best_ip6_device (NMManager *manager, NMActRequest **out_req) if (prio > 0 && prio < best_prio) { best = dev; best_prio = prio; - *out_req = req; } } @@ -295,8 +289,6 @@ static void update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) { char *configured_hostname = NULL; - NMActRequest *best_req4 = NULL; - NMActRequest *best_req6 = NULL; const char *dhcp_hostname, *p; g_return_if_fail (policy != NULL); @@ -325,9 +317,9 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) /* Try automatically determined hostname from the best device's IP config */ if (!best4) - best4 = get_best_ip4_device (policy->manager, &best_req4); + best4 = get_best_ip4_device (policy->manager); if (!best6) - best6 = get_best_ip6_device (policy->manager, &best_req6); + best6 = get_best_ip6_device (policy->manager); if (!best4 && !best6) { /* No best device; fall back to original hostname or if there wasn't @@ -433,270 +425,370 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) } static void -update_ip4_routing_and_dns (NMPolicy *policy, gboolean force_update) +update_default_ac (NMPolicy *policy, + NMActiveConnection *best, + void (*set_active_func)(NMActiveConnection*, gboolean)) { - NMDnsIPConfigType dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE; - NMDevice *best = NULL; - NMActRequest *best_req = NULL; - NMDnsManager *dns_mgr; - GSList *devices = NULL, *iter, *vpns; - NMIP4Config *ip4_config = NULL; - NMIP4Address *addr; - const char *ip_iface = NULL; - NMConnection *connection = NULL; - NMSettingConnection *s_con = NULL; - const char *connection_id; - int ip_ifindex = 0; + GSList *devices, *vpns, *iter; + NMActRequest *req; - best = get_best_ip4_device (policy->manager, &best_req); - if (!best) - goto out; - if (!force_update && (best == policy->default_device4)) - goto out; + /* Clear the 'default[6]' flag on all active connections that aren't the new + * default active connection. We'll set the new default after; this ensures + * we don't ever have two marked 'default[6]' simultaneously. + */ + devices = nm_manager_get_devices (policy->manager); + for (iter = devices; iter; iter = g_slist_next (iter)) { + req = nm_device_get_act_request (NM_DEVICE (iter->data)); + if (req && (NM_ACTIVE_CONNECTION (req) != best)) + set_active_func (NM_ACTIVE_CONNECTION (req), FALSE); + } + + vpns = nm_vpn_manager_get_active_connections (policy->vpn_manager); + for (iter = vpns; iter; iter = g_slist_next (iter)) { + if (NM_ACTIVE_CONNECTION (iter->data) != best) + set_active_func (NM_ACTIVE_CONNECTION (iter->data), FALSE); + } + g_slist_free (vpns); + + /* Mark new default active connection */ + if (best) + set_active_func (best, TRUE); +} + +static NMIP4Config * +get_best_ip4_config (NMPolicy *policy, + gboolean ignore_never_default, + const char **out_ip_iface, + int *out_ip_ifindex, + NMActiveConnection **out_ac, + NMDevice **out_device, + NMVPNConnection **out_vpn) +{ + GSList *vpns, *iter; + NMDevice *device; + NMActRequest *req = NULL; + NMIP4Config *ip4_config = NULL; /* If a VPN connection is active, it is preferred */ vpns = nm_vpn_manager_get_active_connections (policy->vpn_manager); for (iter = vpns; iter; iter = g_slist_next (iter)) { NMVPNConnection *candidate = NM_VPN_CONNECTION (iter->data); - NMConnection *vpn_connection; + NMIP4Config *vpn_ip4; + NMConnection *tmp; NMSettingIP4Config *s_ip4; - gboolean can_default = TRUE; NMVPNConnectionState vpn_state; - /* If it's marked 'never-default', don't make it default */ - vpn_connection = nm_vpn_connection_get_connection (candidate); - g_assert (vpn_connection); - - /* Check the active IP4 config from the VPN service daemon */ - ip4_config = nm_vpn_connection_get_ip4_config (candidate); - if (ip4_config && nm_ip4_config_get_never_default (ip4_config)) - can_default = FALSE; - - /* Check the user's preference from the NMConnection */ - s_ip4 = nm_connection_get_setting_ip4_config (vpn_connection); - if (s_ip4 && nm_setting_ip4_config_get_never_default (s_ip4)) - can_default = FALSE; + tmp = nm_vpn_connection_get_connection (candidate); + g_assert (tmp); vpn_state = nm_vpn_connection_get_vpn_state (candidate); - if (can_default && (vpn_state == NM_VPN_CONNECTION_STATE_ACTIVATED)) { - NMIP4Config *parent_ip4; - NMDevice *parent; - - ip_iface = nm_vpn_connection_get_ip_iface (candidate); - ip_ifindex = nm_vpn_connection_get_ip_ifindex (candidate); - connection = nm_vpn_connection_get_connection (candidate); - addr = nm_ip4_config_get_address (ip4_config, 0); + if (vpn_state != NM_VPN_CONNECTION_STATE_ACTIVATED) + continue; - parent = nm_vpn_connection_get_parent_device (candidate); - parent_ip4 = nm_device_get_ip4_config (parent); + vpn_ip4 = nm_vpn_connection_get_ip4_config (candidate); + if (!vpn_ip4) + continue; - nm_system_replace_default_ip4_route_vpn (ip_ifindex, - nm_ip4_address_get_gateway (addr), - nm_vpn_connection_get_ip4_internal_gateway (candidate), - nm_ip4_config_get_mss (ip4_config), - nm_device_get_ip_ifindex (parent), - nm_ip4_config_get_mss (parent_ip4)); + if (ignore_never_default == FALSE) { + /* Check for a VPN-provided config never-default */ + if (nm_ip4_config_get_never_default (vpn_ip4)) + continue; - dns_type = NM_DNS_IP_CONFIG_TYPE_VPN; + /* Check the user's preference from the NMConnection */ + s_ip4 = nm_connection_get_setting_ip4_config (tmp); + if (s_ip4 && nm_setting_ip4_config_get_never_default (s_ip4)) + continue; } + + ip4_config = vpn_ip4; + if (out_vpn) + *out_vpn = candidate; + if (out_ac) + *out_ac = NM_ACTIVE_CONNECTION (candidate); + if (out_ip_iface) + *out_ip_iface = nm_vpn_connection_get_ip_iface (candidate); + if (out_ip_ifindex) + *out_ip_ifindex = nm_vpn_connection_get_ip_ifindex (candidate); + break; } g_slist_free (vpns); - /* The best device gets the default route if a VPN connection didn't */ - if (!ip_iface || !ip4_config) { - connection = nm_act_request_get_connection (best_req); - ip_iface = nm_device_get_ip_iface (best); - ip_ifindex = nm_device_get_ip_ifindex (best); - ip4_config = nm_device_get_ip4_config (best); - g_assert (ip4_config); - addr = nm_ip4_config_get_address (ip4_config, 0); - - nm_system_replace_default_ip4_route (ip_ifindex, - nm_ip4_address_get_gateway (addr), - nm_ip4_config_get_mss (ip4_config)); - dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE; + /* If no VPN connections, we use the best device instead */ + if (!ip4_config) { + device = get_best_ip4_device (policy->manager); + if (device) { + ip4_config = nm_device_get_ip4_config (device); + g_assert (ip4_config); + req = nm_device_get_act_request (device); + g_assert (req); + + if (out_device) + *out_device = device; + if (out_ac) + *out_ac = NM_ACTIVE_CONNECTION (req); + if (out_ip_iface) + *out_ip_iface = nm_device_get_ip_iface (device); + if (out_ip_ifindex) + *out_ip_ifindex = nm_device_get_ip_ifindex (device); + } } - if (!ip_iface || !ip4_config) { - nm_log_warn (LOGD_CORE, "couldn't determine IP interface (%p) or IPv4 config (%p)!", - ip_iface, ip4_config); - goto out; - } + return ip4_config; +} - /* Update the default active connection. Only mark the new default - * active connection after setting default = FALSE on all other connections - * first. The order is important, we don't want two connections marked - * default at the same time ever. - */ - devices = nm_manager_get_devices (policy->manager); - for (iter = devices; iter; iter = g_slist_next (iter)) { - NMDevice *dev = NM_DEVICE (iter->data); - NMActRequest *req; +static void +update_ip4_dns (NMPolicy *policy, NMDnsManager *dns_mgr) +{ + NMIP4Config *ip4_config; + const char *ip_iface = NULL; + NMVPNConnection *vpn = NULL; + NMDnsIPConfigType dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE; - req = nm_device_get_act_request (dev); - if (req && (req != best_req)) - nm_active_connection_set_default (NM_ACTIVE_CONNECTION (req), FALSE); + ip4_config = get_best_ip4_config (policy, TRUE, &ip_iface, NULL, NULL, NULL, &vpn); + if (ip4_config) { + if (vpn) + dns_type = NM_DNS_IP_CONFIG_TYPE_VPN; + + /* Tell the DNS manager this config is preferred by re-adding it with + * a different IP config type. + */ + nm_dns_manager_add_ip4_config (dns_mgr, ip_iface, ip4_config, dns_type); } +} - dns_mgr = nm_dns_manager_get (NULL); - nm_dns_manager_add_ip4_config (dns_mgr, ip_iface, ip4_config, dns_type); - g_object_unref (dns_mgr); +static void +update_ip4_routing (NMPolicy *policy, gboolean force_update) +{ + NMDevice *best = NULL, *parent; + NMConnection *connection = NULL; + NMVPNConnection *vpn = NULL; + NMActiveConnection *best_ac = NULL; + NMIP4Config *ip4_config = NULL, *parent_ip4; + NMIP4Address *addr; + const char *ip_iface = NULL; + int ip_ifindex = -1; + guint32 parent_mss; - /* Now set new default active connection _after_ updating DNS info, so that - * if the connection is shared dnsmasq picks up the right stuff. + /* Note that we might have an IPv4 VPN tunneled over an IPv6-only device, + * so we can get (vpn != NULL && best == NULL). */ - if (best_req) - nm_active_connection_set_default (NM_ACTIVE_CONNECTION (best_req), TRUE); + ip4_config = get_best_ip4_config (policy, FALSE, &ip_iface, &ip_ifindex, &best_ac, &best, &vpn); + if (!ip4_config) { + policy->default_device4 = NULL; + return; + } + g_assert ((best || vpn) && best_ac); - if (connection) - s_con = nm_connection_get_setting_connection (connection); + if (!force_update && best && (best == policy->default_device4)) + return; - connection_id = s_con ? nm_setting_connection_get_id (s_con) : NULL; - if (connection_id) { - nm_log_info (LOGD_CORE, "Policy set '%s' (%s) as default for IPv4 routing and DNS.", connection_id, ip_iface); + /* We set the default route to the gateway of the first IP address of the config */ + addr = nm_ip4_config_get_address (ip4_config, 0); + g_assert (addr); + + if (vpn) { + parent = nm_vpn_connection_get_parent_device (vpn); + parent_ip4 = nm_device_get_ip4_config (parent); + parent_mss = parent_ip4 ? nm_ip4_config_get_mss (parent_ip4) : 0; + + nm_system_replace_default_ip4_route_vpn (ip_ifindex, + nm_ip4_address_get_gateway (addr), + nm_vpn_connection_get_ip4_internal_gateway (vpn), + nm_ip4_config_get_mss (ip4_config), + nm_device_get_ip_ifindex (parent), + parent_mss); } else { - nm_log_info (LOGD_CORE, "Policy set (%s) as default for IPv4 routing and DNS.", ip_iface); + nm_system_replace_default_ip4_route (ip_ifindex, + nm_ip4_address_get_gateway (addr), + nm_ip4_config_get_mss (ip4_config)); } -out: + update_default_ac (policy, best_ac, nm_active_connection_set_default); policy->default_device4 = best; + + connection = nm_active_connection_get_connection (best_ac); + nm_log_info (LOGD_CORE, "Policy set '%s' (%s) as default for IPv4 routing and DNS.", + nm_connection_get_id (connection), ip_iface); } -static void -update_ip6_routing_and_dns (NMPolicy *policy, gboolean force_update) +static NMIP6Config * +get_best_ip6_config (NMPolicy *policy, + gboolean ignore_never_default, + const char **out_ip_iface, + int *out_ip_ifindex, + NMActiveConnection **out_ac, + NMDevice **out_device, + NMVPNConnection **out_vpn) { - NMDnsIPConfigType dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE; - NMDevice *best = NULL; - NMActRequest *best_req = NULL; - NMDnsManager *dns_mgr; - GSList *devices = NULL, *iter; -#if 0 - GSList *vpns; -#endif + GSList *vpns, *iter; + NMDevice *device; + NMActRequest *req = NULL; NMIP6Config *ip6_config = NULL; - NMIP6Address *addr; - const char *ip_iface = NULL; - int ip_ifindex = -1; - NMConnection *connection = NULL; - NMSettingConnection *s_con = NULL; - const char *connection_id; - best = get_best_ip6_device (policy->manager, &best_req); - if (!best) - goto out; - if (!force_update && (best == policy->default_device6)) - goto out; - -#if 0 /* If a VPN connection is active, it is preferred */ vpns = nm_vpn_manager_get_active_connections (policy->vpn_manager); for (iter = vpns; iter; iter = g_slist_next (iter)) { NMVPNConnection *candidate = NM_VPN_CONNECTION (iter->data); - NMConnection *vpn_connection; + NMIP6Config *vpn_ip6; + NMConnection *tmp; NMSettingIP6Config *s_ip6; - gboolean can_default = TRUE; NMVPNConnectionState vpn_state; - /* If it's marked 'never-default', don't make it default */ - vpn_connection = nm_vpn_connection_get_connection (candidate); - g_assert (vpn_connection); - s_ip6 = nm_connection_get_setting_ip6_config (vpn_connection); - if (s_ip6 && nm_setting_ip6_config_get_never_default (s_ip6)) - can_default = FALSE; + tmp = nm_vpn_connection_get_connection (candidate); + g_assert (tmp); vpn_state = nm_vpn_connection_get_vpn_state (candidate); - if (can_default && (vpn_state == NM_VPN_CONNECTION_STATE_ACTIVATED)) { - NMIP6Config *parent_ip6; - NMDevice *parent; - - ip_iface = nm_vpn_connection_get_ip_iface (candidate); - connection = nm_vpn_connection_get_connection (candidate); - ip6_config = nm_vpn_connection_get_ip6_config (candidate); - addr = nm_ip6_config_get_address (ip6_config, 0); + if (vpn_state != NM_VPN_CONNECTION_STATE_ACTIVATED) + continue; - parent = nm_vpn_connection_get_parent_device (candidate); - parent_ip6 = nm_device_get_ip6_config (parent); + vpn_ip6 = nm_vpn_connection_get_ip6_config (candidate); + if (!vpn_ip6) + continue; - nm_system_replace_default_ip6_route_vpn (ip_iface, - nm_ip6_address_get_gateway (addr), - nm_vpn_connection_get_ip4_internal_gateway (candidate), - nm_ip6_config_get_mss (ip4_config), - nm_device_get_ip_iface (parent), - nm_ip6_config_get_mss (parent_ip4)); + if (ignore_never_default == FALSE) { + /* Check for a VPN-provided config never-default */ + if (nm_ip6_config_get_never_default (vpn_ip6)) + continue; - dns_type = NM_DNS_IP_CONFIG_TYPE_VPN; + /* Check the user's preference from the NMConnection */ + s_ip6 = nm_connection_get_setting_ip6_config (tmp); + if (s_ip6 && nm_setting_ip6_config_get_never_default (s_ip6)) + continue; } + + ip6_config = vpn_ip6; + if (out_vpn) + *out_vpn = candidate; + if (out_ac) + *out_ac = NM_ACTIVE_CONNECTION (candidate); + if (out_ip_iface) + *out_ip_iface = nm_vpn_connection_get_ip_iface (candidate); + if (out_ip_ifindex) + *out_ip_ifindex = nm_vpn_connection_get_ip_ifindex (candidate); + break; } g_slist_free (vpns); -#endif - /* The best device gets the default route if a VPN connection didn't */ - if (!ip_iface || !ip6_config) { - connection = nm_act_request_get_connection (best_req); - ip_iface = nm_device_get_ip_iface (best); - ip_ifindex = nm_device_get_ip_ifindex (best); - ip6_config = nm_device_get_ip6_config (best); - g_assert (ip6_config); - addr = nm_ip6_config_get_address (ip6_config, 0); - - nm_system_replace_default_ip6_route (ip_ifindex, nm_ip6_address_get_gateway (addr)); - - dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE; + /* If no VPN connections, we use the best device instead */ + if (!ip6_config) { + device = get_best_ip6_device (policy->manager); + if (device) { + req = nm_device_get_act_request (device); + g_assert (req); + ip6_config = nm_device_get_ip6_config (device); + g_assert (ip6_config); + + if (out_device) + *out_device = device; + if (out_ac) + *out_ac = NM_ACTIVE_CONNECTION (req); + if (out_ip_iface) + *out_ip_iface = nm_device_get_ip_iface (device); + if (out_ip_ifindex) + *out_ip_ifindex = nm_device_get_ip_ifindex (device); + } } - if (!ip_iface || !ip6_config) { - nm_log_warn (LOGD_CORE, "couldn't determine IP interface (%p) or IPv6 config (%p)!", - ip_iface, ip6_config); - goto out; - } + return ip6_config; +} - /* Update the default active connection. Only mark the new default - * active connection after setting default = FALSE on all other connections - * first. The order is important, we don't want two connections marked - * default at the same time ever. - */ - devices = nm_manager_get_devices (policy->manager); - for (iter = devices; iter; iter = g_slist_next (iter)) { - NMDevice *dev = NM_DEVICE (iter->data); - NMActRequest *req; +static void +update_ip6_dns (NMPolicy *policy, NMDnsManager *dns_mgr) +{ + NMIP6Config *ip6_config; + const char *ip_iface = NULL; + NMVPNConnection *vpn = NULL; + NMDnsIPConfigType dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE; - req = nm_device_get_act_request (dev); - if (req && (req != best_req)) - nm_active_connection_set_default6 (NM_ACTIVE_CONNECTION (req), FALSE); + ip6_config = get_best_ip6_config (policy, TRUE, &ip_iface, NULL, NULL, NULL, &vpn); + if (ip6_config) { + if (vpn) + dns_type = NM_DNS_IP_CONFIG_TYPE_VPN; + + /* Tell the DNS manager this config is preferred by re-adding it with + * a different IP config type. + */ + nm_dns_manager_add_ip6_config (dns_mgr, ip_iface, ip6_config, dns_type); } +} - dns_mgr = nm_dns_manager_get (NULL); - nm_dns_manager_add_ip6_config (dns_mgr, ip_iface, ip6_config, dns_type); - g_object_unref (dns_mgr); +static void +update_ip6_routing (NMPolicy *policy, gboolean force_update) +{ + NMDevice *best = NULL, *parent; + NMConnection *connection = NULL; + NMVPNConnection *vpn = NULL; + NMActiveConnection *best_ac = NULL; + NMIP6Config *ip6_config = NULL, *parent_ip6; + NMIP6Address *addr; + const char *ip_iface = NULL; + int ip_ifindex = -1; + guint32 parent_mss; - /* Now set new default active connection _after_ updating DNS info, so that - * if the connection is shared dnsmasq picks up the right stuff. + /* Note that we might have an IPv6 VPN tunneled over an IPv4-only device, + * so we can get (vpn != NULL && best == NULL). */ - if (best_req) - nm_active_connection_set_default6 (NM_ACTIVE_CONNECTION (best_req), TRUE); + ip6_config = get_best_ip6_config (policy, FALSE, &ip_iface, &ip_ifindex, &best_ac, &best, &vpn); + if (!ip6_config) { + policy->default_device6 = NULL; + return; + } + g_assert ((best || vpn) && best_ac); - if (connection) - s_con = nm_connection_get_setting_connection (connection); + if (!force_update && best && (best == policy->default_device6)) + return; - connection_id = s_con ? nm_setting_connection_get_id (s_con) : NULL; - if (connection_id) { - nm_log_info (LOGD_CORE, "Policy set '%s' (%s) as default for IPv6 routing and DNS.", connection_id, ip_iface); + /* We set the default route to the gateway of the first IP address of the config */ + addr = nm_ip6_config_get_address (ip6_config, 0); + g_assert (addr); + + if (vpn) { + parent = nm_vpn_connection_get_parent_device (vpn); + parent_ip6 = nm_device_get_ip6_config (parent); + parent_mss = parent_ip6 ? nm_ip6_config_get_mss (parent_ip6) : 0; + + nm_system_replace_default_ip6_route_vpn (ip_ifindex, + nm_ip6_address_get_gateway (addr), + nm_vpn_connection_get_ip6_internal_gateway (vpn), + nm_ip6_config_get_mss (ip6_config), + nm_device_get_ip_ifindex (parent), + parent_mss); } else { - nm_log_info (LOGD_CORE, "Policy set (%s) as default for IPv6 routing and DNS.", ip_iface); + if (memcmp (nm_ip6_address_get_gateway (addr)->s6_addr, in6addr_any.s6_addr, sizeof (in6addr_any.s6_addr)) != 0) + nm_system_replace_default_ip6_route (ip_ifindex, nm_ip6_address_get_gateway (addr)); + else if (nm_ip6_config_get_gateway (ip6_config)) + nm_system_replace_default_ip6_route (ip_ifindex, nm_ip6_config_get_gateway (ip6_config)); + else + nm_log_dbg (LOGD_IP6, "missing default IPv6 route"); } -out: + update_default_ac (policy, best_ac, nm_active_connection_set_default6); policy->default_device6 = best; + + connection = nm_active_connection_get_connection (best_ac); + nm_log_info (LOGD_CORE, "Policy set '%s' (%s) as default for IPv6 routing and DNS.", + nm_connection_get_id (connection), ip_iface); } static void update_routing_and_dns (NMPolicy *policy, gboolean force_update) { - update_ip4_routing_and_dns (policy, force_update); - update_ip6_routing_and_dns (policy, force_update); + NMDnsManager *mgr; + + mgr = nm_dns_manager_get (NULL); + nm_dns_manager_begin_updates (mgr, __func__); + + update_ip4_dns (policy, mgr); + update_ip6_dns (policy, mgr); + + update_ip4_routing (policy, force_update); + update_ip6_routing (policy, force_update); /* Update the system hostname */ update_system_hostname (policy, policy->default_device4, policy->default_device6); + + nm_dns_manager_end_updates (mgr, __func__); + g_object_unref (mgr); } static void @@ -842,17 +934,96 @@ vpn_connection_activated (NMVPNManager *manager, NMVPNConnection *vpn, gpointer user_data) { + NMDnsManager *mgr; + NMIP4Config *ip4_config; + NMIP6Config *ip6_config; + const char *ip_iface; + + mgr = nm_dns_manager_get (NULL); + nm_dns_manager_begin_updates (mgr, __func__); + + ip_iface = nm_vpn_connection_get_ip_iface (vpn); + + /* Add the VPN connection's IP configs from DNS */ + + ip4_config = nm_vpn_connection_get_ip4_config (vpn); + if (ip4_config) + nm_dns_manager_add_ip4_config (mgr, ip_iface, ip4_config, NM_DNS_IP_CONFIG_TYPE_VPN); + + ip6_config = nm_vpn_connection_get_ip6_config (vpn); + if (ip6_config) + nm_dns_manager_add_ip6_config (mgr, ip_iface, ip6_config, NM_DNS_IP_CONFIG_TYPE_VPN); + update_routing_and_dns ((NMPolicy *) user_data, TRUE); + + nm_dns_manager_end_updates (mgr, __func__); } static void vpn_connection_deactivated (NMVPNManager *manager, NMVPNConnection *vpn, - NMVPNConnectionState state, + NMVPNConnectionState new_state, + NMVPNConnectionState old_state, NMVPNConnectionStateReason reason, gpointer user_data) { + NMDnsManager *mgr; + NMIP4Config *ip4_config, *parent_ip4 = NULL; + NMIP6Config *ip6_config, *parent_ip6 = NULL; + const char *ip_iface; + NMDevice *parent; + + mgr = nm_dns_manager_get (NULL); + nm_dns_manager_begin_updates (mgr, __func__); + + ip_iface = nm_vpn_connection_get_ip_iface (vpn); + parent = nm_vpn_connection_get_parent_device (vpn); + + ip4_config = nm_vpn_connection_get_ip4_config (vpn); + if (ip4_config) { + /* Remove the VPN connection's IP4 config from DNS */ + nm_dns_manager_remove_ip4_config (mgr, ip_iface, ip4_config); + + /* Re-apply routes and addresses of the VPN connection's parent interface, + * which the VPN might have overridden. + */ + if (parent) { + parent_ip4 = nm_device_get_ip4_config (parent); + if (parent_ip4) { + if (!nm_system_apply_ip4_config (nm_device_get_ip_ifindex (parent), + parent_ip4, + nm_device_get_priority (parent), + NM_IP4_COMPARE_FLAG_ADDRESSES | NM_IP4_COMPARE_FLAG_ROUTES)) { + nm_log_err (LOGD_VPN, "failed to re-apply VPN parent device IPv4 addresses and routes."); + } + } + } + } + + ip6_config = nm_vpn_connection_get_ip6_config (vpn); + if (ip6_config) { + /* Remove the VPN connection's IP6 config from DNS */ + nm_dns_manager_remove_ip6_config (mgr, ip_iface, ip6_config); + + /* Re-apply routes and addresses of the VPN connection's parent interface, + * which the VPN might have overridden. + */ + if (parent) { + parent_ip6 = nm_device_get_ip6_config (parent); + if (parent_ip6) { + if (!nm_system_apply_ip6_config (nm_device_get_ip_ifindex (parent), + parent_ip6, + nm_device_get_priority (parent), + NM_IP6_COMPARE_FLAG_ADDRESSES | NM_IP6_COMPARE_FLAG_ROUTES)) { + nm_log_err (LOGD_VPN, "failed to re-apply VPN parent device IPv6 addresses and routes."); + } + } + } + } + update_routing_and_dns ((NMPolicy *) user_data, TRUE); + + nm_dns_manager_end_updates (mgr, __func__); } static void @@ -976,15 +1147,6 @@ reset_connections_retries (gpointer user_data) return FALSE; } -static NMConnection * -get_device_connection (NMDevice *device) -{ - NMActRequest *req = NULL; - - req = nm_device_get_act_request (device); - return req ? nm_act_request_get_connection (req) : NULL; -} - static void schedule_activate_all (NMPolicy *policy); static void @@ -1025,7 +1187,11 @@ device_state_changed (NMDevice *device, gpointer user_data) { NMPolicy *policy = (NMPolicy *) user_data; - NMConnection *connection = get_device_connection (device); + NMConnection *connection = nm_device_get_connection (device); + const char *ip_iface = nm_device_get_ip_iface (device); + NMIP4Config *ip4_config; + NMIP6Config *ip6_config; + NMDnsManager *dns_mgr; if (connection) g_object_set_data (G_OBJECT (connection), FAILURE_REASON_TAG, GUINT_TO_POINTER (0)); @@ -1081,20 +1247,33 @@ device_state_changed (NMDevice *device, nm_connection_clear_secrets (connection); } - update_routing_and_dns (policy, FALSE); + /* Add device's new IPv4 and IPv6 configs to DNS */ + + dns_mgr = nm_dns_manager_get (NULL); + nm_dns_manager_begin_updates (dns_mgr, __func__); + + ip4_config = nm_device_get_ip4_config (device); + if (ip4_config) { + nm_dns_manager_add_ip4_config (dns_mgr, ip_iface, ip4_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT); + update_ip4_dns (policy, dns_mgr); + } + ip6_config = nm_device_get_ip6_config (device); + if (ip6_config) { + nm_dns_manager_add_ip6_config (dns_mgr, ip_iface, ip6_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT); + update_ip6_dns (policy, dns_mgr); + } + + nm_dns_manager_end_updates (dns_mgr, __func__); + g_object_unref (dns_mgr); + + /* And make sure the best devices have the default route */ + update_ip4_routing (policy, FALSE); + update_ip6_routing (policy, FALSE); break; case NM_DEVICE_STATE_UNMANAGED: - if ( old_state == NM_DEVICE_STATE_UNAVAILABLE - || old_state == NM_DEVICE_STATE_DISCONNECTED) { - /* If the device was never activated, there's no point in - * updating routing or DNS. This allows us to keep the previous - * resolv.conf or routes from before NM started if no device was - * ever managed by NM. - */ - break; - } case NM_DEVICE_STATE_UNAVAILABLE: - update_routing_and_dns (policy, FALSE); + if (old_state > NM_DEVICE_STATE_DISCONNECTED) + update_routing_and_dns (policy, FALSE); break; case NM_DEVICE_STATE_DISCONNECTED: /* Reset RETRIES_TAG when carrier on. If cable was unplugged @@ -1102,8 +1281,10 @@ device_state_changed (NMDevice *device, if (reason == NM_DEVICE_STATE_REASON_CARRIER && old_state == NM_DEVICE_STATE_UNAVAILABLE) reset_retries_all (policy->settings, device); + if (old_state > NM_DEVICE_STATE_DISCONNECTED) + update_routing_and_dns (policy, FALSE); + /* Device is now available for auto-activation */ - update_routing_and_dns (policy, FALSE); schedule_activate_check (policy, device, 0); break; @@ -1119,11 +1300,86 @@ device_state_changed (NMDevice *device, } static void -device_ip_config_changed (NMDevice *device, - GParamSpec *pspec, - gpointer user_data) +device_ip4_config_changed (NMDevice *device, + NMIP4Config *new_config, + NMIP4Config *old_config, + gpointer user_data) { - update_routing_and_dns ((NMPolicy *) user_data, TRUE); + NMPolicy *policy = user_data; + NMDnsManager *dns_mgr; + const char *ip_iface = nm_device_get_ip_iface (device); + NMIP4ConfigCompareFlags diff = NM_IP4_COMPARE_FLAG_ALL; + + dns_mgr = nm_dns_manager_get (NULL); + nm_dns_manager_begin_updates (dns_mgr, __func__); + + /* Old configs get removed immediately */ + if (old_config) + nm_dns_manager_remove_ip4_config (dns_mgr, ip_iface, old_config); + + /* Ignore IP config changes while the device is activating, because we'll + * catch all the changes when the device moves to ACTIVATED state. + * Prevents unecessary changes to DNS information. + */ + if (!nm_device_is_activating (device)) { + if (new_config) + nm_dns_manager_add_ip4_config (dns_mgr, ip_iface, new_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT); + update_ip4_dns (policy, dns_mgr); + + /* Only change routing if something actually changed */ + diff = nm_ip4_config_diff (new_config, old_config); + if (diff & (NM_IP4_COMPARE_FLAG_ADDRESSES | NM_IP4_COMPARE_FLAG_PTP_ADDRESS | NM_IP4_COMPARE_FLAG_ROUTES)) + update_ip4_routing (policy, TRUE); + } + + nm_dns_manager_end_updates (dns_mgr, __func__); + g_object_unref (dns_mgr); +} + +static void +device_ip6_config_changed (NMDevice *device, + NMIP6Config *new_config, + NMIP6Config *old_config, + gpointer user_data) +{ + NMPolicy *policy = user_data; + NMDnsManager *dns_mgr; + const char *ip_iface = nm_device_get_ip_iface (device); + NMIP4ConfigCompareFlags diff = NM_IP4_COMPARE_FLAG_ALL; + + dns_mgr = nm_dns_manager_get (NULL); + nm_dns_manager_begin_updates (dns_mgr, __func__); + + /* Old configs get removed immediately */ + if (old_config) + nm_dns_manager_remove_ip6_config (dns_mgr, ip_iface, old_config); + + /* Ignore IP config changes while the device is activating, because we'll + * catch all the changes when the device moves to ACTIVATED state. + * Prevents unecessary changes to DNS information. + */ + if (!nm_device_is_activating (device)) { + if (new_config) + nm_dns_manager_add_ip6_config (dns_mgr, ip_iface, new_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT); + update_ip6_dns (policy, dns_mgr); + + /* Only change routing if something actually changed */ + diff = nm_ip6_config_diff (new_config, old_config); + if (diff & (NM_IP6_COMPARE_FLAG_ADDRESSES | NM_IP6_COMPARE_FLAG_PTP_ADDRESS | NM_IP6_COMPARE_FLAG_ROUTES)) + update_ip6_routing (policy, TRUE); + } + + nm_dns_manager_end_updates (dns_mgr, __func__); + g_object_unref (dns_mgr); +} + +static void +device_autoconnect_changed (NMDevice *device, + GParamSpec *pspec, + gpointer user_data) +{ + if (nm_device_get_autoconnect (device)) + schedule_activate_check ((NMPolicy *) user_data, device, 0); } static void @@ -1167,8 +1423,9 @@ device_added (NMManager *manager, NMDevice *device, gpointer user_data) NMPolicy *policy = (NMPolicy *) user_data; _connect_device_signal (policy, device, "state-changed", device_state_changed); - _connect_device_signal (policy, device, "notify::" NM_DEVICE_IP4_CONFIG, device_ip_config_changed); - _connect_device_signal (policy, device, "notify::" NM_DEVICE_IP6_CONFIG, device_ip_config_changed); + _connect_device_signal (policy, device, NM_DEVICE_IP4_CONFIG_CHANGED, device_ip4_config_changed); + _connect_device_signal (policy, device, NM_DEVICE_IP6_CONFIG_CHANGED, device_ip6_config_changed); + _connect_device_signal (policy, device, "notify::" NM_DEVICE_AUTOCONNECT, device_autoconnect_changed); switch (nm_device_get_device_type (device)) { case NM_DEVICE_TYPE_WIFI: @@ -1215,7 +1472,9 @@ device_removed (NMManager *manager, NMDevice *device, gpointer user_data) iter = next; } - update_routing_and_dns (policy, FALSE); + /* Don't update routing and DNS here as we've already handled that + * for devices that need it when the device's state changed to UNMANAGED. + */ } static void @@ -1273,7 +1532,7 @@ firewall_update_zone (NMPolicy *policy, NMConnection *connection) for (iter = devices; iter; iter = g_slist_next (iter)) { NMDevice *dev = NM_DEVICE (iter->data); - if ( (get_device_connection (dev) == connection) + if ( (nm_device_get_connection (dev) == connection) && (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED)) { nm_firewall_manager_add_or_change_zone (policy->fw_manager, nm_device_get_ip_iface (dev), @@ -1299,7 +1558,7 @@ firewall_started (NMFirewallManager *manager, for (iter = devices; iter; iter = g_slist_next (iter)) { NMDevice *dev = NM_DEVICE (iter->data); - connection = get_device_connection (dev); + connection = nm_device_get_connection (dev); s_con = nm_connection_get_setting_connection (connection); if (nm_device_get_state (dev) == NM_DEVICE_STATE_ACTIVATED) { nm_firewall_manager_add_or_change_zone (policy->fw_manager, diff --git a/src/nm-system.c b/src/nm-system.c index 91153ec2..b980dc53 100644 --- a/src/nm-system.c +++ b/src/nm-system.c @@ -349,14 +349,15 @@ add_ip4_addresses (NMIP4Config *config, int ifindex) } struct rtnl_route * -nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device, NMIP4Config *vpn_config) +nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device, guint32 vpn_gw) { NMIP4Config *parent_config; - guint32 parent_gw = 0, parent_prefix = 0, vpn_gw = 0, i; + guint32 parent_gw = 0, parent_prefix = 0, i; NMIP4Address *tmp; struct rtnl_route *route = NULL; g_return_val_if_fail (NM_IS_DEVICE (parent_device), NULL); + g_return_val_if_fail (vpn_gw != 0, NULL); /* Set up a route to the VPN gateway's public IP address through the default * network device if the VPN gateway is on a different subnet. @@ -374,15 +375,7 @@ nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device, NMIP4Config *vpn_c } } - for (i = 0; i < nm_ip4_config_get_num_addresses (vpn_config); i++) { - tmp = nm_ip4_config_get_address (vpn_config, i); - if (nm_ip4_address_get_gateway (tmp)) { - vpn_gw = nm_ip4_address_get_gateway (tmp); - break; - } - } - - if (!parent_gw || !vpn_gw) + if (!parent_gw) return NULL; /* If the VPN gateway is in the same subnet as one of the parent device's @@ -479,7 +472,7 @@ nm_system_set_ip6_route (int ifindex, struct rtnl_route *route; int err = 0; - g_return_val_if_fail (ifindex >= 0, -1); + g_return_val_if_fail (ifindex > 0, -1); nlh = nm_netlink_get_default_handle (); g_return_val_if_fail (nlh != NULL, -1); @@ -520,6 +513,96 @@ nm_system_set_ip6_route (int ifindex, } static gboolean +ip6_dest_in_same_subnet (NMIP6Config *config, const struct in6_addr *dest, guint32 dest_prefix) +{ + int num; + int i; + + num = nm_ip6_config_get_num_addresses (config); + for (i = 0; i < num; i++) { + NMIP6Address *addr = nm_ip6_config_get_address (config, i); + guint32 prefix = nm_ip6_address_get_prefix (addr); + const struct in6_addr *address = nm_ip6_address_get_address (addr); + + if (prefix <= dest_prefix) { + const guint8 *maskbytes = (const guint8 *)address; + const guint8 *addrbytes = (const guint8 *)dest; + int nbytes, nbits; + + /* Copied from g_inet_address_mask_matches() */ + nbytes = prefix / 8; + if (nbytes != 0 && memcmp (maskbytes, addrbytes, nbytes) != 0) + continue; + + nbits = prefix % 8; + if (nbits == 0) + return TRUE; + + if (maskbytes[nbytes] == (addrbytes[nbytes] & (0xFF << (8 - nbits)))) + return TRUE; + } + } + + return FALSE; +} + +struct rtnl_route * +nm_system_add_ip6_vpn_gateway_route (NMDevice *parent_device, + const struct in6_addr *vpn_gw) +{ + NMIP6Config *parent_config; + const struct in6_addr *parent_gw = NULL; + guint32 parent_prefix = 0; + int i, err; + NMIP6Address *tmp; + struct rtnl_route *route = NULL; + + g_return_val_if_fail (NM_IS_DEVICE (parent_device), NULL); + g_return_val_if_fail (vpn_gw != NULL, NULL); + + /* This is all just the same as + * nm_system_add_ip4_vpn_gateway_route(), except with an IPv6 + * address for the VPN gateway. + */ + + parent_config = nm_device_get_ip6_config (parent_device); + g_return_val_if_fail (parent_config != NULL, NULL); + + for (i = 0; i < nm_ip6_config_get_num_addresses (parent_config); i++) { + tmp = nm_ip6_config_get_address (parent_config, i); + if (nm_ip6_address_get_gateway (tmp)) { + parent_gw = nm_ip6_address_get_gateway (tmp); + parent_prefix = nm_ip6_address_get_prefix (tmp); + break; + } + } + + if (!parent_gw) + return NULL; + + if (ip6_dest_in_same_subnet (parent_config, vpn_gw, parent_prefix)) { + err = nm_system_set_ip6_route (nm_device_get_ip_ifindex (parent_device), + vpn_gw, 128, NULL, 0, + nm_ip6_config_get_mss (parent_config), + RTPROT_UNSPEC, RT_TABLE_UNSPEC, + &route); + } else { + err = nm_system_set_ip6_route (nm_device_get_ip_ifindex (parent_device), + vpn_gw, 128, parent_gw, 0, + nm_ip6_config_get_mss (parent_config), + RTPROT_UNSPEC, RT_TABLE_UNSPEC, + &route); + } + + if (err) { + nm_log_err (LOGD_DEVICE | LOGD_IP6, + "(%s): failed to add IPv6 route to VPN gateway (%d)", + nm_device_get_iface (parent_device), err); + } + return route; +} + +static gboolean add_ip6_addresses (NMIP6Config *config, int ifindex) { char *iface; @@ -909,7 +992,7 @@ nm_system_replace_default_ip4_route_vpn (int ifindex, goto out; if ((err != -NLE_OBJ_NOTFOUND) && (err != -NLE_FAILURE)) { - nm_log_err (LOGD_DEVICE | LOGD_IP4, + nm_log_err (LOGD_DEVICE | LOGD_VPN | LOGD_IP4, "(%s): failed to set IPv4 default route: %d", iface, err); goto out; @@ -924,7 +1007,7 @@ nm_system_replace_default_ip4_route_vpn (int ifindex, err = replace_default_ip4_route (ifindex, int_gw, mss); if (err != 0) { nm_netlink_route_delete (gw_route); - nm_log_err (LOGD_DEVICE | LOGD_IP4, + nm_log_err (LOGD_DEVICE | LOGD_VPN | LOGD_IP4, "(%s): failed to set IPv4 default route (pass #2): %d", iface, err); } else @@ -989,7 +1072,7 @@ out: } static struct rtnl_route * -add_ip6_route_to_gateway (int ifindex, const struct in6_addr *gw) +add_ip6_route_to_gateway (int ifindex, const struct in6_addr *gw, int mss) { struct nl_sock *nlh; struct rtnl_route *route = NULL; @@ -999,7 +1082,7 @@ add_ip6_route_to_gateway (int ifindex, const struct in6_addr *gw) g_return_val_if_fail (nlh != NULL, NULL); /* Gateway might be over a bridge; try adding a route to gateway first */ - route = nm_netlink_route_new (ifindex, AF_INET6, 0, + route = nm_netlink_route_new (ifindex, AF_INET6, mss, NMNL_PROP_SCOPE, RT_SCOPE_LINK, NMNL_PROP_TABLE, RT_TABLE_MAIN, NULL); @@ -1023,7 +1106,7 @@ add_ip6_route_to_gateway (int ifindex, const struct in6_addr *gw) } static int -replace_default_ip6_route (int ifindex, const struct in6_addr *gw) +add_default_ip6_route (int ifindex, const struct in6_addr *gw, int mss) { struct rtnl_route *route = NULL; struct nl_sock *nlh; @@ -1034,25 +1117,81 @@ replace_default_ip6_route (int ifindex, const struct in6_addr *gw) nlh = nm_netlink_get_default_handle (); g_return_val_if_fail (nlh != NULL, -ENOMEM); - route = nm_netlink_route_new (ifindex, AF_INET6, 0, + route = nm_netlink_route_new (ifindex, AF_INET6, mss, NMNL_PROP_SCOPE, RT_SCOPE_UNIVERSE, NMNL_PROP_TABLE, RT_TABLE_MAIN, + NMNL_PROP_PRIO, 1, NULL); g_return_val_if_fail (route != NULL, -ENOMEM); /* Add the new default route */ - err = nm_netlink_route6_add (route, &in6addr_any, 0, gw, NLM_F_REPLACE); - if (err == -NLE_EXIST) { - /* FIXME: even though we use NLM_F_REPLACE the kernel won't replace - * the route if it's the same. Suppress the pointless error. - */ + err = nm_netlink_route6_add (route, &in6addr_any, 0, gw, NLM_F_CREATE); + if (err == -NLE_EXIST) err = 0; - } rtnl_route_put (route); return err; } +static struct rtnl_route * +find_static_default_routes (struct rtnl_route *route, + struct nl_addr *dst, + const char *iface, + gpointer user_data) +{ + GList **def_routes = user_data; + + if ( nl_addr_get_prefixlen (dst) == 0 + && rtnl_route_get_protocol (route) == RTPROT_STATIC) { + rtnl_route_get (route); + *def_routes = g_list_prepend (*def_routes, route); + } + + return NULL; +} + +static int +replace_default_ip6_route (int ifindex, const struct in6_addr *gw, int mss) +{ + GList *def_routes, *iter; + struct rtnl_route *route; + char *iface; + char gw_str[INET6_ADDRSTRLEN + 1]; + + g_return_val_if_fail (ifindex > 0, FALSE); + g_return_val_if_fail (gw != NULL, FALSE); + + if (nm_logging_level_enabled (LOGL_DEBUG)) { + memset (gw_str, 0, sizeof (gw_str)); + if (inet_ntop (AF_INET6, gw, gw_str, sizeof (gw_str) - 1)) + nm_log_dbg (LOGD_IP6, "Setting IPv6 default route via %s", gw_str); + } + + /* We can't just use NLM_F_REPLACE here like in the IPv4 case, because + * the kernel doesn't like it if we replace the default routes it + * creates. (See rh#785772.) So we delete any non-kernel default routes, + * and then add a new default route of our own with a lower metric than + * the kernel ones. + */ + def_routes = NULL; + nm_netlink_foreach_route (ifindex, AF_INET6, RT_SCOPE_UNIVERSE, TRUE, + find_static_default_routes, &def_routes); + for (iter = def_routes; iter; iter = iter->next) { + route = iter->data; + if (!nm_netlink_route_delete (route)) { + iface = nm_netlink_index_to_iface (ifindex); + nm_log_err (LOGD_DEVICE | LOGD_IP6, + "(%s): failed to delete existing IPv6 default route", + iface); + g_free (iface); + } + rtnl_route_put (route); + } + g_list_free (def_routes); + + return add_default_ip6_route (ifindex, gw, mss); +} + /* * nm_system_replace_default_ip6_route * @@ -1067,11 +1206,8 @@ nm_system_replace_default_ip6_route (int ifindex, const struct in6_addr *gw) char *iface; int err; - err = replace_default_ip6_route (ifindex, gw); - if (err == 0) - return TRUE; - - if (err == -NLE_EXIST) + err = replace_default_ip6_route (ifindex, gw, 0); + if (err == 0 || err == -NLE_EXIST) return TRUE; iface = nm_netlink_index_to_iface (ifindex); @@ -1086,12 +1222,12 @@ nm_system_replace_default_ip6_route (int ifindex, const struct in6_addr *gw) } /* Try adding a direct route to the gateway first */ - gw_route = add_ip6_route_to_gateway (ifindex, gw); + gw_route = add_ip6_route_to_gateway (ifindex, gw, 0); if (!gw_route) goto out; /* Try adding the original route again */ - err = replace_default_ip6_route (ifindex, gw); + err = replace_default_ip6_route (ifindex, gw, 0); if (err != 0) { nm_netlink_route_delete (gw_route); nm_log_err (LOGD_DEVICE | LOGD_IP6, @@ -1107,6 +1243,60 @@ out: return success; } +gboolean +nm_system_replace_default_ip6_route_vpn (int ifindex, + const struct in6_addr *ext_gw, + const struct in6_addr *int_gw, + guint32 mss, + int parent_ifindex, + guint32 parent_mss) +{ + struct rtnl_route *gw_route = NULL; + struct nl_sock *nlh; + gboolean success = FALSE; + int err; + char *iface; + + nlh = nm_netlink_get_default_handle (); + g_return_val_if_fail (nlh != NULL, FALSE); + + err = replace_default_ip6_route (ifindex, int_gw, mss); + if (err == 0) + return TRUE; + + iface = nm_netlink_index_to_iface (ifindex); + if (!iface) + goto out; + + if ((err != -NLE_OBJ_NOTFOUND) && (err != -NLE_FAILURE)) { + nm_log_err (LOGD_DEVICE | LOGD_VPN | LOGD_IP6, + "(%s): failed to set IPv6 default route: %d", + iface, err); + goto out; + } + + /* Try adding a direct route to the gateway first */ + gw_route = add_ip6_route_to_gateway (parent_ifindex, ext_gw, parent_mss); + if (!gw_route) + goto out; + + /* Try adding the original route again */ + err = replace_default_ip6_route (ifindex, int_gw, mss); + if (err != 0) { + nm_netlink_route_delete (gw_route); + nm_log_err (LOGD_DEVICE | LOGD_VPN | LOGD_IP6, + "(%s): failed to set IPv6 default route (pass #2): %d", + iface, err); + } else + success = TRUE; + +out: + if (gw_route) + rtnl_route_put (gw_route); + g_free (iface); + return success; +} + /* * nm_system_iface_flush_addresses * @@ -1435,9 +1625,9 @@ nm_system_iface_enslave (gint master_ifindex, struct nl_sock *sock; int err; - g_return_val_if_fail (master_ifindex >= 0, FALSE); + g_return_val_if_fail (master_ifindex > 0, FALSE); g_return_val_if_fail (master_iface != NULL, FALSE); - g_return_val_if_fail (slave_ifindex >= 0, FALSE); + g_return_val_if_fail (slave_ifindex > 0, FALSE); g_return_val_if_fail (slave_iface != NULL, FALSE); sock = nm_netlink_get_default_handle (); @@ -1520,9 +1710,9 @@ nm_system_iface_release (gint master_ifindex, struct nl_sock *sock; int err; - g_return_val_if_fail (master_ifindex >= 0, FALSE); + g_return_val_if_fail (master_ifindex > 0, FALSE); g_return_val_if_fail (master_iface != NULL, FALSE); - g_return_val_if_fail (slave_ifindex >= 0, FALSE); + g_return_val_if_fail (slave_ifindex > 0, FALSE); g_return_val_if_fail (slave_iface != NULL, FALSE); sock = nm_netlink_get_default_handle (); @@ -1561,7 +1751,7 @@ nm_system_get_iface_type (int ifindex, const char *name) char *type; int res = NM_IFACE_TYPE_UNSPEC; - g_return_val_if_fail (ifindex >= 0 || name, NM_IFACE_TYPE_UNSPEC); + g_return_val_if_fail (ifindex > 0 || name, NM_IFACE_TYPE_UNSPEC); nlh = nm_netlink_get_default_handle (); if (!nlh) @@ -1706,7 +1896,7 @@ nm_system_iface_compat_add_vlan_device (const char *master, int vid) } memset (&if_request, 0, sizeof (struct vlan_ioctl_args)); - strcpy (if_request.device1, master); + g_strlcpy (if_request.device1, master, sizeof (if_request.device1)); if_request.cmd = ADD_VLAN_CMD; if_request.u.VID = vid; @@ -1732,7 +1922,7 @@ nm_system_iface_compat_rem_vlan_device (const char *iface) } memset (&if_request, 0, sizeof (struct vlan_ioctl_args)); - strcpy (if_request.device1, iface); + g_strlcpy (if_request.device1, iface, sizeof (if_request.device1)); if_request.cmd = DEL_VLAN_CMD; if (ioctl (fd, SIOCSIFVLAN, &if_request) < 0) { @@ -1868,7 +2058,7 @@ nm_system_add_vlan_iface (NMConnection *connection, guint32 vlan_flags = 0; guint32 num, i, from, to; - g_return_val_if_fail (parent_ifindex >= 0, FALSE); + g_return_val_if_fail (parent_ifindex > 0, FALSE); nlh = nm_netlink_get_default_handle (); g_return_val_if_fail (nlh != NULL, FALSE); diff --git a/src/nm-system.h b/src/nm-system.h index 84ae6c27..1acb8853 100644 --- a/src/nm-system.h +++ b/src/nm-system.h @@ -53,8 +53,17 @@ gboolean nm_system_replace_default_ip4_route_vpn (int ifindex, int parent_ifindex, guint32 parent_mss); -struct rtnl_route *nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device, NMIP4Config *vpn_config); +gboolean nm_system_replace_default_ip6_route_vpn (int ifindex, + const struct in6_addr *ext_gw, + const struct in6_addr *int_gw, + guint32 mss, + int parent_ifindex, + guint32 parent_mss); +struct rtnl_route *nm_system_add_ip4_vpn_gateway_route (NMDevice *parent_device, + guint32 vpn_gw); +struct rtnl_route *nm_system_add_ip6_vpn_gateway_route (NMDevice *parent_device, + const struct in6_addr *vpn_gw); gboolean nm_system_iface_flush_addresses (int ifindex, int family); diff --git a/src/nm-udev-manager.c b/src/nm-udev-manager.c index 45262f87..57b36d38 100644 --- a/src/nm-udev-manager.c +++ b/src/nm-udev-manager.c @@ -329,52 +329,34 @@ rfkill_remove (NMUdevManager *self, } } -static void -net_add (NMUdevManager *self, GUdevDevice *udev_device) +static gboolean +dev_get_attrs (GUdevDevice *udev_device, + const char **out_ifname, + const char **out_path, + char **out_driver, + int *out_ifindex) { GUdevDevice *parent = NULL, *grandparent = NULL; - gint ifindex; - gint etype; - const char *ifname, *driver, *path, *subsys, *tmp; - gboolean is_ctc; + const char *ifname, *driver, *path, *subsys; + gint ifindex = -1; + gboolean success = FALSE; - g_return_if_fail (udev_device != NULL); + g_return_val_if_fail (udev_device != NULL, FALSE); + g_return_val_if_fail (out_ifname != NULL, FALSE); + g_return_val_if_fail (out_path != NULL, FALSE); + g_return_val_if_fail (out_driver != NULL, FALSE); + g_return_val_if_fail (out_ifindex != NULL, FALSE); ifname = g_udev_device_get_name (udev_device); if (!ifname) { nm_log_dbg (LOGD_HW, "failed to get device's interface"); - return; - } - - etype = g_udev_device_get_sysfs_attr_as_int (udev_device, "type"); - is_ctc = (strncmp (ifname, "ctc", 3) == 0) && (etype == 256); - - /* Ignore devices that don't report Ethernet encapsulation, except for - * s390 CTC-type devices that report 256 for some reason. - * FIXME: use something other than interface name to detect CTC here. - */ - if ((etype != ARPHRD_ETHER) && (etype != ARPHRD_INFINIBAND) && (is_ctc == FALSE)) { - nm_log_dbg (LOGD_HW, "(%s): ignoring interface with type %d", ifname, etype); - return; - } - - /* Not all ethernet devices are immediately usable; newer mobile broadband - * devices (Ericsson, Option, Sierra) require setup on the tty before the - * ethernet device is usable. 2.6.33 and later kernels set the 'DEVTYPE' - * uevent variable which we can use to ignore the interface as a NMDevice - * subclass. ModemManager will pick it up though and so we'll handle it - * through the mobile broadband stuff. - */ - tmp = g_udev_device_get_property (udev_device, "DEVTYPE"); - if (g_strcmp0 (tmp, "wwan") == 0) { - nm_log_dbg (LOGD_HW, "(%s): ignoring interface with devtype '%s'", ifname, tmp); - return; + return FALSE; } path = g_udev_device_get_sysfs_path (udev_device); if (!path) { nm_log_warn (LOGD_HW, "couldn't determine device path; ignoring..."); - return; + return FALSE; } driver = g_udev_device_get_driver (udev_device); @@ -399,11 +381,8 @@ net_add (NMUdevManager *self, GUdevDevice *udev_device) } } - ifindex = g_udev_device_get_sysfs_attr_as_int (udev_device, "ifindex"); - if (ifindex <= 0) { - nm_log_warn (LOGD_HW, "%s: device had invalid ifindex %d; ignoring...", path, (guint32) ifindex); - goto out; - } + if (g_udev_device_get_sysfs_attr (udev_device, "ifindex")) + ifindex = g_udev_device_get_sysfs_attr_as_int (udev_device, "ifindex"); if (!driver) { switch (nm_system_get_iface_type (ifindex, ifname)) { @@ -425,13 +404,69 @@ net_add (NMUdevManager *self, GUdevDevice *udev_device) } } - g_signal_emit (self, signals[DEVICE_ADDED], 0, udev_device, ifname, path, driver, ifindex); + *out_ifname = ifname; + *out_path = path; + *out_driver = g_strdup (driver); + *out_ifindex = ifindex; + success = TRUE; out: if (grandparent) g_object_unref (grandparent); if (parent) g_object_unref (parent); + + return success; +} + +static void +net_add (NMUdevManager *self, GUdevDevice *udev_device) +{ + gint ifindex = -1; + gint etype; + const char *ifname = NULL, *path = NULL, *tmp; + char *driver = NULL; + gboolean is_ctc; + + g_return_if_fail (udev_device != NULL); + + if (!dev_get_attrs (udev_device, &ifname, &path, &driver, &ifindex)) + return; + + if (ifindex < 0) { + nm_log_warn (LOGD_HW, "%s: device had invalid ifindex %d; ignoring...", path, ifindex); + goto out; + } + + etype = g_udev_device_get_sysfs_attr_as_int (udev_device, "type"); + is_ctc = (strncmp (ifname, "ctc", 3) == 0) && (etype == 256); + + /* Ignore devices that don't report Ethernet encapsulation, except for + * s390 CTC-type devices that report 256 for some reason. + * FIXME: use something other than interface name to detect CTC here. + */ + if ((etype != ARPHRD_ETHER) && (etype != ARPHRD_INFINIBAND) && (is_ctc == FALSE)) { + nm_log_dbg (LOGD_HW, "(%s): ignoring interface with type %d", ifname, etype); + goto out; + } + + /* Not all ethernet devices are immediately usable; newer mobile broadband + * devices (Ericsson, Option, Sierra) require setup on the tty before the + * ethernet device is usable. 2.6.33 and later kernels set the 'DEVTYPE' + * uevent variable which we can use to ignore the interface as a NMDevice + * subclass. ModemManager will pick it up though and so we'll handle it + * through the mobile broadband stuff. + */ + tmp = g_udev_device_get_property (udev_device, "DEVTYPE"); + if (g_strcmp0 (tmp, "wwan") == 0) { + nm_log_dbg (LOGD_HW, "(%s): ignoring interface with devtype '%s'", ifname, tmp); + goto out; + } + + g_signal_emit (self, signals[DEVICE_ADDED], 0, udev_device, ifname, path, driver, ifindex); + +out: + g_free (driver); } static void @@ -440,6 +475,30 @@ net_remove (NMUdevManager *self, GUdevDevice *device) g_signal_emit (self, signals[DEVICE_REMOVED], 0, device); } +static void +adsl_add (NMUdevManager *self, GUdevDevice *udev_device) +{ + gint ifindex = -1; + const char *ifname = NULL, *path = NULL; + char *driver = NULL; + + g_return_if_fail (udev_device != NULL); + + nm_log_dbg (LOGD_HW, "adsl_add: ATM Device detected from udev. Adding .."); + + if (dev_get_attrs (udev_device, &ifname, &path, &driver, &ifindex)) + g_signal_emit (self, signals[DEVICE_ADDED], 0, udev_device, ifname, path, driver, ifindex); + g_free (driver); +} + +static void +adsl_remove (NMUdevManager *self, GUdevDevice *device) +{ + nm_log_dbg (LOGD_HW, "adsl_remove: Removing ATM Device"); + + g_signal_emit (self, signals[DEVICE_REMOVED], 0, device); +} + void nm_udev_manager_query_devices (NMUdevManager *self) { @@ -455,6 +514,14 @@ nm_udev_manager_query_devices (NMUdevManager *self) g_object_unref (G_UDEV_DEVICE (iter->data)); } g_list_free (devices); + + + devices = g_udev_client_query_by_subsystem (priv->client, "atm"); + for (iter = devices; iter; iter = g_list_next (iter)) { + adsl_add (self, G_UDEV_DEVICE (iter->data)); + g_object_unref (G_UDEV_DEVICE (iter->data)); + } + g_list_free (devices); } static void @@ -475,18 +542,23 @@ handle_uevent (GUdevClient *client, nm_log_dbg (LOGD_HW, "UDEV event: action '%s' subsys '%s' device '%s'", action, subsys, g_udev_device_get_name (device)); - g_return_if_fail (!strcmp (subsys, "rfkill") || !strcmp (subsys, "net")); + g_return_if_fail (!strcmp (subsys, "rfkill") || !strcmp (subsys, "net") || + !strcmp (subsys, "atm")); if (!strcmp (action, "add")) { if (!strcmp (subsys, "rfkill")) rfkill_add (self, device); else if (!strcmp (subsys, "net")) net_add (self, device); + else if (!strcmp (subsys, "atm")) + adsl_add (self, device); } else if (!strcmp (action, "remove")) { if (!strcmp (subsys, "rfkill")) rfkill_remove (self, device); else if (!strcmp (subsys, "net")) net_remove (self, device); + else if (!strcmp (subsys, "atm")) + adsl_remove (self, device); } recheck_killswitches (self); @@ -496,7 +568,7 @@ static void nm_udev_manager_init (NMUdevManager *self) { NMUdevManagerPrivate *priv = NM_UDEV_MANAGER_GET_PRIVATE (self); - const char *subsys[3] = { "rfkill", "net", NULL }; + const char *subsys[4] = { "rfkill", "net", "atm", NULL }; GList *switches, *iter; guint32 i; diff --git a/src/nm-wifi-ap.c b/src/nm-wifi-ap.c index 92a99b69..6a607960 100644 --- a/src/nm-wifi-ap.c +++ b/src/nm-wifi-ap.c @@ -509,7 +509,6 @@ NMAccessPoint * nm_ap_new_from_properties (const char *supplicant_path, GHashTable *properties) { NMAccessPoint *ap; - GTimeVal cur_time; const struct ether_addr * addr; const char bad_bssid1[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; const char bad_bssid2[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; @@ -531,8 +530,7 @@ nm_ap_new_from_properties (const char *supplicant_path, GHashTable *properties) return NULL; } - g_get_current_time (&cur_time); - nm_ap_set_last_seen (ap, cur_time.tv_sec); + nm_ap_set_last_seen (ap, (guint32) time (NULL)); if (!nm_ap_get_ssid (ap)) nm_ap_set_broadcast (ap, FALSE); @@ -966,16 +964,15 @@ 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); - if (mode == NM_802_11_MODE_ADHOC || mode == NM_802_11_MODE_INFRA) { - priv = NM_AP_GET_PRIVATE (ap); + priv = NM_AP_GET_PRIVATE (ap); - if (priv->mode != mode) { - priv->mode = mode; - g_object_notify (G_OBJECT (ap), NM_AP_MODE); - } - } else - nm_log_warn (LOGD_WIFI, "Invalid AP mode '%d'", mode); + if (priv->mode != mode) { + priv->mode = mode; + g_object_notify (G_OBJECT (ap), NM_AP_MODE); + } } diff --git a/src/org.freedesktop.NetworkManager.conf b/src/org.freedesktop.NetworkManager.conf index 15b11b7e..7df1c8e8 100644 --- a/src/org.freedesktop.NetworkManager.conf +++ b/src/org.freedesktop.NetworkManager.conf @@ -43,15 +43,12 @@ send_interface="org.freedesktop.NetworkManager.Connection.Active"/> <allow send_destination="org.freedesktop.NetworkManager" - send_interface="org.freedesktop.NetworkManager.Device.Cdma"/> + send_interface="org.freedesktop.NetworkManager.Device.Modem"/> <allow send_destination="org.freedesktop.NetworkManager" send_interface="org.freedesktop.NetworkManager.Device.Wired"/> <allow send_destination="org.freedesktop.NetworkManager" - send_interface="org.freedesktop.NetworkManager.Device.Gsm"/> - - <allow send_destination="org.freedesktop.NetworkManager" send_interface="org.freedesktop.NetworkManager.Device.Serial"/> <allow send_destination="org.freedesktop.NetworkManager" @@ -115,7 +112,5 @@ send_interface="org.freedesktop.NetworkManager" send_member="wake"/> </policy> - - <limit name="max_replies_per_connection">512</limit> </busconfig> diff --git a/src/posix-signals/Makefile.am b/src/posix-signals/Makefile.am new file mode 100644 index 00000000..88c3d8d4 --- /dev/null +++ b/src/posix-signals/Makefile.am @@ -0,0 +1,15 @@ +noinst_LTLIBRARIES = libnm-posix-signals.la + +libnm_posix_signals_la_SOURCES = \ + nm-posix-signals.c \ + nm-posix-signals.h + +libnm_posix_signals_la_CPPFLAGS = \ + $(GLIB_CFLAGS) \ + -DLIBEXECDIR=\"$(libexecdir)\" \ + -DG_DISABLE_DEPRECATED + +libnm_posix_signals_la_LIBADD = \ + -ldl \ + $(GLIB_LIBS) + diff --git a/src/posix-signals/Makefile.in b/src/posix-signals/Makefile.in new file mode 100644 index 00000000..3cacb29f --- /dev/null +++ b/src/posix-signals/Makefile.in @@ -0,0 +1,640 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/posix-signals +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/introspection.m4 \ + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libnl-check.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +am__DEPENDENCIES_1 = +libnm_posix_signals_la_DEPENDENCIES = $(am__DEPENDENCIES_1) +am_libnm_posix_signals_la_OBJECTS = \ + libnm_posix_signals_la-nm-posix-signals.lo +libnm_posix_signals_la_OBJECTS = $(am_libnm_posix_signals_la_OBJECTS) +AM_V_lt = $(am__v_lt_$(V)) +am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +am__v_lt_0 = --silent +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_$(V)) +am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +am__v_CC_0 = @echo " CC " $@; +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_$(V)) +am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(libnm_posix_signals_la_SOURCES) +DIST_SOURCES = $(libnm_posix_signals_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DHCLIENT_PATH = @DHCLIENT_PATH@ +DHCLIENT_VERSION = @DHCLIENT_VERSION@ +DHCPCD_PATH = @DHCPCD_PATH@ +DISABLE_DEPRECATED = @DISABLE_DEPRECATED@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMODULE_CFLAGS = @GMODULE_CFLAGS@ +GMODULE_LIBS = @GMODULE_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ +GNUTLS_LIBS = @GNUTLS_LIBS@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +IPTABLES_PATH = @IPTABLES_PATH@ +IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ +IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ +KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDL = @LIBDL@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ +LIBNL_CFLAGS = @LIBNL_CFLAGS@ +LIBNL_GENL3_CFLAGS = @LIBNL_GENL3_CFLAGS@ +LIBNL_GENL3_LIBS = @LIBNL_GENL3_LIBS@ +LIBNL_LIBS = @LIBNL_LIBS@ +LIBNL_ROUTE3_CFLAGS = @LIBNL_ROUTE3_CFLAGS@ +LIBNL_ROUTE3_LIBS = @LIBNL_ROUTE3_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ +LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MOC = @MOC@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ +NM_MICRO_VERSION = @NM_MICRO_VERSION@ +NM_MINOR_VERSION = @NM_MINOR_VERSION@ +NM_VERSION = @NM_VERSION@ +NSS_CFLAGS = @NSS_CFLAGS@ +NSS_LIBS = @NSS_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKGCONFIG_PATH = @PKGCONFIG_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ +QT_CFLAGS = @QT_CFLAGS@ +QT_LIBS = @QT_LIBS@ +RANLIB = @RANLIB@ +RESOLVCONF_PATH = @RESOLVCONF_PATH@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ +UDEV_BASE_DIR = @UDEV_BASE_DIR@ +USE_NLS = @USE_NLS@ +UUID_CFLAGS = @UUID_CFLAGS@ +UUID_LIBS = @UUID_LIBS@ +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@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +noinst_LTLIBRARIES = libnm-posix-signals.la +libnm_posix_signals_la_SOURCES = \ + nm-posix-signals.c \ + nm-posix-signals.h + +libnm_posix_signals_la_CPPFLAGS = \ + $(GLIB_CFLAGS) \ + -DLIBEXECDIR=\"$(libexecdir)\" \ + -DG_DISABLE_DEPRECATED + +libnm_posix_signals_la_LIBADD = \ + -ldl \ + $(GLIB_LIBS) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/posix-signals/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/posix-signals/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libnm-posix-signals.la: $(libnm_posix_signals_la_OBJECTS) $(libnm_posix_signals_la_DEPENDENCIES) + $(AM_V_CCLD)$(LINK) $(libnm_posix_signals_la_OBJECTS) $(libnm_posix_signals_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_posix_signals_la-nm-posix-signals.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +libnm_posix_signals_la-nm-posix-signals.lo: nm-posix-signals.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_posix_signals_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_posix_signals_la-nm-posix-signals.lo -MD -MP -MF $(DEPDIR)/libnm_posix_signals_la-nm-posix-signals.Tpo -c -o libnm_posix_signals_la-nm-posix-signals.lo `test -f 'nm-posix-signals.c' || echo '$(srcdir)/'`nm-posix-signals.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnm_posix_signals_la-nm-posix-signals.Tpo $(DEPDIR)/libnm_posix_signals_la-nm-posix-signals.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-posix-signals.c' object='libnm_posix_signals_la-nm-posix-signals.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_posix_signals_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_posix_signals_la-nm-posix-signals.lo `test -f 'nm-posix-signals.c' || echo '$(srcdir)/'`nm-posix-signals.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +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 +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/posix-signals/nm-posix-signals.c b/src/posix-signals/nm-posix-signals.c new file mode 100644 index 00000000..22fed831 --- /dev/null +++ b/src/posix-signals/nm-posix-signals.c @@ -0,0 +1,62 @@ +/* -*- 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) 2012 Red Hat, Inc. + */ + +#include "config.h" + +#include <signal.h> + +#include "nm-posix-signals.h" + + +/* Stores the original signal mask of NetworkManager process */ +static sigset_t nm_original_signal_mask; + +void +nm_save_original_signal_mask (sigset_t sig_mask) +{ + nm_original_signal_mask = sig_mask; +} + +const sigset_t * +nm_get_original_signal_mask (void) +{ + return &nm_original_signal_mask; +} + +/* + * Unblock signals. + * If a signal set is passed, those signals are unblocked. If user_data is NULL + * the process' signal mask is set to the saved original mask. + * Note: This function can be used in g_spawn_* as GSpawnChildSetupFunc() + * callback. + */ +void +nm_unblock_posix_signals (gpointer user_data) +{ + sigset_t *user_sigset = (sigset_t *) user_data; + + if (user_sigset != NULL) { + pthread_sigmask (SIG_UNBLOCK, user_sigset, NULL); + } else { + const sigset_t *orig_sig_mask = nm_get_original_signal_mask (); + pthread_sigmask (SIG_SETMASK, orig_sig_mask, NULL); + } +} + diff --git a/src/posix-signals/nm-posix-signals.h b/src/posix-signals/nm-posix-signals.h new file mode 100644 index 00000000..81be5e1c --- /dev/null +++ b/src/posix-signals/nm-posix-signals.h @@ -0,0 +1,36 @@ +/* -*- 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) 2012 Red Hat, Inc. + */ + +#ifndef NM_POSIX_SIGNALS_H +#define NM_POSIX_SIGNALS_H + +#include <glib.h> +#include <signal.h> + +/* + * This function can be used in g_spawn_* as GSpawnChildSetupFunc() + * callback. + */ +void nm_unblock_posix_signals (gpointer user_data); + +void nm_save_original_signal_mask (sigset_t sig_mask); +const sigset_t *nm_get_original_signal_mask (void); + +#endif /* NM_POSIX_SIGNALS_H */ diff --git a/src/ppp-manager/Makefile.am b/src/ppp-manager/Makefile.am index 8df2f584..36e54ec9 100644 --- a/src/ppp-manager/Makefile.am +++ b/src/ppp-manager/Makefile.am @@ -7,7 +7,8 @@ INCLUDES = \ -I${top_srcdir}/src \ -I${top_srcdir}/src/generated \ -I${top_builddir}/src/generated \ - -I${top_srcdir}/src/logging + -I${top_srcdir}/src/logging \ + -I${top_srcdir}/src/posix-signals noinst_LTLIBRARIES = libppp-manager.la @@ -33,6 +34,7 @@ libppp_manager_la_CPPFLAGS = \ libppp_manager_la_LIBADD = \ $(top_builddir)/src/generated/libnm-generated.la \ $(top_builddir)/src/logging/libnm-logging.la \ + $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ $(DBUS_LIBS) \ $(GLIB_LIBS) diff --git a/src/ppp-manager/Makefile.in b/src/ppp-manager/Makefile.in index 55355a7d..c9ff095a 100644 --- a/src/ppp-manager/Makefile.in +++ b/src/ppp-manager/Makefile.in @@ -47,7 +47,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -81,6 +81,7 @@ am__DEPENDENCIES_1 = libppp_manager_la_DEPENDENCIES = \ $(top_builddir)/src/generated/libnm-generated.la \ $(top_builddir)/src/logging/libnm-logging.la \ + $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libppp_manager_la_OBJECTS = libppp_manager_la-nm-ppp-manager.lo libppp_manager_la_OBJECTS = $(am_libppp_manager_la_OBJECTS) @@ -204,6 +205,10 @@ 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@ @@ -299,6 +304,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -337,6 +345,8 @@ 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@ @@ -366,7 +376,8 @@ INCLUDES = \ -I${top_srcdir}/src \ -I${top_srcdir}/src/generated \ -I${top_builddir}/src/generated \ - -I${top_srcdir}/src/logging + -I${top_srcdir}/src/logging \ + -I${top_srcdir}/src/posix-signals noinst_LTLIBRARIES = libppp-manager.la libppp_manager_la_SOURCES = \ @@ -385,6 +396,7 @@ libppp_manager_la_CPPFLAGS = \ libppp_manager_la_LIBADD = \ $(top_builddir)/src/generated/libnm-generated.la \ $(top_builddir)/src/logging/libnm-logging.la \ + $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ $(DBUS_LIBS) \ $(GLIB_LIBS) diff --git a/src/ppp-manager/nm-ppp-manager.c b/src/ppp-manager/nm-ppp-manager.c index 59698c34..73cc566f 100644 --- a/src/ppp-manager/nm-ppp-manager.c +++ b/src/ppp-manager/nm-ppp-manager.c @@ -16,7 +16,7 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Copyright (C) 2008 Novell, Inc. - * Copyright (C) 2008 - 2011 Red Hat, Inc. + * Copyright (C) 2008 - 2012 Red Hat, Inc. */ #include <config.h> @@ -47,11 +47,13 @@ #include "nm-setting-connection.h" #include "nm-setting-ppp.h" #include "nm-setting-pppoe.h" +#include "nm-setting-adsl.h" #include "nm-setting-gsm.h" #include "nm-setting-cdma.h" #include "nm-dbus-manager.h" #include "nm-logging.h" #include "nm-marshal.h" +#include "nm-posix-signals.h" static void impl_ppp_manager_need_secrets (NMPPPManager *manager, DBusGMethodInvocation *context); @@ -304,18 +306,20 @@ monitor_cb (gpointer user_data) { NMPPPManager *manager = NM_PPP_MANAGER (user_data); NMPPPManagerPrivate *priv = NM_PPP_MANAGER_GET_PRIVATE (manager); - struct ifpppstatsreq req; + struct ifreq req; + struct ppp_stats stats; memset (&req, 0, sizeof (req)); - req.stats_ptr = (caddr_t) &req.stats; + memset (&stats, 0, sizeof (stats)); + req.ifr_data = (caddr_t) &stats; - strncpy (req.ifr__name, priv->ip_iface, sizeof (req.ifr__name)); + strncpy (req.ifr_name, priv->ip_iface, sizeof (req.ifr_name)); if (ioctl (priv->monitor_fd, SIOCGPPPSTATS, &req) < 0) { nm_log_warn (LOGD_PPP, "could not read ppp stats: %s", strerror (errno)); } else { g_signal_emit (manager, signals[STATS], 0, - req.stats.p.ppp_ibytes, - req.stats.p.ppp_obytes); + stats.p.ppp_ibytes, + stats.p.ppp_obytes); } return TRUE; @@ -391,6 +395,9 @@ extract_details_from_connection (NMConnection *connection, if (NM_IS_SETTING_PPPOE (setting)) { *username = nm_setting_pppoe_get_username (NM_SETTING_PPPOE (setting)); *password = nm_setting_pppoe_get_password (NM_SETTING_PPPOE (setting)); + } else if (NM_IS_SETTING_ADSL (setting)) { + *username = nm_setting_adsl_get_username (NM_SETTING_ADSL (setting)); + *password = nm_setting_adsl_get_password (NM_SETTING_ADSL (setting)); } else if (NM_IS_SETTING_GSM (setting)) { *username = nm_setting_gsm_get_username (NM_SETTING_GSM (setting)); *password = nm_setting_gsm_get_password (NM_SETTING_GSM (setting)); @@ -792,6 +799,7 @@ static NMCmdLine * create_pppd_cmd_line (NMPPPManager *self, NMSettingPPP *setting, NMSettingPPPOE *pppoe, + NMSettingAdsl *adsl, const char *ppp_name, GError **err) { @@ -819,6 +827,10 @@ create_pppd_cmd_line (NMPPPManager *self, /* NM handles setting the default route */ nm_cmd_line_add_string (cmd, "nodefaultroute"); + /* Allow IPv6 to be configured by IPV6CP */ + nm_cmd_line_add_string (cmd, "ipv6"); + nm_cmd_line_add_string (cmd, ","); + ppp_debug = !!getenv ("NM_PPP_DEBUG"); if ( nm_logging_level_enabled (LOGL_DEBUG) && nm_logging_domain_enabled (LOGD_PPP)) @@ -848,6 +860,34 @@ create_pppd_cmd_line (NMPPPManager *self, nm_cmd_line_add_string (cmd, "rp_pppoe_service"); nm_cmd_line_add_string (cmd, pppoe_service); } + } else if (adsl) { + const gchar *protocol = nm_setting_adsl_get_protocol (adsl); + + if (!strcmp (protocol, NM_SETTING_ADSL_PROTOCOL_PPPOA)) { + guint32 vpi = nm_setting_adsl_get_vpi (adsl); + guint32 vci = nm_setting_adsl_get_vci (adsl); + const char *encaps = nm_setting_adsl_get_encapsulation (adsl); + gchar *vpivci; + + nm_cmd_line_add_string (cmd, "plugin"); + nm_cmd_line_add_string (cmd, "pppoatm.so"); + + vpivci = g_strdup_printf("%d.%d", vpi, vci); + nm_cmd_line_add_string (cmd, vpivci); + g_free (vpivci); + + if (g_strcmp0 (encaps, NM_SETTING_ADSL_ENCAPSULATION_LLC) == 0) + nm_cmd_line_add_string (cmd, "llc-encaps"); + else if (g_strcmp0 (encaps, NM_SETTING_ADSL_ENCAPSULATION_VCMUX) == 0) + nm_cmd_line_add_string (cmd, "vc-encaps"); + + } else if (!strcmp (protocol, NM_SETTING_ADSL_PROTOCOL_PPPOE)) { + nm_cmd_line_add_string (cmd, "plugin"); + nm_cmd_line_add_string (cmd, "rp-pppoe.so"); + nm_cmd_line_add_string (cmd, priv->parent_iface); + } + + nm_cmd_line_add_string (cmd, "noipdefault"); } else { nm_cmd_line_add_string (cmd, priv->parent_iface); /* Don't send some random address as the local address */ @@ -924,6 +964,12 @@ pppd_child_setup (gpointer user_data G_GNUC_UNUSED) /* We are in the child process at this point */ pid_t pid = getpid (); setpgid (pid, pid); + + /* + * We blocked signals in main(). We need to restore original signal + * mask for pppd here so that it can receive signals. + */ + nm_unblock_posix_signals (NULL); } static void @@ -965,6 +1011,7 @@ nm_ppp_manager_start (NMPPPManager *manager, NMSettingPPP *s_ppp; gboolean s_ppp_created = FALSE; NMSettingPPPOE *pppoe_setting; + NMSettingAdsl *adsl_setting; NMCmdLine *ppp_cmd; char *cmd_str; struct stat st; @@ -1006,7 +1053,9 @@ nm_ppp_manager_start (NMPPPManager *manager, if (pppoe_setting) pppoe_fill_defaults (s_ppp); - ppp_cmd = create_pppd_cmd_line (manager, s_ppp, pppoe_setting, ppp_name, err); + adsl_setting = (NMSettingAdsl *) nm_connection_get_setting (connection, NM_TYPE_SETTING_ADSL); + + ppp_cmd = create_pppd_cmd_line (manager, s_ppp, pppoe_setting, adsl_setting, ppp_name, err); if (!ppp_cmd) goto out; diff --git a/src/settings/Makefile.in b/src/settings/Makefile.in index d1278206..b8cbffc4 100644 --- a/src/settings/Makefile.in +++ b/src/settings/Makefile.in @@ -47,7 +47,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -230,6 +230,10 @@ 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@ @@ -325,6 +329,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -363,6 +370,8 @@ 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@ diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index 5d240c77..ddc758c7 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -1355,7 +1355,7 @@ dbus_secrets_auth_cb (NMSettingsConnection *self, TRUE, sender_uid, setting_name, - NM_SETTINGS_GET_SECRETS_FLAG_NONE, + NM_SETTINGS_GET_SECRETS_FLAG_USER_REQUESTED, NULL, dbus_get_agent_secrets_cb, context, diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index 1ead4f8b..96564605 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -49,6 +49,7 @@ #include <nm-setting-serial.h> #include <nm-setting-vpn.h> #include <nm-setting-wired.h> +#include <nm-setting-adsl.h> #include <nm-setting-wireless.h> #include <nm-setting-wireless-security.h> #include <nm-setting-bond.h> @@ -68,6 +69,7 @@ #include "plugins/keyfile/plugin.h" #include "nm-agent-manager.h" #include "nm-settings-utils.h" +#include "nm-connection-provider.h" #define CONFIG_KEY_NO_AUTO_DEFAULT "no-auto-default" @@ -110,6 +112,12 @@ static void impl_settings_save_hostname (NMSettings *self, static void unmanaged_specs_changed (NMSystemConfigInterface *config, gpointer user_data); +static void connection_provider_init (NMConnectionProvider *cp_class); + +G_DEFINE_TYPE_EXTENDED (NMSettings, nm_settings, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_CONNECTION_PROVIDER, connection_provider_init)) + + typedef struct { NMDBusManager *dbus_mgr; DBusGConnection *bus; @@ -127,8 +135,6 @@ typedef struct { GSList *unmanaged_specs; } NMSettingsPrivate; -G_DEFINE_TYPE (NMSettings, nm_settings, G_TYPE_OBJECT) - #define NM_SETTINGS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTINGS, NMSettingsPrivate)) enum { @@ -186,6 +192,7 @@ load_connections (NMSettings *self) unmanaged_specs_changed (NULL, self); g_signal_emit (self, signals[CONNECTIONS_LOADED], 0); + g_signal_emit_by_name (self, NM_CP_SIGNAL_CONNECTIONS_LOADED); } void @@ -674,6 +681,7 @@ connection_removed (NMSettingsConnection *obj, gpointer user_data) /* Re-emit for listeners like NMPolicy */ g_signal_emit (NM_SETTINGS (user_data), signals[CONNECTION_REMOVED], 0, connection); + g_signal_emit_by_name (NM_SETTINGS (user_data), NM_CP_SIGNAL_CONNECTION_REMOVED, connection); g_object_unref (connection); } @@ -701,6 +709,7 @@ connection_updated (NMSettingsConnection *connection, gpointer user_data) signals[CONNECTION_UPDATED], 0, connection); + g_signal_emit_by_name (NM_SETTINGS (user_data), NM_CP_SIGNAL_CONNECTION_UPDATED, connection); } static void @@ -849,6 +858,7 @@ claim_connection (NMSettings *self, if (priv->connections_loaded) { /* Internal added signal */ g_signal_emit (self, signals[CONNECTION_ADDED], 0, connection); + g_signal_emit_by_name (self, NM_CP_SIGNAL_CONNECTION_ADDED, connection); /* Exported D-Bus signal */ g_signal_emit (self, signals[NEW_CONNECTION], 0, connection); @@ -1621,6 +1631,100 @@ nm_settings_device_removed (NMSettings *self, NMDevice *device) /***************************************************************/ +static gint +best_connection_sort (gconstpointer a, gconstpointer b, gpointer user_data) +{ + NMSettingsConnection *ac = (NMSettingsConnection *) a; + NMSettingsConnection *bc = (NMSettingsConnection *) b; + guint64 ats, bts; + + if (!ac && bc) + return -1; + else if (ac && !bc) + return 1; + else if (!ac && !bc) + return 0; + + g_assert (ac && bc); + + /* In the future we may use connection priorities in addition to timestamps */ + ats = nm_settings_connection_get_timestamp (ac); + bts = nm_settings_connection_get_timestamp (bc); + + if (ats < bts) + return -1; + else if (ats > bts) + return 1; + return 0; +} + +static GSList * +get_best_connections (NMConnectionProvider *provider, + guint max_requested, + const char *ctype1, + const char *ctype2, + NMConnectionFilterFunc func, + gpointer func_data) +{ + NMSettings *self = NM_SETTINGS (provider); + NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); + GSList *sorted = NULL; + GHashTableIter iter; + NMSettingsConnection *connection; + guint added = 0; + guint64 oldest = 0; + + g_hash_table_iter_init (&iter, priv->connections); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &connection)) { + if (ctype1 && !nm_connection_is_type (NM_CONNECTION (connection), ctype1)) + continue; + if (ctype2 && !nm_connection_is_type (NM_CONNECTION (connection), ctype2)) + continue; + if (func && !func (provider, NM_CONNECTION (connection), func_data)) + continue; + + /* Don't bother with a connection that's older than the oldest one in the list */ + if ( max_requested + && added >= max_requested + && nm_settings_connection_get_timestamp (connection) <= oldest) + continue; + + /* List is sorted with oldest first */ + sorted = g_slist_insert_sorted_with_data (sorted, connection, best_connection_sort, NULL); + added++; + + if (max_requested && added > max_requested) { + /* Over the limit, remove the oldest one */ + sorted = g_slist_delete_link (sorted, sorted); + added--; + } + + oldest = nm_settings_connection_get_timestamp (NM_SETTINGS_CONNECTION (sorted->data)); + } + + return g_slist_reverse (sorted); +} + +static const GSList * +get_connections (NMConnectionProvider *provider) +{ + static GSList *list = NULL; + NMSettings *self = NM_SETTINGS (provider); + GHashTableIter iter; + NMSettingsConnection *connection; + + /* Lazily free the list with every call so we can keep it 'const' for callers */ + g_slist_free (list); + list = NULL; + + g_hash_table_iter_init (&iter, NM_SETTINGS_GET_PRIVATE (self)->connections); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &connection)) + list = g_slist_prepend (list, connection); + return g_slist_reverse (list); +} + +/***************************************************************/ + NMSettings * nm_settings_new (const char *config_file, const char **plugins, @@ -1660,6 +1764,13 @@ nm_settings_new (const char *config_file, } static void +connection_provider_init (NMConnectionProvider *cp_class) +{ + cp_class->get_best_connections = get_best_connections; + cp_class->get_connections = get_connections; +} + +static void nm_settings_init (NMSettings *self) { NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); @@ -1873,6 +1984,7 @@ nm_settings_class_init (NMSettingsClass *class) dbus_g_error_domain_register (NM_SETTING_PPP_ERROR, NULL, NM_TYPE_SETTING_PPP_ERROR); dbus_g_error_domain_register (NM_SETTING_PPPOE_ERROR, NULL, NM_TYPE_SETTING_PPPOE_ERROR); dbus_g_error_domain_register (NM_SETTING_SERIAL_ERROR, NULL, NM_TYPE_SETTING_SERIAL_ERROR); + dbus_g_error_domain_register (NM_SETTING_ADSL_ERROR, NULL, NM_TYPE_SETTING_ADSL_ERROR); dbus_g_error_domain_register (NM_SETTING_VPN_ERROR, NULL, NM_TYPE_SETTING_VPN_ERROR); dbus_g_error_domain_register (NM_SETTING_WIRED_ERROR, NULL, NM_TYPE_SETTING_WIRED_ERROR); dbus_g_error_domain_register (NM_SETTING_WIRELESS_SECURITY_ERROR, NULL, NM_TYPE_SETTING_WIRELESS_SECURITY_ERROR); diff --git a/src/settings/plugins/Makefile.am b/src/settings/plugins/Makefile.am index 5df57d5e..d4ba12f0 100644 --- a/src/settings/plugins/Makefile.am +++ b/src/settings/plugins/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS=keyfile +SUBDIRS=keyfile example if TARGET_REDHAT SUBDIRS+=ifcfg-rh diff --git a/src/settings/plugins/Makefile.in b/src/settings/plugins/Makefile.in index 0997f445..11560049 100644 --- a/src/settings/plugins/Makefile.in +++ b/src/settings/plugins/Makefile.in @@ -51,7 +51,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -80,7 +80,7 @@ AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ distdir ETAGS = etags CTAGS = ctags -DIST_SUBDIRS = keyfile ifcfg-rh ifcfg-suse ifupdown ifnet +DIST_SUBDIRS = keyfile example ifcfg-rh ifcfg-suse ifupdown ifnet DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ @@ -179,6 +179,10 @@ 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@ @@ -274,6 +278,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -312,6 +319,8 @@ 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@ @@ -332,8 +341,8 @@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ -SUBDIRS = keyfile $(am__append_1) $(am__append_2) $(am__append_3) \ - $(am__append_4) $(am__append_5) +SUBDIRS = keyfile example $(am__append_1) $(am__append_2) \ + $(am__append_3) $(am__append_4) $(am__append_5) all: all-recursive .SUFFIXES: diff --git a/src/settings/plugins/example/Makefile.am b/src/settings/plugins/example/Makefile.am new file mode 100644 index 00000000..027f6f89 --- /dev/null +++ b/src/settings/plugins/example/Makefile.am @@ -0,0 +1,40 @@ +INCLUDES = \ + -I$(top_srcdir)/src/settings \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/include \ + -I$(top_srcdir)/libnm-util \ + -I$(top_builddir)/libnm-util + +# 'noinst' here because this is an example plugin we don't want to install +noinst_LTLIBRARIES = libnm-settings-plugin-example.la + +# The actual plugins typically pull reader.c and writer.c out into +# their own static library so that unit tests can use them without +# having to build the entire plugin. But since this is a simple +# plugin we don't do that yet. + +libnm_settings_plugin_example_la_SOURCES = \ + nm-example-connection.c \ + nm-example-connection.h \ + plugin.c \ + plugin.h \ + errors.c \ + common.h \ + reader.c \ + writer.c + +libnm_settings_plugin_example_la_CPPFLAGS = \ + $(GLIB_CFLAGS) \ + $(GMODULE_CFLAGS) \ + $(DBUS_CFLAGS) \ + -DSYSCONFDIR=\"$(sysconfdir)\" \ + -DG_DISABLE_DEPRECATED + +libnm_settings_plugin_example_la_LIBADD = \ + $(top_builddir)/libnm-util/libnm-util.la \ + $(GLIB_LIBS) \ + $(GMODULE_LIBS) \ + $(GIO_LIBS) + +libnm_settings_plugin_example_la_LDFLAGS = -module -avoid-version + diff --git a/src/settings/plugins/example/Makefile.in b/src/settings/plugins/example/Makefile.in new file mode 100644 index 00000000..463ebac9 --- /dev/null +++ b/src/settings/plugins/example/Makefile.in @@ -0,0 +1,712 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, +# Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/settings/plugins/example +DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/gtk-doc.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intlmacosx.m4 \ + $(top_srcdir)/m4/intltool.m4 $(top_srcdir)/m4/introspection.m4 \ + $(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \ + $(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/libnl-check.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ + $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +am__DEPENDENCIES_1 = +libnm_settings_plugin_example_la_DEPENDENCIES = \ + $(top_builddir)/libnm-util/libnm-util.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +am_libnm_settings_plugin_example_la_OBJECTS = \ + libnm_settings_plugin_example_la-nm-example-connection.lo \ + libnm_settings_plugin_example_la-plugin.lo \ + libnm_settings_plugin_example_la-errors.lo \ + libnm_settings_plugin_example_la-reader.lo \ + libnm_settings_plugin_example_la-writer.lo +libnm_settings_plugin_example_la_OBJECTS = \ + $(am_libnm_settings_plugin_example_la_OBJECTS) +AM_V_lt = $(am__v_lt_$(V)) +am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +am__v_lt_0 = --silent +libnm_settings_plugin_example_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ + $(AM_CFLAGS) $(CFLAGS) \ + $(libnm_settings_plugin_example_la_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_$(V)) +am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +am__v_CC_0 = @echo " CC " $@; +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_$(V)) +am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(libnm_settings_plugin_example_la_SOURCES) +DIST_SOURCES = $(libnm_settings_plugin_example_la_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALL_LINGUAS = @ALL_LINGUAS@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DBUS_CFLAGS = @DBUS_CFLAGS@ +DBUS_LIBS = @DBUS_LIBS@ +DBUS_SYS_DIR = @DBUS_SYS_DIR@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DHCLIENT_PATH = @DHCLIENT_PATH@ +DHCLIENT_VERSION = @DHCLIENT_VERSION@ +DHCPCD_PATH = @DHCPCD_PATH@ +DISABLE_DEPRECATED = @DISABLE_DEPRECATED@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GETTEXT_MACRO_VERSION = @GETTEXT_MACRO_VERSION@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GIO_CFLAGS = @GIO_CFLAGS@ +GIO_LIBS = @GIO_LIBS@ +GLIB_CFLAGS = @GLIB_CFLAGS@ +GLIB_GENMARSHAL = @GLIB_GENMARSHAL@ +GLIB_LIBS = @GLIB_LIBS@ +GLIB_MAKEFILE = @GLIB_MAKEFILE@ +GLIB_MKENUMS = @GLIB_MKENUMS@ +GMODULE_CFLAGS = @GMODULE_CFLAGS@ +GMODULE_LIBS = @GMODULE_LIBS@ +GMSGFMT = @GMSGFMT@ +GMSGFMT_015 = @GMSGFMT_015@ +GNUTLS_CFLAGS = @GNUTLS_CFLAGS@ +GNUTLS_LIBS = @GNUTLS_LIBS@ +GREP = @GREP@ +GTKDOC_CHECK = @GTKDOC_CHECK@ +GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ +GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ +GTKDOC_MKPDF = @GTKDOC_MKPDF@ +GTKDOC_REBASE = @GTKDOC_REBASE@ +GUDEV_CFLAGS = @GUDEV_CFLAGS@ +GUDEV_LIBS = @GUDEV_LIBS@ +HTML_DIR = @HTML_DIR@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INTLLIBS = @INTLLIBS@ +INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@ +INTLTOOL_MERGE = @INTLTOOL_MERGE@ +INTLTOOL_PERL = @INTLTOOL_PERL@ +INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ +INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@ +INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@ +INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@ +INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@ +INTL_MACOSX_LIBS = @INTL_MACOSX_LIBS@ +INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ +INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ +INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ +INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ +INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ +INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ +INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ +INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ +IPTABLES_PATH = @IPTABLES_PATH@ +IWMX_SDK_CFLAGS = @IWMX_SDK_CFLAGS@ +IWMX_SDK_LIBS = @IWMX_SDK_LIBS@ +KERNEL_FIRMWARE_DIR = @KERNEL_FIRMWARE_DIR@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBDL = @LIBDL@ +LIBGCRYPT_CFLAGS = @LIBGCRYPT_CFLAGS@ +LIBGCRYPT_CONFIG = @LIBGCRYPT_CONFIG@ +LIBGCRYPT_LIBS = @LIBGCRYPT_LIBS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBM = @LIBM@ +LIBNL1_CFLAGS = @LIBNL1_CFLAGS@ +LIBNL1_LIBS = @LIBNL1_LIBS@ +LIBNL2_CFLAGS = @LIBNL2_CFLAGS@ +LIBNL2_LIBS = @LIBNL2_LIBS@ +LIBNL3_CFLAGS = @LIBNL3_CFLAGS@ +LIBNL3_LIBS = @LIBNL3_LIBS@ +LIBNL_CFLAGS = @LIBNL_CFLAGS@ +LIBNL_GENL3_CFLAGS = @LIBNL_GENL3_CFLAGS@ +LIBNL_GENL3_LIBS = @LIBNL_GENL3_LIBS@ +LIBNL_LIBS = @LIBNL_LIBS@ +LIBNL_ROUTE3_CFLAGS = @LIBNL_ROUTE3_CFLAGS@ +LIBNL_ROUTE3_LIBS = @LIBNL_ROUTE3_LIBS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBSOUP_CFLAGS = @LIBSOUP_CFLAGS@ +LIBSOUP_LIBS = @LIBSOUP_LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +MOC = @MOC@ +MSGFMT = @MSGFMT@ +MSGFMT_015 = @MSGFMT_015@ +MSGMERGE = @MSGMERGE@ +NM = @NM@ +NMEDIT = @NMEDIT@ +NM_MAJOR_VERSION = @NM_MAJOR_VERSION@ +NM_MICRO_VERSION = @NM_MICRO_VERSION@ +NM_MINOR_VERSION = @NM_MINOR_VERSION@ +NM_VERSION = @NM_VERSION@ +NSS_CFLAGS = @NSS_CFLAGS@ +NSS_LIBS = @NSS_LIBS@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKGCONFIG_PATH = @PKGCONFIG_PATH@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POLKIT_CFLAGS = @POLKIT_CFLAGS@ +POLKIT_LIBS = @POLKIT_LIBS@ +POSUB = @POSUB@ +PPPD_PLUGIN_DIR = @PPPD_PLUGIN_DIR@ +QT_CFLAGS = @QT_CFLAGS@ +QT_LIBS = @QT_LIBS@ +RANLIB = @RANLIB@ +RESOLVCONF_PATH = @RESOLVCONF_PATH@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SYSTEMD_CFLAGS = @SYSTEMD_CFLAGS@ +SYSTEMD_LIBS = @SYSTEMD_LIBS@ +SYSTEM_CA_PATH = @SYSTEM_CA_PATH@ +UDEV_BASE_DIR = @UDEV_BASE_DIR@ +USE_NLS = @USE_NLS@ +UUID_CFLAGS = @UUID_CFLAGS@ +UUID_LIBS = @UUID_LIBS@ +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@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +systemdsystemunitdir = @systemdsystemunitdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +INCLUDES = \ + -I$(top_srcdir)/src/settings \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/include \ + -I$(top_srcdir)/libnm-util \ + -I$(top_builddir)/libnm-util + + +# 'noinst' here because this is an example plugin we don't want to install +noinst_LTLIBRARIES = libnm-settings-plugin-example.la + +# The actual plugins typically pull reader.c and writer.c out into +# their own static library so that unit tests can use them without +# having to build the entire plugin. But since this is a simple +# plugin we don't do that yet. +libnm_settings_plugin_example_la_SOURCES = \ + nm-example-connection.c \ + nm-example-connection.h \ + plugin.c \ + plugin.h \ + errors.c \ + common.h \ + reader.c \ + writer.c + +libnm_settings_plugin_example_la_CPPFLAGS = \ + $(GLIB_CFLAGS) \ + $(GMODULE_CFLAGS) \ + $(DBUS_CFLAGS) \ + -DSYSCONFDIR=\"$(sysconfdir)\" \ + -DG_DISABLE_DEPRECATED + +libnm_settings_plugin_example_la_LIBADD = \ + $(top_builddir)/libnm-util/libnm-util.la \ + $(GLIB_LIBS) \ + $(GMODULE_LIBS) \ + $(GIO_LIBS) + +libnm_settings_plugin_example_la_LDFLAGS = -module -avoid-version +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/settings/plugins/example/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/settings/plugins/example/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libnm-settings-plugin-example.la: $(libnm_settings_plugin_example_la_OBJECTS) $(libnm_settings_plugin_example_la_DEPENDENCIES) + $(AM_V_CCLD)$(libnm_settings_plugin_example_la_LINK) $(libnm_settings_plugin_example_la_OBJECTS) $(libnm_settings_plugin_example_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_settings_plugin_example_la-errors.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_settings_plugin_example_la-nm-example-connection.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_settings_plugin_example_la-plugin.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_settings_plugin_example_la-reader.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnm_settings_plugin_example_la-writer.Plo@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< + +libnm_settings_plugin_example_la-nm-example-connection.lo: nm-example-connection.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_settings_plugin_example_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_settings_plugin_example_la-nm-example-connection.lo -MD -MP -MF $(DEPDIR)/libnm_settings_plugin_example_la-nm-example-connection.Tpo -c -o libnm_settings_plugin_example_la-nm-example-connection.lo `test -f 'nm-example-connection.c' || echo '$(srcdir)/'`nm-example-connection.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnm_settings_plugin_example_la-nm-example-connection.Tpo $(DEPDIR)/libnm_settings_plugin_example_la-nm-example-connection.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='nm-example-connection.c' object='libnm_settings_plugin_example_la-nm-example-connection.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_settings_plugin_example_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_settings_plugin_example_la-nm-example-connection.lo `test -f 'nm-example-connection.c' || echo '$(srcdir)/'`nm-example-connection.c + +libnm_settings_plugin_example_la-plugin.lo: plugin.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_settings_plugin_example_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_settings_plugin_example_la-plugin.lo -MD -MP -MF $(DEPDIR)/libnm_settings_plugin_example_la-plugin.Tpo -c -o libnm_settings_plugin_example_la-plugin.lo `test -f 'plugin.c' || echo '$(srcdir)/'`plugin.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnm_settings_plugin_example_la-plugin.Tpo $(DEPDIR)/libnm_settings_plugin_example_la-plugin.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='plugin.c' object='libnm_settings_plugin_example_la-plugin.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_settings_plugin_example_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_settings_plugin_example_la-plugin.lo `test -f 'plugin.c' || echo '$(srcdir)/'`plugin.c + +libnm_settings_plugin_example_la-errors.lo: errors.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_settings_plugin_example_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_settings_plugin_example_la-errors.lo -MD -MP -MF $(DEPDIR)/libnm_settings_plugin_example_la-errors.Tpo -c -o libnm_settings_plugin_example_la-errors.lo `test -f 'errors.c' || echo '$(srcdir)/'`errors.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnm_settings_plugin_example_la-errors.Tpo $(DEPDIR)/libnm_settings_plugin_example_la-errors.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='errors.c' object='libnm_settings_plugin_example_la-errors.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_settings_plugin_example_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_settings_plugin_example_la-errors.lo `test -f 'errors.c' || echo '$(srcdir)/'`errors.c + +libnm_settings_plugin_example_la-reader.lo: reader.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_settings_plugin_example_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_settings_plugin_example_la-reader.lo -MD -MP -MF $(DEPDIR)/libnm_settings_plugin_example_la-reader.Tpo -c -o libnm_settings_plugin_example_la-reader.lo `test -f 'reader.c' || echo '$(srcdir)/'`reader.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnm_settings_plugin_example_la-reader.Tpo $(DEPDIR)/libnm_settings_plugin_example_la-reader.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='reader.c' object='libnm_settings_plugin_example_la-reader.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_settings_plugin_example_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_settings_plugin_example_la-reader.lo `test -f 'reader.c' || echo '$(srcdir)/'`reader.c + +libnm_settings_plugin_example_la-writer.lo: writer.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_settings_plugin_example_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libnm_settings_plugin_example_la-writer.lo -MD -MP -MF $(DEPDIR)/libnm_settings_plugin_example_la-writer.Tpo -c -o libnm_settings_plugin_example_la-writer.lo `test -f 'writer.c' || echo '$(srcdir)/'`writer.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnm_settings_plugin_example_la-writer.Tpo $(DEPDIR)/libnm_settings_plugin_example_la-writer.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='writer.c' object='libnm_settings_plugin_example_la-writer.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libnm_settings_plugin_example_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libnm_settings_plugin_example_la-writer.lo `test -f 'writer.c' || echo '$(srcdir)/'`writer.c + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +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 +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + 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: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ + pdf pdf-am ps ps-am tags uninstall uninstall-am + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/settings/plugins/example/README b/src/settings/plugins/example/README new file mode 100644 index 00000000..224814d1 --- /dev/null +++ b/src/settings/plugins/example/README @@ -0,0 +1,35 @@ +Plugins generally have three components: + +1) plugin object: manages the individual "connections", which are + just objects wrapped around on-disk config data. The plugin handles requests + to add new connections via the NM D-Bus API, and also watches config + directories for changes to configuration data. It also handles reading and + writing the persistent hostname, if the plugin supports hostnames. Plugins + implement the NMSystemConfigInterface interface. See plugin.c. + +2) "connections": subclasses of NMSettingsConnection. They handle updates to + configuration data, deletion, etc. See NMExampleConnection.c. + +3) reader/writer code: typically a separate static library that gets linked + into the main plugin shared object, so they can be unit tested separately + from the plugin. This code should read config data from disk and create + an NMConnection from it, and be capable of taking an NMConnection and writing + out appropriate configuration data to disk. + +NM will first call the "factory" function that every module must provide, which +is nm_system_config_factory(). That function creates and returns a singleton +instance of the plugin's main object, which implements NMSystemConfigInterface. +That interface is implemented via the object definition in G_DEFINE_TYPE_EXTENDED +in plugin.c, which registers the interface setup function +system_config_interface_init(), which when called actually sets up the vtables +for the functions defined by NMSystemConfigInterface. Thus there are two +entry points into the plugin: nm_system_config_factory() and +the NMSystemConfigInterface methods. + +The plugin also emits various signals (defined by NMSystemConfigInterface) +which NetworkManager listens for. These include persistent hostname changes +(if something modified the file in which the persistent hostname is stored) +and notifications of new connections if they were created via changes to +the on-disk files. The "connection" objects can also emit signals +(defined by the NMSettingsConnection and NMConnection superclasses) when the +connections' backing storage gets changed or deleted. diff --git a/src/settings/plugins/example/common.h b/src/settings/plugins/example/common.h new file mode 100644 index 00000000..a4197070 --- /dev/null +++ b/src/settings/plugins/example/common.h @@ -0,0 +1,56 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager system settings service + * + * 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. + * + * (C) Copyright 2012 Red Hat, Inc. + */ + +#ifndef __COMMON_H__ +#define __COMMON_H__ + +#include <glib.h> + +#include <nm-connection.h> + +/* General info about the plugin that the code may want to use for logging + * purposes. + */ +#define EXAMPLE_PLUGIN_NAME "example" +#define EXAMPLE_PLUGIN_INFO "(c) 2012 Red Hat, Inc. To report bugs please use the NetworkManager mailing list." + +#define EXAMPLE_DIR SYSCONFDIR"/NetworkManager/example-plugin" + +/* Boilerplate stuff for the plugin's error domain. Bits of the code that + * create new errors in the plugin's domain will create errors of + * type EXAMPLE_PLUGIN_ERROR like so: + * + * error = g_error_new_literal (EXAMPLE_PLUGIN_ERROR, + * <specific error number>, + * "This is a really bad error."); + */ +#define EXAMPLE_PLUGIN_ERROR (example_plugin_error_quark ()) +GQuark example_plugin_error_quark (void); + +/* Prototypes for the reader/writer functions */ +NMConnection *connection_from_file (const char *filename, GError **error); + +gboolean write_connection (NMConnection *connection, + const char *existing_path, + char **out_path, + GError **error); + +#endif /* __COMMON_H__ */ + diff --git a/src/settings/plugins/example/errors.c b/src/settings/plugins/example/errors.c new file mode 100644 index 00000000..8181f8a3 --- /dev/null +++ b/src/settings/plugins/example/errors.c @@ -0,0 +1,40 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager system settings service + * + * 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. + * + * (C) Copyright 2012 Red Hat, Inc. + */ + +#include <glib.h> +#include "common.h" + +/* This is boilerplate code for defining the error domain that the plugin may + * return to NetworkManager for various operations. It just registers a + * GObject "quark" (a UUID really) for the error which allows glib to keep + * track of all the different error domains. + */ +GQuark +example_plugin_error_quark (void) +{ + static GQuark error_quark = 0; + + if (G_UNLIKELY (error_quark == 0)) + error_quark = g_quark_from_static_string ("example-plugin-error-quark"); + + return error_quark; +} + + diff --git a/src/settings/plugins/example/nm-example-connection.c b/src/settings/plugins/example/nm-example-connection.c new file mode 100644 index 00000000..e4a69f9b --- /dev/null +++ b/src/settings/plugins/example/nm-example-connection.c @@ -0,0 +1,191 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager system settings service - keyfile plugin + * + * 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) 2012 Red Hat, Inc. + */ + +#include <string.h> +#include <glib/gstdio.h> +#include <NetworkManager.h> +#include <nm-setting-connection.h> +#include <nm-utils.h> + +#include "nm-system-config-interface.h" +#include "nm-dbus-glib-types.h" +#include "nm-example-connection.h" +#include "common.h" + +/* GObject boilerplate; this object is a subclass of NMSettingsConnection + * which is specified by the NM_TYPE_SETTINGS_CONNECTION bit here. That + * in turn is a subclass of NMConnection, so it ends up that NMExampleConnection + * is a subclass of NMConnection too. + */ +G_DEFINE_TYPE (NMExampleConnection, nm_example_connection, NM_TYPE_SETTINGS_CONNECTION) + +#define NM_EXAMPLE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_EXAMPLE_CONNECTION, NMExampleConnectionPrivate)) + +/* Object private instance data */ +typedef struct { + char *path; +} NMExampleConnectionPrivate; + + +/* Creates a new object which encapsulates an on-disk connection and any + * plugin-specific operations or data. + */ +NMExampleConnection * +nm_example_connection_new (const char *full_path, + NMConnection *source, + GError **error) +{ + GObject *object; + NMExampleConnectionPrivate *priv; + NMConnection *tmp; + const char *uuid; + + g_return_val_if_fail (full_path != NULL, NULL); + + /* If we're given a connection already, prefer that instead of re-reading */ + if (source) + tmp = g_object_ref (source); + else { + /* Read the data offdisk and translate it into a simple NMConnection object */ + tmp = connection_from_file (full_path, error); + if (!tmp) + return NULL; + } + + /* Actually create the new NMExampleConnection object */ + object = (GObject *) g_object_new (NM_TYPE_EXAMPLE_CONNECTION, NULL); + if (!object) + goto out; + + priv = NM_EXAMPLE_CONNECTION_GET_PRIVATE (object); + priv->path = g_strdup (full_path); + + /* Update our settings with what was read from the file or what got passed + * in as a source NMConnection. + */ + if (!nm_settings_connection_replace_settings (NM_SETTINGS_CONNECTION (object), tmp, error)) { + g_object_unref (object); + object = NULL; + goto out; + } + + /* Make sure we have a UUID; just a sanity check */ + uuid = nm_connection_get_uuid (NM_CONNECTION (object)); + if (!uuid) { + g_set_error (error, EXAMPLE_PLUGIN_ERROR, 0, + "Connection in file %s had no UUID", full_path); + g_object_unref (object); + object = NULL; + } + +out: + g_object_unref (tmp); + return (NMExampleConnection *) object; +} + +const char * +nm_example_connection_get_path (NMExampleConnection *self) +{ + g_return_val_if_fail (NM_IS_EXAMPLE_CONNECTION (self), NULL); + + /* Simple accessor that returns the file path from our private instance data */ + return NM_EXAMPLE_CONNECTION_GET_PRIVATE (self)->path; +} + +static void +commit_changes (NMSettingsConnection *connection, + NMSettingsConnectionCommitFunc callback, + gpointer user_data) +{ + NMExampleConnectionPrivate *priv = NM_EXAMPLE_CONNECTION_GET_PRIVATE (connection); + char *path = NULL; + GError *error = NULL; + + /* Write the new connection data out to disk. This function passes + * back the path of the file it wrote out so that we know what that + * path is if the connection is a completely new one. + */ + if (!write_connection (NM_CONNECTION (connection), priv->path, &path, &error)) { + callback (connection, error, user_data); + g_clear_error (&error); + return; + } + + /* Update the filename if it changed */ + if (path) { + g_free (priv->path); + priv->path = path; + } + + /* Chain up to parent for generic commit stuff */ + NM_SETTINGS_CONNECTION_CLASS (nm_example_connection_parent_class)->commit_changes (connection, + callback, + user_data); +} + +static void +do_delete (NMSettingsConnection *connection, + NMSettingsConnectionDeleteFunc callback, + gpointer user_data) +{ + NMExampleConnectionPrivate *priv = NM_EXAMPLE_CONNECTION_GET_PRIVATE (connection); + + g_unlink (priv->path); + + /* Chain up to parent for generic deletion stuff */ + NM_SETTINGS_CONNECTION_CLASS (nm_example_connection_parent_class)->delete (connection, + callback, + user_data); +} + +/**************************************************************/ + +static void +nm_example_connection_init (NMExampleConnection *connection) +{ +} + +static void +finalize (GObject *object) +{ + NMExampleConnectionPrivate *priv = NM_EXAMPLE_CONNECTION_GET_PRIVATE (object); + + /* Zero out any secrets so we don't leave them in memory */ + nm_connection_clear_secrets (NM_CONNECTION (object)); + + g_free (priv->path); + + G_OBJECT_CLASS (nm_example_connection_parent_class)->finalize (object); +} + +static void +nm_example_connection_class_init (NMExampleConnectionClass *keyfile_connection_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (keyfile_connection_class); + NMSettingsConnectionClass *settings_class = NM_SETTINGS_CONNECTION_CLASS (keyfile_connection_class); + + /* Tells GObject to allocate and zero our instance data pointer */ + g_type_class_add_private (keyfile_connection_class, sizeof (NMExampleConnectionPrivate)); + + /* Overrides of various superclass methods */ + object_class->finalize = finalize; + settings_class->commit_changes = commit_changes; + settings_class->delete = do_delete; +} diff --git a/src/settings/plugins/example/nm-example-connection.h b/src/settings/plugins/example/nm-example-connection.h new file mode 100644 index 00000000..d6d09e16 --- /dev/null +++ b/src/settings/plugins/example/nm-example-connection.h @@ -0,0 +1,55 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager system settings service - keyfile plugin + * + * 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) 2012 Red Hat, Inc. + */ + +#ifndef NM_EXAMPLE_CONNECTION_H +#define NM_EXAMPLE_CONNECTION_H + +#include <nm-settings-connection.h> + +G_BEGIN_DECLS + +/* GObject boilerplate */ +#define NM_TYPE_EXAMPLE_CONNECTION (nm_example_connection_get_type ()) +#define NM_EXAMPLE_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_EXAMPLE_CONNECTION, NMExampleConnection)) +#define NM_EXAMPLE_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_EXAMPLE_CONNECTION, NMExampleConnectionClass)) +#define NM_IS_EXAMPLE_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_EXAMPLE_CONNECTION)) +#define NM_IS_EXAMPLE_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_EXAMPLE_CONNECTION)) +#define NM_EXAMPLE_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_EXAMPLE_CONNECTION, NMExampleConnectionClass)) + +typedef struct { + NMSettingsConnection parent; +} NMExampleConnection; + +typedef struct { + NMSettingsConnectionClass parent; +} NMExampleConnectionClass; + +GType nm_example_connection_get_type (void); + +/* Actual API that plugin.c will call */ +NMExampleConnection *nm_example_connection_new (const char *filename, + NMConnection *source, + GError **error); + +const char *nm_example_connection_get_path (NMExampleConnection *self); + +G_END_DECLS + +#endif /* NM_EXAMPLE_CONNECTION_H */ diff --git a/src/settings/plugins/example/plugin.c b/src/settings/plugins/example/plugin.c new file mode 100644 index 00000000..04af03e7 --- /dev/null +++ b/src/settings/plugins/example/plugin.c @@ -0,0 +1,868 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager system settings service - keyfile plugin + * + * 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) 2012 Red Hat, Inc. + */ + +#include <config.h> +#include <sys/stat.h> +#include <unistd.h> +#include <sys/types.h> +#include <netinet/ether.h> +#include <string.h> + +#include <gmodule.h> +#include <glib.h> +#include <glib/gstdio.h> +#include <gio/gio.h> + +#include <nm-connection.h> +#include <nm-setting.h> +#include <nm-setting-connection.h> + +#include "plugin.h" +#include "nm-system-config-interface.h" +#include "common.h" +#include "nm-example-connection.h" + +static char *plugin_get_hostname (SCPluginExample *plugin); +static void system_config_interface_init (NMSystemConfigInterface *system_config_interface_class); + +/* GObject object definition. This actually defines the object and tells + * GObject about the interfaces this object provides. Here we provide + * the "system config interface" which is the API that NetworkManager uses + * to communicate with this plugin. + * + * Interface and super/sub-class access with GObject works via casting and + * GObject magically figures out what needs to be called. So, given: + * + * SCPluginExample *plugin = <new plugin>; + * + * you can call GObject methods since SCPluginExample inherits from GObject + * via the G_TYPE_OBJECT argument of G_DEFINE_TYPE_EXTENDED below: + * + * g_object_set_data (G_OBJECT (plugin), ...); + * + * and since SCPluginExample implements NMSystemConfigInterface via the + * G_IMPLEMENT_INTERFACE bit below, we can also call any methods of + * NMSystemConfigInterface (defined in NM sources in nm-system-config-interface.c): + * + * connections = nm_system_config_interface_get_connections (NM_SYSTEM_CONFIG_INTERFACE (plugin)); + * + * For the call to nm_system_config_interface_get_connections() that eventually + * ends up in the get_connections() method in this file because the + * system_config_interface_init() function sets up the vtable for this objects + * implementation of NMSystemConfigInterface. + */ +G_DEFINE_TYPE_EXTENDED (SCPluginExample, sc_plugin_example, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_SYSTEM_CONFIG_INTERFACE, system_config_interface_init)) + +/* Quick define to access the object's private data pointer; this pointer + * points to the object's instance data. + */ +#define SC_PLUGIN_EXAMPLE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SC_TYPE_PLUGIN_EXAMPLE, SCPluginExamplePrivate)) + +/* Instance data. When the object is created, a new structure of this type + * will be created and zeroed for this instance of the object to use. This + * is actually done by g_type_class_add_private() when called from the object's + * class init function. + */ +typedef struct { + /* This hash holds each connection known to this plugin */ + GHashTable *connections; + + /* A watch for changes on the directory that holds the configuration files + * so the plugin can respond to configuration changes on-the-fly and + * tell NM that the connection data has changed. Typically the plugin + * needs to monitor the directory itself (to watch for completely new files) + * while the individual connections watch their individual config files. + */ + GFileMonitor *monitor; + guint monitor_id; + + /* Tracks changes to the global NM config file, just in case our + * plugin has some specific options (like unmanaged devices) that + * might be changed at runtime. + */ + char *conf_file; + GFileMonitor *conf_file_monitor; + guint conf_file_monitor_id; + + /* Persistent hostname if the plugin supports hostnames. Normally used + * for distro plugins; ie Red Hat uses /etc/sysconfig/hostname while + * Debian uses /etc/hostname. Plugins can abstract the storage location + * and just tell NM what the persisten hostname is and when its backing + * file has changed. NM handles actually setting the hostname. + */ + char *hostname; +} SCPluginExamplePrivate; + +static NMSettingsConnection * +_internal_new_connection (SCPluginExample *self, + const char *full_path, + NMConnection *source, + GError **error) +{ + SCPluginExamplePrivate *priv = SC_PLUGIN_EXAMPLE_GET_PRIVATE (self); + NMExampleConnection *connection; + + g_return_val_if_fail (full_path != NULL, NULL); + + /* 'source' will usually be NULL if we're going to read the connection + * off disk. But if the new connection is coming from NetworkManager + * (ie, from a D-Bus AddConnection request) then we'll have 'source' too. + * This function expects the connection to already be written to disk + * so that the NMExampleConnection object can re-read it and intialize + * state in the same manner as when getting a change notification from + * the config directory. That simplifies things somewhat. + */ + + connection = nm_example_connection_new (full_path, source, error); + if (connection) { + g_hash_table_insert (priv->connections, + (gpointer) nm_example_connection_get_path (connection), + connection); + } + + return (NMSettingsConnection *) connection; +} + +/* Read each file in our config directory and try to create a new + * NMExamplePlugin for it. + */ +static void +read_connections (NMSystemConfigInterface *config) +{ + SCPluginExample *self = SC_PLUGIN_EXAMPLE (config); + GDir *dir; + GError *error = NULL; + const char *item; + + dir = g_dir_open (EXAMPLE_DIR, 0, &error); + if (!dir) { + PLUGIN_WARN (EXAMPLE_PLUGIN_NAME, "Cannot read directory '%s': (%d) %s", + EXAMPLE_DIR, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + return; + } + + while ((item = g_dir_read_name (dir))) { + NMSettingsConnection *connection; + char *full_path; + + /* XXX: Check file extension and ignore "~", ".tmp", ".bak", etc */ + + full_path = g_build_filename (EXAMPLE_DIR, item, NULL); + PLUGIN_PRINT (EXAMPLE_PLUGIN_NAME, "parsing %s ... ", item); + + connection = _internal_new_connection (self, full_path, NULL, &error); + if (connection) { + PLUGIN_PRINT (EXAMPLE_PLUGIN_NAME, " read connection '%s'", + nm_connection_get_id (NM_CONNECTION (connection))); + } else { + PLUGIN_PRINT (EXAMPLE_PLUGIN_NAME, " error: %s", + (error && error->message) ? error->message : "(unknown)"); + } + g_clear_error (&error); + g_free (full_path); + } + g_dir_close (dir); +} + +static void +update_connection_settings_commit_cb (NMSettingsConnection *orig, GError *error, gpointer user_data) +{ + /* If there was an error updating the connection's internal stuff, then + * we can't do anything except log it and remove the connection. This might + * happen due to invalid data, but as the data would already have been + * verified before it ever got to this plugin, we shouldn't ever get + * an error here. + */ + if (error) { + g_warning ("%s: '%s' / '%s' invalid: %d", + __func__, + error ? g_type_name (nm_connection_lookup_setting_type_by_quark (error->domain)) : "(none)", + (error && error->message) ? error->message : "(none)", + error ? error->code : -1); + g_clear_error (&error); + + nm_settings_connection_signal_remove (orig); + } +} + +static void +update_connection_settings (NMExampleConnection *orig, + NMExampleConnection *new) +{ + /* This just replaces the orig's internal settings with those from new */ + nm_settings_connection_replace_and_commit (NM_SETTINGS_CONNECTION (orig), + NM_CONNECTION (new), + update_connection_settings_commit_cb, NULL); +} + +/* Monitoring */ + +static void +remove_connection (SCPluginExample *self, + NMExampleConnection *connection, + const char *name) +{ + g_return_if_fail (connection != NULL); + g_return_if_fail (name != NULL); + + /* Removing from the hash table should drop the last reference, but since + * we need the object to stay alive across the signal emission to NM, + * we grab a temporary reference. + */ + g_object_ref (connection); + g_hash_table_remove (SC_PLUGIN_EXAMPLE_GET_PRIVATE (self)->connections, name); + + /* Tell NM the connection is gone */ + nm_settings_connection_signal_remove (NM_SETTINGS_CONNECTION (connection)); + + /* Remove the temporary reference; connection will now be destroyed */ + g_object_unref (connection); +} + +/* Look through all connections we know about and return one with a given UUID */ +static NMExampleConnection * +find_by_uuid (SCPluginExample *self, const char *uuid) +{ + SCPluginExamplePrivate *priv = SC_PLUGIN_EXAMPLE_GET_PRIVATE (self); + GHashTableIter iter; + gpointer data = NULL; + + g_return_val_if_fail (uuid != NULL, NULL); + + g_hash_table_iter_init (&iter, priv->connections); + while (g_hash_table_iter_next (&iter, NULL, &data)) { + NMConnection *candidate = NM_CONNECTION (data); + + if (strcmp (uuid, nm_connection_get_uuid (candidate)) == 0) + return NM_EXAMPLE_CONNECTION (candidate); + } + return NULL; +} + + +static void +dir_changed (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, + gpointer user_data) +{ + NMSystemConfigInterface *config = NM_SYSTEM_CONFIG_INTERFACE (user_data); + SCPluginExample *self = SC_PLUGIN_EXAMPLE (config); + SCPluginExamplePrivate *priv = SC_PLUGIN_EXAMPLE_GET_PRIVATE (self); + char *full_path; + NMExampleConnection *connection; + GError *error = NULL; + + full_path = g_file_get_path (file); + /* XXX: Check here if you need to ignore this file, ie by checking for + * extensions like "~" and ".bak" or ".tmp". If so just return; + */ + + /* Check if we know about this connection already */ + connection = g_hash_table_lookup (priv->connections, full_path); + + switch (event_type) { + case G_FILE_MONITOR_EVENT_DELETED: + if (connection) { + PLUGIN_PRINT (EXAMPLE_PLUGIN_NAME, "removed %s.", full_path); + remove_connection (SC_PLUGIN_EXAMPLE (config), connection, full_path); + } + break; + case G_FILE_MONITOR_EVENT_CREATED: + case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: + if (connection) { + /* Update of an existing connection. Here we re-read the file and + * compare it against the existing connection to check if anything + * actually changed. + */ + NMExampleConnection *tmp; + + tmp = nm_example_connection_new (full_path, NULL, &error); + if (tmp) { + if (!nm_connection_compare (NM_CONNECTION (connection), + NM_CONNECTION (tmp), + NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS | + NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)) { + /* Connection changed; update our internal connection object */ + PLUGIN_PRINT (EXAMPLE_PLUGIN_NAME, "updating %s", full_path); + update_connection_settings (connection, tmp); + } + g_object_unref (tmp); + } else { + /* There was an error parsing the updated connection; it may + * no longer be valid and thus we've got to delete it. If it + * becomes valid again later we'll get another change + * notification, we'll re-read it, and we'll treat it as new. + */ + PLUGIN_PRINT (EXAMPLE_PLUGIN_NAME, " error: %s", + (error && error->message) ? error->message : "(unknown)"); + remove_connection (SC_PLUGIN_EXAMPLE (config), connection, full_path); + } + g_clear_error (&error); + } else { + PLUGIN_PRINT (EXAMPLE_PLUGIN_NAME, "updating %s", full_path); + + /* We don't know about the connection yet, so the change represents + * a completely new connection. + */ + connection = nm_example_connection_new (full_path, NULL, &error); + if (connection) { + NMExampleConnection *found = NULL; + + /* Connection renames will show up as different files but with + * the same UUID. Try to find the original connection. + * A connection rename is treated just like an update except + * there's a bit more housekeeping with the hash table. + */ + found = find_by_uuid (self, nm_connection_get_uuid (NM_CONNECTION (connection))); + if (found) { + const char *old_path = nm_example_connection_get_path (connection); + + /* Removing from the hash table should drop the last reference, + * but of course we want to keep the connection around. + */ + g_object_ref (found); + g_hash_table_remove (priv->connections, old_path); + + /* Updating settings should update the NMExampleConnection's + * filename property too. + */ + update_connection_settings (found, connection); + + /* Re-insert the connection back into the hash with the new filename */ + g_hash_table_insert (priv->connections, + (gpointer) nm_example_connection_get_path (found), + found); + + /* Get rid of the temporary connection */ + g_object_unref (connection); + } else { + /* Completely new connection, not a rename. */ + g_hash_table_insert (priv->connections, + (gpointer) nm_example_connection_get_path (connection), + connection); + /* Tell NM we found a new connection */ + g_signal_emit_by_name (config, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, connection); + } + } else { + PLUGIN_PRINT (EXAMPLE_PLUGIN_NAME, " error: %s", + (error && error->message) ? error->message : "(unknown)"); + g_clear_error (&error); + } + } + break; + default: + break; + } + + g_free (full_path); +} + +static void +conf_file_changed (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, + gpointer data) +{ + SCPluginExample *self = SC_PLUGIN_EXAMPLE (data); + SCPluginExamplePrivate *priv = SC_PLUGIN_EXAMPLE_GET_PRIVATE (self); + char *tmp; + + switch (event_type) { + case G_FILE_MONITOR_EVENT_DELETED: + case G_FILE_MONITOR_EVENT_CREATED: + case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: + /* Unmanaged devices option may have changed; just emit the changed + * signal for unmanaged specs and when NM calls back in to get the + * updated specs we'll re-read the config file then. + */ + g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); + + /* Hostname may also have changed; read it and if it did actually + * change, notify NM. + */ + tmp = plugin_get_hostname (self); + if (g_strcmp0 (tmp, priv->hostname) != 0) { + g_free (priv->hostname); + priv->hostname = tmp; + tmp = NULL; + g_object_notify (G_OBJECT (self), NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME); + } + g_free (tmp); + break; + default: + break; + } +} + +/* This function starts the inotify monitors that watch the plugin's config + * file directory for new connections and changes to existing connections. + * At this time all plugins are expected to make NM aware of changes on-the-fly + * instead of requiring a SIGHUP or SIGUSR1 or some D-Bus method to say + * "reload". + */ +static void +setup_monitoring (NMSystemConfigInterface *config) +{ + SCPluginExamplePrivate *priv = SC_PLUGIN_EXAMPLE_GET_PRIVATE (config); + GFileMonitor *monitor; + GFile *file; + + /* Initialize connection hash here; we use the connection hash as the + * "are we initialized yet" variable. + */ + priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref); + + /* Set up the watch for our config directory */ + file = g_file_new_for_path (EXAMPLE_DIR); + monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL); + g_object_unref (file); + if (monitor) { + /* This registers the dir_changed() function to be called whenever + * the GFileMonitor object notices a change in the directory. + */ + priv->monitor_id = g_signal_connect (monitor, "changed", G_CALLBACK (dir_changed), config); + priv->monitor = monitor; + } + + /* Set up a watch on our configuration file, basically just for watching + * whether the user has changed the unmanaged devices option or the + * persistent hostname. + */ + if (priv->conf_file) { + file = g_file_new_for_path (priv->conf_file); + monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, NULL); + g_object_unref (file); + + if (monitor) { + priv->conf_file_monitor_id = g_signal_connect (monitor, "changed", G_CALLBACK (conf_file_changed), config); + priv->conf_file_monitor = monitor; + } + } +} + +/*******************************************************************/ + +/* Return to NM the full list of connections this plugin owns */ +static GSList * +get_connections (NMSystemConfigInterface *config) +{ + SCPluginExamplePrivate *priv = SC_PLUGIN_EXAMPLE_GET_PRIVATE (config); + GHashTableIter iter; + NMSettingsConnection *connection; + GSList *list = NULL; + + if (!priv->connections) { + /* If we haven't read connections in yet, do so now */ + setup_monitoring (config); + read_connections (config); + } + + /* Add each connection from our internal hash table to a list returned + * to NetworkManager. + */ + g_hash_table_iter_init (&iter, priv->connections); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &connection)) + list = g_slist_prepend (list, connection); + return list; +} + +/* Called by NetworkManager when a user adds a new connection via D-Bus. + * The plugin should convert the data in 'connection' to its on-disk format + * write it out to disk, and return an object that's a subclass of + * NMSettingsConnection. Typically plugins will subclass NMSettingsConnection + * and use that class to handle any plugin-specific stuff like monitoring + * the on-disk config files for changes, and/or parsing the file-format and + * converting back and forth from that to NMConnection. + */ +static NMSettingsConnection * +add_connection (NMSystemConfigInterface *config, + NMConnection *connection, + GError **error) +{ + SCPluginExample *self = SC_PLUGIN_EXAMPLE (config); + NMSettingsConnection *added = NULL; + char *path = NULL; + + /* Write it out first, then add the connection to our internal list; that + * way we don't trigger the new NMSettingsConnection subclass' file watch + * functions needlessly. + */ + if (write_connection (connection, NULL, &path, error)) { + added = _internal_new_connection (self, path, connection, error); + g_free (path); + } + return added; +} + +/* This function returns a list of "unmanaged device specs" which represent + * a list of devices that NetworkManager should not manage. Each unmanaged + * spec item has a specific format starting with a "tag" and followed by + * tag-specific data. The only currently specified item is "mac:" followed + * by the MAC address of the interface NM should not manage. This function + * reads the list of unmanaged devices from wherever the plugin wants to + * store them and returns that list to NetworkManager. + */ +static GSList * +get_unmanaged_specs (NMSystemConfigInterface *config) +{ + SCPluginExamplePrivate *priv = SC_PLUGIN_EXAMPLE_GET_PRIVATE (config); + GKeyFile *key_file; + GSList *specs = NULL; + GError *error = NULL; + char *str, **macs; + int i; + + if (!priv->conf_file) + return NULL; + + key_file = g_key_file_new (); + if (!g_key_file_load_from_file (key_file, priv->conf_file, G_KEY_FILE_NONE, &error)) { + g_warning ("Error parsing file '%s': %s", priv->conf_file, error->message); + g_error_free (error); + goto out; + } + + + str = g_key_file_get_value (key_file, "keyfile", "unmanaged-devices", NULL); + if (!str) + goto out; + + macs = g_strsplit (str, ";", -1); + for (i = 0; macs[i] != NULL; i++) { + /* Verify unmanaged specification and add it to the list */ + if (strlen (macs[i]) > 4 && !strncmp (macs[i], "mac:", 4) && ether_aton (macs[i] + 4)) { + char *p = macs[i]; + + /* To accept uppercase MACs in configuration file, we have to + * convert values to lowercase here. Unmanaged MACs in specs are + * always in lowercase. + */ + while (*p) { + *p = g_ascii_tolower (*p); + p++; + } + + specs = g_slist_append (specs, macs[i]); + } else { + g_warning ("Error in file '%s': invalid unmanaged-devices entry: '%s'", priv->conf_file, macs[i]); + g_free (macs[i]); + } + } + + g_free (macs); /* Yes, g_free, not g_strfreev because we need the strings in the list */ + g_free (str); + +out: + g_key_file_free (key_file); + return specs; +} + + +static char * +plugin_get_hostname (SCPluginExample *plugin) +{ + SCPluginExamplePrivate *priv = SC_PLUGIN_EXAMPLE_GET_PRIVATE (plugin); + GKeyFile *key_file; + char *hostname = NULL; + GError *error = NULL; + + if (!priv->conf_file) + return NULL; + + /* Read the persistent hostname out of backing storage, which happens + * to be the NM config file. Other plugins (like distro-specific ones) + * should read it from the distro-specific location like /etc/hostname. + */ + key_file = g_key_file_new (); + if (g_key_file_load_from_file (key_file, priv->conf_file, G_KEY_FILE_NONE, &error)) + hostname = g_key_file_get_value (key_file, "keyfile", "hostname", NULL); + else { + g_warning ("Error parsing file '%s': %s", priv->conf_file, error->message); + g_error_free (error); + } + + g_key_file_free (key_file); + return hostname; +} + +static gboolean +plugin_set_hostname (SCPluginExample *plugin, const char *hostname) +{ + SCPluginExamplePrivate *priv = SC_PLUGIN_EXAMPLE_GET_PRIVATE (plugin); + GKeyFile *key_file; + GError *error = NULL; + gboolean success = FALSE; + char *data; + gsize len; + + if (!priv->conf_file) { + g_warning ("Error saving hostname: no config file"); + return FALSE; + } + + /* This just saves the hostname to the NM config file in a section + * private to this plugin. + */ + key_file = g_key_file_new (); + if (!g_key_file_load_from_file (key_file, priv->conf_file, G_KEY_FILE_NONE, &error)) { + g_warning ("Error parsing file '%s': %s", priv->conf_file, error->message); + g_error_free (error); + goto out; + } + + g_key_file_set_string (key_file, "example", "hostname", hostname); + + data = g_key_file_to_data (key_file, &len, &error); + if (data) { + /* Save updated file to disk */ + g_file_set_contents (priv->conf_file, data, len, &error); + g_free (data); + + /* Update internal copy of hostname */ + g_free (priv->hostname); + priv->hostname = g_strdup (hostname); + success = TRUE; + } + + if (error) { + g_warning ("Error saving hostname: %s", error->message); + g_error_free (error); + } + +out: + g_key_file_free (key_file); + return success; +} + +/* GObject */ + +static void +sc_plugin_example_init (SCPluginExample *plugin) +{ + /* Here we'd do any instance-specific initialization like setting + * members of SCPluginExamplePrivate to default values. But we + * don't have anything to do here since most initialization is done + * when NM calls the various entry points. + */ +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + switch (prop_id) { + case NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME: + g_value_set_string (value, EXAMPLE_PLUGIN_NAME); + break; + case NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO: + g_value_set_string (value, EXAMPLE_PLUGIN_INFO); + break; + case NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES: + /* Return capabilities to NM; this plugin supports changing connections + * as well as being capable of saving the hostname to persistent storage. + * If the plugin can't write out updated configuration, then obviously + * it shouldn't advertise that capability. If it can't save hostnames + * to persistent storage, it shouldn't advertise that capability either. + */ + g_value_set_uint (value, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS | + NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME); + break; + case NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME: + /* Return the hostname we've read from persistent storage */ + g_value_set_string (value, SC_PLUGIN_EXAMPLE_GET_PRIVATE (object)->hostname); + 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) +{ + const char *hostname; + + switch (prop_id) { + case NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME: + /* We'll get here when the user has changed the hostname via NM's + * D-Bus interface and we're requested to save this hostname to + * persistent storage. + */ + hostname = g_value_get_string (value); + if (hostname && strlen (hostname) < 1) + hostname = NULL; + plugin_set_hostname (SC_PLUGIN_EXAMPLE (object), hostname); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +dispose (GObject *object) +{ + SCPluginExamplePrivate *priv = SC_PLUGIN_EXAMPLE_GET_PRIVATE (object); + + /* GObject has a two-stage object destruction process: dispose and finalize. + * In dispose the object should free any references it might have on other + * objects to break circular refs, then it's finally cleaned up by finalize. + * We don't bother to implement a finalize, so we just make sure that we + * clean everything up (including clearing pointers) in dispose so that + * if GObject decides to revive this object post-dispose (yes, legal) + * we don't crash on dangling pointers. + */ + + if (priv->monitor) { + if (priv->monitor_id) { + g_signal_handler_disconnect (priv->monitor, priv->monitor_id); + priv->monitor_id = 0; + } + + g_file_monitor_cancel (priv->monitor); + g_object_unref (priv->monitor); + priv->monitor = NULL; + } + + if (priv->conf_file_monitor) { + if (priv->conf_file_monitor_id) { + g_signal_handler_disconnect (priv->conf_file_monitor, priv->conf_file_monitor_id); + priv->conf_file_monitor_id = 0; + } + + g_file_monitor_cancel (priv->conf_file_monitor); + g_object_unref (priv->conf_file_monitor); + priv->conf_file_monitor = NULL; + } + + if (priv->connections) { + /* Destroying the connections hash unrefs each connection in it + * due to the GHashTable value_destroy_func that we passed into + * g_hash_table_new_full(). + */ + g_hash_table_destroy (priv->connections); + priv->connections = NULL; + } + + g_free (priv->hostname); + priv->hostname = NULL; + g_free (priv->conf_file); + priv->conf_file = NULL; + + /* Chain up to the superclass */ + G_OBJECT_CLASS (sc_plugin_example_parent_class)->dispose (object); +} + +/* This function gets called to set up any method and property overrides + * of superclasses, and also (if we actually had any) to set up any + * custom properties and signals this object might have. This is called before + * the object is actually instantiated; it just sets up the generic class + * stuff, not anything related to a specific object instance. + */ +static void +sc_plugin_example_class_init (SCPluginExampleClass *req_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (req_class); + + /* This actually creates and zeros the object's instance data struct */ + g_type_class_add_private (req_class, sizeof (SCPluginExamplePrivate)); + + /* Override GObject base class methods with our custom implementations */ + object_class->dispose = dispose; + object_class->get_property = get_property; + object_class->set_property = set_property; + + /* Override various GObject properties that we need to change. Here we + * just tell GObject that we will be handling the get/set operations for + * these specific properties. They are actually defined by the + * NMSystemConfigInterface interface in nm-system-config-interface.c. + * What happens here is that we tell GObject that for a given property + * name (ie NM_SYSTEM_CONFIG_INTERFACE_NAME) we'll be using the enum value + * NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME locally in get_property() and + * set_property(). + */ + g_object_class_override_property (object_class, + NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME, + NM_SYSTEM_CONFIG_INTERFACE_NAME); + + g_object_class_override_property (object_class, + NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO, + NM_SYSTEM_CONFIG_INTERFACE_INFO); + + g_object_class_override_property (object_class, + NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES, + NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES); + + g_object_class_override_property (object_class, + NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME, + NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME); +} + +static void +system_config_interface_init (NMSystemConfigInterface *sci_intf) +{ + /* Interface implementation for NMSystemConfigInterface. This sets + * up the GInterface vtable that lets GObject know what functions to + * call for each method of the NMSystemConfigInterface interface. + */ + sci_intf->get_connections = get_connections; + sci_intf->add_connection = add_connection; + sci_intf->get_unmanaged_specs = get_unmanaged_specs; +} + +/*******************************************************************/ + +/* Factory function: this is the first entry point for NetworkManager, which + * gets called during NM startup to create the the instance of this plugin + * that NetworkManager will actually use. Since every plugin is a singleton + * we just return a singleton instance. This function should never be called + * twice. + */ +G_MODULE_EXPORT GObject * +nm_system_config_factory (const char *config_file) +{ + static SCPluginExample *singleton = NULL; + SCPluginExamplePrivate *priv; + + if (!singleton) { + /* Instantiate our plugin */ + singleton = SC_PLUGIN_EXAMPLE (g_object_new (SC_TYPE_PLUGIN_EXAMPLE, NULL)); + if (singleton) { + priv = SC_PLUGIN_EXAMPLE_GET_PRIVATE (singleton); + + /* Cache the config file path */ + priv->conf_file = g_strdup (config_file); + } + } else { + /* This function should never be called twice */ + g_assert_not_reached (); + } + + return G_OBJECT (singleton); +} + diff --git a/src/settings/plugins/example/plugin.h b/src/settings/plugins/example/plugin.h new file mode 100644 index 00000000..23b68e2e --- /dev/null +++ b/src/settings/plugins/example/plugin.h @@ -0,0 +1,55 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager system settings service - example plugin + * + * 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) 2012 Red Hat, Inc. + */ + +#ifndef _PLUGIN_H_ +#define _PLUGIN_H_ + +#include <glib-object.h> + +/* GObject boilerplate: you usually only need to rename 'example' here to + * your plugin's name. These functions get used when casting pointers + * to your plugin's object type. + */ +#define SC_TYPE_PLUGIN_EXAMPLE (sc_plugin_example_get_type ()) +#define SC_PLUGIN_EXAMPLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SC_TYPE_PLUGIN_EXAMPLE, SCPluginExample)) +#define SC_PLUGIN_EXAMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SC_TYPE_PLUGIN_EXAMPLE, SCPluginExampleClass)) +#define SC_IS_PLUGIN_EXAMPLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SC_TYPE_PLUGIN_EXAMPLE)) +#define SC_IS_PLUGIN_EXAMPLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SC_TYPE_PLUGIN_EXAMPLE)) +#define SC_PLUGIN_EXAMPLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SC_TYPE_PLUGIN_EXAMPLE, SCPluginExampleClass)) + +typedef struct { + /* GObject instance structure for the plugin; we don't do anything special + * here so this object's instance is exactly the same as its parent. + */ + GObject parent; +} SCPluginExample; + +typedef struct { + /* GObject class structure; we don't do anything special here + * so this object's class is exactly the same as its parent. Typically + * if the plugin implemented custom signals their prototypes would go + * here, but most plugins don't need to do this. + */ + GObjectClass parent; +} SCPluginExampleClass; + +GType sc_plugin_example_get_type (void); + +#endif /* _PLUGIN_H_ */ diff --git a/src/settings/plugins/example/reader.c b/src/settings/plugins/example/reader.c new file mode 100644 index 00000000..9a4cecaa --- /dev/null +++ b/src/settings/plugins/example/reader.c @@ -0,0 +1,46 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager system settings service + * + * 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) 2012 Red Hat, Inc. + */ + +#include <config.h> +#include <glib.h> + +#include <nm-connection.h> +#include <NetworkManager.h> + +#include "common.h" + +NMConnection * +connection_from_file (const char *filename, GError **error) +{ + /* This function should, given a file path, read that file and convert its + * data into an NMConnection. There are two approaches to this. First, + * if the plugin data format is similar to the NMConnection internal + * format, you can get away with calling nm_connection_for_each_setting_value() + * to iterate through every possible setting's keys and read that value + * from the plugin's format. If the plugin's format is siginificantly + * different then you may have to build up the connection manually by + * determining the type of connection from the on-disk data, creating + * each setting object, adding the values, then adding that setting to + * the NMConnection. + */ + + return NULL; +} + diff --git a/src/settings/plugins/example/writer.c b/src/settings/plugins/example/writer.c new file mode 100644 index 00000000..4703fa94 --- /dev/null +++ b/src/settings/plugins/example/writer.c @@ -0,0 +1,55 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager system settings service + * + * 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) 2012 Red Hat, Inc. + */ + +#include <config.h> +#include <glib.h> + +#include <nm-connection.h> + +#include "common.h" + +gboolean +write_connection (NMConnection *connection, + const char *existing_path, + char **out_path, + GError **error) +{ + /* This function should take the NMConnection and convert it to the format + * which this plugin uses on-disk and then write out that data. It returns + * the file path of the file that represents this connection data so that + * the plugin can track it for change notification and updates. If + * 'existing_path' is given we can assume that this is an update of an + * existing connection and not a completely new one. + */ + + /* There are two approaches to converting the data. The first more manual + * approach consists of grabbing each setting value from the NMConnection + * and converting it into the appropriate value for the plugin's data + * format. This is usually taken by distro plugins becuase their format + * is significantly different than NetworkManager's internal format. + * The second uses nm_connection_for_each_setting_value() to iterate + * through each value of each setting in the NMConnection, convert it to + * the required format, and write it out, but this requires that the + * plugin format more closely follow the NetworkManager internal format. + */ + + return FALSE; +} + diff --git a/src/settings/plugins/ifcfg-rh/Makefile.am b/src/settings/plugins/ifcfg-rh/Makefile.am index 8b5b0f24..68225ba1 100644 --- a/src/settings/plugins/ifcfg-rh/Makefile.am +++ b/src/settings/plugins/ifcfg-rh/Makefile.am @@ -25,6 +25,7 @@ libifcfg_rh_io_la_SOURCES = \ INCLUDES = \ -I$(top_srcdir)/src/wifi \ -I$(top_srcdir)/src/settings \ + -I$(top_srcdir)/src/posix-signals \ -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -I$(top_srcdir)/libnm-glib \ @@ -40,6 +41,7 @@ libifcfg_rh_io_la_CPPFLAGS = \ libifcfg_rh_io_la_LIBADD = \ $(top_builddir)/src/wifi/libwifi-utils.la \ + $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ $(top_builddir)/libnm-util/libnm-util.la \ $(GLIB_LIBS) \ $(NSS_LIBS) diff --git a/src/settings/plugins/ifcfg-rh/Makefile.in b/src/settings/plugins/ifcfg-rh/Makefile.in index 3325c7e8..ba3bb528 100644 --- a/src/settings/plugins/ifcfg-rh/Makefile.in +++ b/src/settings/plugins/ifcfg-rh/Makefile.in @@ -48,7 +48,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -82,6 +82,7 @@ LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkglib_LTLIBRARIES) am__DEPENDENCIES_1 = libifcfg_rh_io_la_DEPENDENCIES = \ $(top_builddir)/src/wifi/libwifi-utils.la \ + $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ $(top_builddir)/libnm-util/libnm-util.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_libifcfg_rh_io_la_OBJECTS = libifcfg_rh_io_la-shvar.lo \ @@ -249,6 +250,10 @@ 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@ @@ -344,6 +349,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -382,6 +390,8 @@ 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@ @@ -423,6 +433,7 @@ libifcfg_rh_io_la_SOURCES = \ INCLUDES = \ -I$(top_srcdir)/src/wifi \ -I$(top_srcdir)/src/settings \ + -I$(top_srcdir)/src/posix-signals \ -I$(top_srcdir)/include \ -I$(top_builddir)/include \ -I$(top_srcdir)/libnm-glib \ @@ -438,6 +449,7 @@ libifcfg_rh_io_la_CPPFLAGS = \ libifcfg_rh_io_la_LIBADD = \ $(top_builddir)/src/wifi/libwifi-utils.la \ + $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ $(top_builddir)/libnm-util/libnm-util.la \ $(GLIB_LIBS) \ $(NSS_LIBS) diff --git a/src/settings/plugins/ifcfg-rh/reader.c b/src/settings/plugins/ifcfg-rh/reader.c index 01d83c1b..a2b08e4f 100644 --- a/src/settings/plugins/ifcfg-rh/reader.c +++ b/src/settings/plugins/ifcfg-rh/reader.c @@ -48,6 +48,7 @@ #include <nm-utils.h> #include "wifi-utils.h" +#include "nm-posix-signals.h" #include "common.h" #include "shvar.h" @@ -208,6 +209,12 @@ iscsiadm_child_setup (gpointer user_data G_GNUC_UNUSED) */ pid_t pid = getpid (); setpgid (pid, pid); + + /* + * We blocked signals in main(). We need to restore original signal + * mask for iscsiadm here so that it can receive signals. + */ + nm_unblock_posix_signals (NULL); } static char * @@ -3732,8 +3739,8 @@ make_vlan_setting (shvarFile *ifcfg, char *value = NULL; char *iface_name = NULL; char *parent = NULL; - const char *p = NULL, *w; - gboolean has_numbers = FALSE; + const char *p = NULL; + char *end = NULL; gint vlan_id = -1; guint32 vlan_flags = 0; @@ -3773,17 +3780,12 @@ make_vlan_setting (shvarFile *ifcfg, p = iface_name + 4; } - w = p; - while (*w && !has_numbers) - has_numbers = g_ascii_isdigit (*w); - - /* Grab VLAN ID from interface name; this takes precedence over the - * separate VLAN_ID property for backwards compat. - */ - if (has_numbers) { - errno = 0; - vlan_id = (gint) g_ascii_strtoll (p, NULL, 10); - if (vlan_id < 0 || vlan_id > 4095 || errno) { + if (p) { + /* Grab VLAN ID from interface name; this takes precedence over the + * separate VLAN_ID property for backwards compat. + */ + vlan_id = (gint) g_ascii_strtoll (p, &end, 10); + if (vlan_id < 0 || vlan_id > 4095 || end == p || *end) { g_set_error (error, IFCFG_PLUGIN_ERROR, 0, "Failed to determine VLAN ID from DEVICE '%s'", iface_name); diff --git a/src/settings/plugins/ifcfg-rh/tests/Makefile.in b/src/settings/plugins/ifcfg-rh/tests/Makefile.in index 5e8abf83..dd601727 100644 --- a/src/settings/plugins/ifcfg-rh/tests/Makefile.in +++ b/src/settings/plugins/ifcfg-rh/tests/Makefile.in @@ -48,7 +48,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -211,6 +211,10 @@ 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@ @@ -306,6 +310,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -344,6 +351,8 @@ 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@ diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in index 4f34cfc3..ab8dc497 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.in @@ -46,7 +46,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -134,6 +134,10 @@ 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@ @@ -229,6 +233,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -267,6 +274,8 @@ 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@ diff --git a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-2 b/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-2 index bf98da5a..6a63e817 100644 --- a/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-2 +++ b/src/settings/plugins/ifcfg-rh/tests/network-scripts/keys-test-wifi-wpa-psk-2 @@ -1,2 +1,2 @@ -WPA_PSK=$'They\'re really saying I love you. >>`<<' +WPA_PSK=$'They\'re really saying I love you. >>`<< \' diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index 62882a76..83b60d22 100644 --- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -4927,7 +4927,7 @@ test_read_wifi_wpa_psk_2 (void) GError *error = NULL; const char *tmp; const char *expected_id = "System ipsum (test-wifi-wpa-psk-2)"; - const char *expected_psk = "They're really saying I love you. >>`<<"; + const char *expected_psk = "They're really saying I love you. >>`<< \\"; connection = connection_from_file (TEST_IFCFG_WIFI_WPA_PSK_2, NULL, @@ -12858,7 +12858,7 @@ int main (int argc, char **argv) FALSE, TRUE, TRUE, - "blah`oops\"grr'$*@~!%"); + "blah`oops\"grr'$*@~!%\\"); test_write_wifi_wpa_psk_adhoc (); test_write_wifi_wpa_eap_tls (); test_write_wifi_wpa_eap_ttls_tls (); diff --git a/src/settings/plugins/ifcfg-rh/utils.c b/src/settings/plugins/ifcfg-rh/utils.c index 0b7ddf36..908d3364 100644 --- a/src/settings/plugins/ifcfg-rh/utils.c +++ b/src/settings/plugins/ifcfg-rh/utils.c @@ -189,7 +189,7 @@ utils_single_unquote_string (const char *str) i = quote + dollar; while (i < slen - quote) { - if (str[i] == escape_char && str[i+1] == q_char) + if (str[i] == escape_char && str[i+1] == q_char && i+1 < slen-quote) i++; new_str[j++] = str[i++]; } diff --git a/src/settings/plugins/ifcfg-rh/writer.c b/src/settings/plugins/ifcfg-rh/writer.c index e2aa57dd..a431a30d 100644 --- a/src/settings/plugins/ifcfg-rh/writer.c +++ b/src/settings/plugins/ifcfg-rh/writer.c @@ -1030,6 +1030,7 @@ write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error) g_free (tmp); } + svSetValue (ifcfg, "MACADDR", NULL, FALSE); cloned_mac = nm_setting_wired_get_cloned_mac_address (s_wired); if (cloned_mac) { tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X", diff --git a/src/settings/plugins/ifcfg-suse/Makefile.in b/src/settings/plugins/ifcfg-suse/Makefile.in index ac528342..25c3d345 100644 --- a/src/settings/plugins/ifcfg-suse/Makefile.in +++ b/src/settings/plugins/ifcfg-suse/Makefile.in @@ -47,7 +47,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -197,6 +197,10 @@ 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@ @@ -292,6 +296,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -330,6 +337,8 @@ 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@ diff --git a/src/settings/plugins/ifnet/Makefile.am b/src/settings/plugins/ifnet/Makefile.am index 84deda5b..07a2fc88 100644 --- a/src/settings/plugins/ifnet/Makefile.am +++ b/src/settings/plugins/ifnet/Makefile.am @@ -1,5 +1,6 @@ SUBDIRS = . tests INCLUDES = \ + -I$(top_srcdir)/src/wifi \ -I$(top_srcdir)/src/settings \ -I$(top_srcdir)/include \ -I$(top_srcdir)/libnm-glib \ @@ -52,6 +53,7 @@ lib_ifnet_io_la_CPPFLAGS = \ -DSBINDIR=\"$(sbindir)\" lib_ifnet_io_la_LIBADD = \ + $(top_builddir)/src/wifi/libwifi-utils.la \ $(top_builddir)/libnm-util/libnm-util.la \ $(GLIB_LIBS)\ $(GIO_LIBS) diff --git a/src/settings/plugins/ifnet/Makefile.in b/src/settings/plugins/ifnet/Makefile.in index 322adbf8..acf4e8bc 100644 --- a/src/settings/plugins/ifnet/Makefile.in +++ b/src/settings/plugins/ifnet/Makefile.in @@ -47,7 +47,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -79,6 +79,7 @@ am__installdirs = "$(DESTDIR)$(pkglibdir)" LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkglib_LTLIBRARIES) am__DEPENDENCIES_1 = lib_ifnet_io_la_DEPENDENCIES = \ + $(top_builddir)/src/wifi/libwifi-utils.la \ $(top_builddir)/libnm-util/libnm-util.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_lib_ifnet_io_la_OBJECTS = lib_ifnet_io_la-net_parser.lo \ @@ -245,6 +246,10 @@ 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@ @@ -340,6 +345,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -378,6 +386,8 @@ 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@ @@ -400,6 +410,7 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = . tests INCLUDES = \ + -I$(top_srcdir)/src/wifi \ -I$(top_srcdir)/src/settings \ -I$(top_srcdir)/include \ -I$(top_srcdir)/libnm-glib \ @@ -449,6 +460,7 @@ lib_ifnet_io_la_CPPFLAGS = \ -DSBINDIR=\"$(sbindir)\" lib_ifnet_io_la_LIBADD = \ + $(top_builddir)/src/wifi/libwifi-utils.la \ $(top_builddir)/libnm-util/libnm-util.la \ $(GLIB_LIBS)\ $(GIO_LIBS) diff --git a/src/settings/plugins/ifnet/net_parser.c b/src/settings/plugins/ifnet/net_parser.c index 38765f5f..2562e613 100644 --- a/src/settings/plugins/ifnet/net_parser.c +++ b/src/settings/plugins/ifnet/net_parser.c @@ -22,7 +22,14 @@ #include <string.h> #include <nm-system-config-interface.h> #include <stdio.h> + +#include <sys/ioctl.h> +#include <net/if.h> +#include <unistd.h> + #include "plugin.h" +#include "wifi-utils.h" + #include "net_parser.h" #include "net_utils.h" @@ -122,6 +129,24 @@ is_global_setting (char *key) return 0; } +/* Find out whether the 'iface' is an interface */ +static gboolean +name_is_interface (const char *iface) +{ + int fd; + struct ifreq ifr; + gboolean is_iface = FALSE; + + fd = socket (PF_INET, SOCK_DGRAM, 0); + if (fd >= 0) { + strncpy (ifr.ifr_name, iface, IFNAMSIZ); + if (ioctl (fd, SIOCGIFHWADDR, &ifr) == 0) + is_iface = TRUE; + close (fd); + } + return is_iface; +} + /* Parse a complete line */ /* Connection type is determined here */ static void @@ -143,12 +168,13 @@ init_block_by_line (gchar * buf) pos = g_strrstr (key_value[0], "_"); if (pos == NULL || is_global_setting (key_value[0])) { /* global data */ - PLUGIN_PRINT (IFNET_PLUGIN_NAME, "global:%s-%s\n", key_value[0], - key_value[1]); - g_hash_table_insert (global_settings_table, - g_strdup (key_value[0]), - g_strdup (key_value[1])); + data = g_strdup (key_value[1]); + tmp = strip_string (data, '"'); + strip_string (tmp, '\''); + PLUGIN_PRINT (IFNET_PLUGIN_NAME, "global:%s-%s\n", key_value[0], tmp); + g_hash_table_insert (global_settings_table, g_strdup (key_value[0]), g_strdup (tmp)); g_strfreev (key_value); + g_free (data); return; } *pos++ = '\0'; @@ -165,8 +191,12 @@ init_block_by_line (gchar * buf) /* ignored connection */ conn = add_new_connection_config ("ignore", pos); } else - /* wireless connection */ - conn = add_new_connection_config ("wireless", pos); + if (name_is_interface (pos) && !wifi_utils_is_wifi (pos, NULL)) + /* wired connection */ + conn = add_new_connection_config ("wired", pos); + else + /* wireless connection */ + conn = add_new_connection_config ("wireless", pos); } data = g_strdup (key_value[1]); tmp = strip_string (data, '"'); @@ -593,7 +623,7 @@ ifnet_flush_to_file (const char *config_file) /* Writing global data */ while (g_hash_table_iter_next (&iter, &key, &value)) { out_line = - g_strdup_printf ("%s=%s\n", (gchar *) key, (gchar *) value); + g_strdup_printf ("%s=\"%s\"\n", (gchar *) key, (gchar *) value); g_io_channel_write_chars (channel, out_line, -1, &bytes_written, error); if (bytes_written == 0 || (error && *error)) diff --git a/src/settings/plugins/ifnet/net_utils.c b/src/settings/plugins/ifnet/net_utils.c index f1687479..d613db6a 100644 --- a/src/settings/plugins/ifnet/net_utils.c +++ b/src/settings/plugins/ifnet/net_utils.c @@ -404,7 +404,7 @@ has_ip6_address (const char *conn_name) g_return_val_if_fail (conn_name != NULL, FALSE); ipset = split_addresses (ifnet_get_data (conn_name, "config")); - length = g_strv_length (ipset); + length = ipset ? g_strv_length (ipset) : 0; for (i = 0; i < length; i++) { if (!is_ip6_address (ipset[i])) continue; @@ -618,7 +618,7 @@ convert_ip4_config_block (const char *conn_name) g_return_val_if_fail (conn_name != NULL, NULL); ipset = split_addresses (ifnet_get_data (conn_name, "config")); - length = g_strv_length (ipset); + length = ipset ? g_strv_length (ipset) : 0; routes = ifnet_get_data (conn_name, "routes"); if (routes) @@ -654,7 +654,7 @@ convert_ip6_config_block (const char *conn_name) g_return_val_if_fail (conn_name != NULL, NULL); ipset = split_addresses (ifnet_get_data (conn_name, "config")); - length = g_strv_length (ipset); + length = ipset ? g_strv_length (ipset) : 0; for (i = 0; i < length; i++) { ip = ipset[i]; ip = strip_string (ip, '"'); @@ -684,7 +684,7 @@ convert_ip4_routes_block (const char *conn_name) g_return_val_if_fail (conn_name != NULL, NULL); ipset = split_routes (ifnet_get_data (conn_name, "routes")); - length = g_strv_length (ipset); + length = ipset ? g_strv_length (ipset) : 0; for (i = 0; i < length; i++) { ip = ipset[i]; if (find_default_gateway_str (ip) || strstr (ip, "::") @@ -718,7 +718,7 @@ convert_ip6_routes_block (const char *conn_name) g_return_val_if_fail (conn_name != NULL, NULL); ipset = split_routes (ifnet_get_data (conn_name, "routes")); - length = g_strv_length (ipset); + length = ipset ? g_strv_length (ipset) : 0; for (i = 0; i < length; i++) { ip = ipset[i]; ip = strip_string (ip, '"'); diff --git a/src/settings/plugins/ifnet/tests/Makefile.am b/src/settings/plugins/ifnet/tests/Makefile.am index 20a26805..85d42388 100644 --- a/src/settings/plugins/ifnet/tests/Makefile.am +++ b/src/settings/plugins/ifnet/tests/Makefile.am @@ -10,7 +10,8 @@ check_ifnet_CPPFLAGS = $(CHECK_CFLAGS) $(GLIB_CFLAGS) check_ifnet_LDADD = $(top_builddir)/libnm-util/libnm-util.la \ $(builddir)/../lib-ifnet-io.la \ $(CHECK_LIBS) \ - $(GLIB_LIBS) + $(GLIB_LIBS) \ + $(LIBM) EXTRA_DIST = hostname \ net \ net.all \ diff --git a/src/settings/plugins/ifnet/tests/Makefile.in b/src/settings/plugins/ifnet/tests/Makefile.in index 02ee121f..743e547c 100644 --- a/src/settings/plugins/ifnet/tests/Makefile.in +++ b/src/settings/plugins/ifnet/tests/Makefile.in @@ -48,7 +48,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -59,7 +59,8 @@ am_check_ifnet_OBJECTS = check_ifnet-test_all.$(OBJEXT) check_ifnet_OBJECTS = $(am_check_ifnet_OBJECTS) am__DEPENDENCIES_1 = check_ifnet_DEPENDENCIES = $(top_builddir)/libnm-util/libnm-util.la \ - $(builddir)/../lib-ifnet-io.la $(am__DEPENDENCIES_1) + $(builddir)/../lib-ifnet-io.la $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) AM_V_lt = $(am__v_lt_$(V)) am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) am__v_lt_0 = --silent @@ -168,6 +169,10 @@ 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@ @@ -263,6 +268,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -301,6 +309,8 @@ 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@ @@ -332,7 +342,8 @@ check_ifnet_CPPFLAGS = $(CHECK_CFLAGS) $(GLIB_CFLAGS) check_ifnet_LDADD = $(top_builddir)/libnm-util/libnm-util.la \ $(builddir)/../lib-ifnet-io.la \ $(CHECK_LIBS) \ - $(GLIB_LIBS) + $(GLIB_LIBS) \ + $(LIBM) EXTRA_DIST = hostname \ net \ diff --git a/src/settings/plugins/ifnet/tests/net b/src/settings/plugins/ifnet/tests/net index 27d39f44..a5ac9ca2 100644 --- a/src/settings/plugins/ifnet/tests/net +++ b/src/settings/plugins/ifnet/tests/net @@ -3,6 +3,8 @@ # please review /etc/conf.d/net.example and save your configuration # in /etc/conf.d/net (this file :]!). +modules="!wpa_supplicant" + config_eth0=( "202.117.16.121 netmask 255.255.255.0 brd 202.117.16.255" "192.168.4.121/24" diff --git a/src/settings/plugins/ifnet/tests/test_all.c b/src/settings/plugins/ifnet/tests/test_all.c index 50441d4e..974258b9 100644 --- a/src/settings/plugins/ifnet/tests/test_all.c +++ b/src/settings/plugins/ifnet/tests/test_all.c @@ -56,6 +56,9 @@ test_getdata () && strcmp (ifnet_get_data ("ppp0", "password"), "password") == 0, "get data", "config_ppp0 password is not correctly read"); + ASSERT (ifnet_get_global_data ("modules") + && strcmp ("!wpa_supplicant", ifnet_get_global_data ("modules")) == 0, + "get data", "config_eth1 is not correct"); } static void diff --git a/src/settings/plugins/ifupdown/Makefile.in b/src/settings/plugins/ifupdown/Makefile.in index f5087648..d1414ef0 100644 --- a/src/settings/plugins/ifupdown/Makefile.in +++ b/src/settings/plugins/ifupdown/Makefile.in @@ -47,7 +47,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -244,6 +244,10 @@ 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@ @@ -339,6 +343,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -377,6 +384,8 @@ 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@ diff --git a/src/settings/plugins/ifupdown/tests/Makefile.am b/src/settings/plugins/ifupdown/tests/Makefile.am index ff219d5d..9a9ea1f7 100644 --- a/src/settings/plugins/ifupdown/tests/Makefile.am +++ b/src/settings/plugins/ifupdown/tests/Makefile.am @@ -29,4 +29,5 @@ endif EXTRA_DIST = \ test1 test2 test3 test4 test5 test6 test7 test8 test9 test11 test12 \ - test13 test14 test15 test16 test17-wired-static-verify-ip4 + test13 test14 test15 test16 test17-wired-static-verify-ip4 \ + test18-wired-static-verify-ip6 diff --git a/src/settings/plugins/ifupdown/tests/Makefile.in b/src/settings/plugins/ifupdown/tests/Makefile.in index a03be1bd..68c166c0 100644 --- a/src/settings/plugins/ifupdown/tests/Makefile.in +++ b/src/settings/plugins/ifupdown/tests/Makefile.in @@ -48,7 +48,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -168,6 +168,10 @@ 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@ @@ -263,6 +267,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -301,6 +308,8 @@ 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@ @@ -343,7 +352,8 @@ test_ifupdown_LDADD = \ EXTRA_DIST = \ test1 test2 test3 test4 test5 test6 test7 test8 test9 test11 test12 \ - test13 test14 test15 test16 test17-wired-static-verify-ip4 + test13 test14 test15 test16 test17-wired-static-verify-ip4 \ + test18-wired-static-verify-ip6 all: all-am diff --git a/src/settings/plugins/ifupdown/tests/test18-wired-static-verify-ip6 b/src/settings/plugins/ifupdown/tests/test18-wired-static-verify-ip6 new file mode 100644 index 00000000..29546a61 --- /dev/null +++ b/src/settings/plugins/ifupdown/tests/test18-wired-static-verify-ip6 @@ -0,0 +1,6 @@ +iface myip6tunnel inet6 v4tunnel + address fc00::1 + netmask 64 + endpoint 78.35.24.124 + dns-nameservers fc00::2 fc00::3 + dns-search example.com foo.example.com diff --git a/src/settings/plugins/keyfile/Makefile.in b/src/settings/plugins/keyfile/Makefile.in index c766e794..4b9ec0dd 100644 --- a/src/settings/plugins/keyfile/Makefile.in +++ b/src/settings/plugins/keyfile/Makefile.in @@ -47,7 +47,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -220,6 +220,10 @@ 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@ @@ -315,6 +319,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -353,6 +360,8 @@ 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@ diff --git a/src/settings/plugins/keyfile/reader.c b/src/settings/plugins/keyfile/reader.c index c7889cfc..47392978 100644 --- a/src/settings/plugins/keyfile/reader.c +++ b/src/settings/plugins/keyfile/reader.c @@ -1351,7 +1351,8 @@ nm_keyfile_plugin_connection_from_file (const char *filename, GError **error) /* Verify the connection */ if (!nm_connection_verify (connection, &verify_error)) { g_set_error (error, KEYFILE_PLUGIN_ERROR, 0, - "invalid or missing connection property '%s'", + "invalid or missing connection property '%s/%s'", + verify_error ? g_type_name (nm_connection_lookup_setting_type_by_quark (verify_error->domain)) : "(unknown)", (verify_error && verify_error->message) ? verify_error->message : "(unknown)"); g_clear_error (&verify_error); g_object_unref (connection); diff --git a/src/settings/plugins/keyfile/tests/Makefile.in b/src/settings/plugins/keyfile/tests/Makefile.in index ff08e529..d37f2c61 100644 --- a/src/settings/plugins/keyfile/tests/Makefile.in +++ b/src/settings/plugins/keyfile/tests/Makefile.in @@ -48,7 +48,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -206,6 +206,10 @@ 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@ @@ -301,6 +305,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -339,6 +346,8 @@ 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@ diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in b/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in index cf5b868f..e6cf35ad 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in +++ b/src/settings/plugins/keyfile/tests/keyfiles/Makefile.in @@ -46,7 +46,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -134,6 +134,10 @@ 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@ @@ -229,6 +233,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -267,6 +274,8 @@ 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@ diff --git a/src/settings/tests/Makefile.in b/src/settings/tests/Makefile.in index de5474d4..5fb95d31 100644 --- a/src/settings/tests/Makefile.in +++ b/src/settings/tests/Makefile.in @@ -48,7 +48,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -170,6 +170,10 @@ 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@ @@ -265,6 +269,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -303,6 +310,8 @@ 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@ diff --git a/src/supplicant-manager/Makefile.in b/src/supplicant-manager/Makefile.in index fbb43bde..4bde9543 100644 --- a/src/supplicant-manager/Makefile.in +++ b/src/supplicant-manager/Makefile.in @@ -47,7 +47,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -210,6 +210,10 @@ 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@ @@ -305,6 +309,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -343,6 +350,8 @@ 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@ diff --git a/src/supplicant-manager/nm-supplicant-interface.c b/src/supplicant-manager/nm-supplicant-interface.c index f8ad8f18..cbe7032f 100644 --- a/src/supplicant-manager/nm-supplicant-interface.c +++ b/src/supplicant-manager/nm-supplicant-interface.c @@ -50,6 +50,8 @@ static void wpas_iface_scan_done (DBusGProxy *proxy, gboolean success, gpointer user_data); +static void wpas_iface_get_props (NMSupplicantInterface *self); + #define NM_SUPPLICANT_INTERFACE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ NM_TYPE_SUPPLICANT_INTERFACE, \ NMSupplicantInterfacePrivate)) @@ -85,6 +87,8 @@ typedef struct { gboolean is_wireless; gboolean has_credreq; /* Whether querying 802.1x credentials is supported */ gboolean fast_supported; + guint32 max_scan_ssids; + guint32 ready_count; char * object_path; guint32 state; @@ -100,7 +104,7 @@ typedef struct { guint32 blobs_left; GHashTable * bss_proxies; - guint32 last_scan; + time_t last_scan; NMSupplicantConfig * cfg; @@ -257,6 +261,10 @@ bss_properties_changed (DBusGProxy *proxy, gpointer user_data) { NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + + if (priv->scanning) + priv->last_scan = time (NULL); if (g_strcmp0 (interface, WPAS_DBUS_IFACE_BSS) == 0) g_signal_emit (self, signals[BSS_UPDATED], 0, dbus_g_proxy_get_path (proxy), props); @@ -268,6 +276,10 @@ old_bss_properties_changed (DBusGProxy *proxy, gpointer user_data) { NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + + if (priv->scanning) + priv->last_scan = time (NULL); g_signal_emit (self, signals[BSS_UPDATED], 0, dbus_g_proxy_get_path (proxy), props); } @@ -346,7 +358,13 @@ wpas_iface_bss_added (DBusGProxy *proxy, GHashTable *props, gpointer user_data) { - handle_new_bss (NM_SUPPLICANT_INTERFACE (user_data), object_path, props); + NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + + if (priv->scanning) + priv->last_scan = time (NULL); + + handle_new_bss (self, object_path, props); } static void @@ -365,7 +383,9 @@ wpas_iface_bss_removed (DBusGProxy *proxy, static int wpas_state_string_to_enum (const char *str_state) { - if (!strcmp (str_state, "disconnected")) + if (!strcmp (str_state, "interface_disabled")) + return NM_SUPPLICANT_INTERFACE_STATE_DISABLED; + else if (!strcmp (str_state, "disconnected")) return NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED; else if (!strcmp (str_state, "inactive")) return NM_SUPPLICANT_INTERFACE_STATE_INACTIVE; @@ -406,7 +426,12 @@ set_state (NMSupplicantInterface *self, guint32 new_state) if (priv->state >= NM_SUPPLICANT_INTERFACE_STATE_READY) g_return_if_fail (new_state > NM_SUPPLICANT_INTERFACE_STATE_READY); - if (new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) { + if (new_state == NM_SUPPLICANT_INTERFACE_STATE_READY) { + /* Get properties again to update to the actual wpa_supplicant + * interface state. + */ + wpas_iface_get_props (self); + } else if (new_state == NM_SUPPLICANT_INTERFACE_STATE_DOWN) { /* Cancel all pending calls when going down */ cancel_all_callbacks (priv->other_pcalls); cancel_all_callbacks (priv->assoc_pcalls); @@ -438,6 +463,11 @@ set_state (NMSupplicantInterface *self, guint32 new_state) } priv->state = new_state; + + if ( priv->state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING + || old_state == NM_SUPPLICANT_INTERFACE_STATE_SCANNING) + priv->last_scan = time (NULL); + g_signal_emit (self, signals[STATE], 0, priv->state, old_state); } @@ -456,16 +486,13 @@ static void set_scanning (NMSupplicantInterface *self, gboolean new_scanning) { NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - GTimeVal cur_time; if (priv->scanning != new_scanning) { priv->scanning = new_scanning; /* Cache time of last scan completion */ - if (priv->scanning == FALSE) { - g_get_current_time (&cur_time); - priv->last_scan = cur_time.tv_sec; - } + if (priv->scanning == FALSE) + priv->last_scan = time (NULL); g_object_notify (G_OBJECT (self), "scanning"); } @@ -486,6 +513,12 @@ nm_supplicant_interface_get_scanning (NMSupplicantInterface *self) return FALSE; } +time_t +nm_supplicant_interface_get_last_scan_time (NMSupplicantInterface *self) +{ + return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->last_scan; +} + static void wpas_iface_scan_done (DBusGProxy *proxy, gboolean success, @@ -493,21 +526,57 @@ wpas_iface_scan_done (DBusGProxy *proxy, { NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); - GTimeVal cur_time; /* Cache last scan completed time */ - g_get_current_time (&cur_time); - priv->last_scan = cur_time.tv_sec; - + priv->last_scan = time (NULL); g_signal_emit (self, signals[SCAN_DONE], 0, success); } static void +parse_capabilities (NMSupplicantInterface *self, GHashTable *props) +{ + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + GValue *value; + gboolean have_active = FALSE, have_ssid = FALSE; + + g_return_if_fail (props != NULL); + + value = g_hash_table_lookup (props, "Scan"); + if (value && G_VALUE_HOLDS (value, G_TYPE_STRV)) { + const char **vals = g_value_get_boxed (value); + const char **iter = vals; + + while (iter && *iter && (!have_active || !have_ssid)) { + if (g_strcmp0 (*iter, "active") == 0) + have_active = TRUE; + else if (g_strcmp0 (*iter, "ssid") == 0) + have_ssid = TRUE; + iter++; + } + } + + value = g_hash_table_lookup (props, "MaxScanSSID"); + if (value && G_VALUE_HOLDS (value, G_TYPE_INT)) { + /* We need active scan and SSID probe capabilities to care about MaxScanSSIDs */ + if (have_active && have_ssid) { + /* wpa_supplicant's WPAS_MAX_SCAN_SSIDS value is 16, but for speed + * and to ensure we don't disclose too many SSIDs from the hidden + * list, we'll limit to 5. + */ + priv->max_scan_ssids = CLAMP (g_value_get_int (value), 0, 5); + nm_log_info (LOGD_SUPPLICANT, "(%s) supports %d scan SSIDs", + priv->dev, priv->max_scan_ssids); + } + } +} + +static void wpas_iface_properties_changed (DBusGProxy *proxy, GHashTable *props, gpointer user_data) { NMSupplicantInterface *self = NM_SUPPLICANT_INTERFACE (user_data); + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); GValue *value; value = g_hash_table_lookup (props, "Scanning"); @@ -515,8 +584,16 @@ wpas_iface_properties_changed (DBusGProxy *proxy, set_scanning (self, g_value_get_boolean (value)); value = g_hash_table_lookup (props, "State"); - if (value && G_VALUE_HOLDS_STRING (value)) - set_state_from_string (self, g_value_get_string (value)); + if (value && G_VALUE_HOLDS_STRING (value)) { + if (priv->state >= NM_SUPPLICANT_INTERFACE_STATE_READY) { + /* Only transition to actual wpa_supplicant interface states (ie, + * anything > READY) after the NMSupplicantInterface has had a + * chance to initialize, which is signalled by entering the READY + * state. + */ + set_state_from_string (self, g_value_get_string (value)); + } + } value = g_hash_table_lookup (props, "BSSs"); if (value && G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH)) { @@ -526,6 +603,22 @@ wpas_iface_properties_changed (DBusGProxy *proxy, for (i = 0; paths && (i < paths->len); i++) handle_new_bss (self, g_ptr_array_index (paths, i), NULL); } + + value = g_hash_table_lookup (props, "Capabilities"); + if (value && G_VALUE_HOLDS (value, DBUS_TYPE_G_MAP_OF_VARIANT)) + parse_capabilities (self, g_value_get_boxed (value)); +} + +static void +iface_check_ready (NMSupplicantInterface *self) +{ + NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self); + + if (priv->ready_count && priv->state < NM_SUPPLICANT_INTERFACE_STATE_READY) { + priv->ready_count--; + if (priv->ready_count == 0) + set_state (self, NM_SUPPLICANT_INTERFACE_STATE_READY); + } } static void @@ -545,6 +638,7 @@ iface_get_props_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer user_da error && error->message ? error->message : "(unknown)"); g_clear_error (&error); } + iface_check_ready (info->interface); } static void @@ -629,6 +723,8 @@ iface_check_netreply_cb (DBusGProxy *proxy, DBusGProxyCall *call_id, gpointer us priv->has_credreq ? "supports" : "does not support"); } g_clear_error (&error); + + iface_check_ready (info->interface); } static void @@ -721,13 +817,10 @@ interface_add_done (NMSupplicantInterface *self, char *path) WPAS_DBUS_SERVICE, path, DBUS_INTERFACE_PROPERTIES); - /* Get initial properties */ + /* Get initial properties and check whether NetworkReply is supported */ wpas_iface_get_props (self); - - /* Check whether NetworkReply is supported */ wpas_iface_check_network_reply (self); - - set_state (self, NM_SUPPLICANT_INTERFACE_STATE_READY); + priv->ready_count = 2; } static void @@ -1159,8 +1252,18 @@ string_to_gvalue (const char *str) return val; } +static GValue * +byte_array_array_to_gvalue (const GPtrArray *array) +{ + GValue *val = g_slice_new0 (GValue); + + g_value_init (val, DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UCHAR); + g_value_set_boxed (val, array); + return val; +} + gboolean -nm_supplicant_interface_request_scan (NMSupplicantInterface * self) +nm_supplicant_interface_request_scan (NMSupplicantInterface *self, const GPtrArray *ssids) { NMSupplicantInterfacePrivate *priv; NMSupplicantInfo *info; @@ -1174,6 +1277,8 @@ nm_supplicant_interface_request_scan (NMSupplicantInterface * self) /* Scan parameters */ hash = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, destroy_gvalue); g_hash_table_insert (hash, "Type", string_to_gvalue ("active")); + if (ssids) + g_hash_table_insert (hash, "SSIDs", byte_array_array_to_gvalue (ssids)); info = nm_supplicant_info_new (self, priv->iface_proxy, priv->other_pcalls); call = dbus_g_proxy_begin_call (priv->iface_proxy, "Scan", @@ -1206,6 +1311,8 @@ nm_supplicant_interface_state_to_string (guint32 state) return "starting"; case NM_SUPPLICANT_INTERFACE_STATE_READY: return "ready"; + case NM_SUPPLICANT_INTERFACE_STATE_DISABLED: + return "disabled"; case NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED: return "disconnected"; case NM_SUPPLICANT_INTERFACE_STATE_INACTIVE: @@ -1259,6 +1366,15 @@ nm_supplicant_interface_get_ifname (NMSupplicantInterface *self) return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->dev; } +guint +nm_supplicant_interface_get_max_scan_ssids (NMSupplicantInterface *self) +{ + g_return_val_if_fail (self != NULL, 0); + g_return_val_if_fail (NM_IS_SUPPLICANT_INTERFACE (self), 0); + + return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->max_scan_ssids; +} + /*******************************************************************/ NMSupplicantInterface * diff --git a/src/supplicant-manager/nm-supplicant-interface.h b/src/supplicant-manager/nm-supplicant-interface.h index 608ee059..b99c0f26 100644 --- a/src/supplicant-manager/nm-supplicant-interface.h +++ b/src/supplicant-manager/nm-supplicant-interface.h @@ -34,6 +34,7 @@ enum { NM_SUPPLICANT_INTERFACE_STATE_INIT = 0, NM_SUPPLICANT_INTERFACE_STATE_STARTING, NM_SUPPLICANT_INTERFACE_STATE_READY, + NM_SUPPLICANT_INTERFACE_STATE_DISABLED, NM_SUPPLICANT_INTERFACE_STATE_DISCONNECTED, NM_SUPPLICANT_INTERFACE_STATE_INACTIVE, NM_SUPPLICANT_INTERFACE_STATE_SCANNING, @@ -127,7 +128,7 @@ const char * nm_supplicant_interface_get_device (NMSupplicantInterface * iface); const char *nm_supplicant_interface_get_object_path (NMSupplicantInterface * iface); -gboolean nm_supplicant_interface_request_scan (NMSupplicantInterface * self); +gboolean nm_supplicant_interface_request_scan (NMSupplicantInterface * self, const GPtrArray *ssids); guint32 nm_supplicant_interface_get_state (NMSupplicantInterface * self); @@ -135,8 +136,12 @@ const char *nm_supplicant_interface_state_to_string (guint32 state); gboolean nm_supplicant_interface_get_scanning (NMSupplicantInterface *self); +time_t nm_supplicant_interface_get_last_scan_time (NMSupplicantInterface *self); + const char *nm_supplicant_interface_get_ifname (NMSupplicantInterface *self); +guint nm_supplicant_interface_get_max_scan_ssids (NMSupplicantInterface *self); + gboolean nm_supplicant_interface_get_has_credentials_request (NMSupplicantInterface *self); gboolean nm_supplicant_interface_credentials_reply (NMSupplicantInterface *self, diff --git a/src/supplicant-manager/tests/Makefile.in b/src/supplicant-manager/tests/Makefile.in index 65be2b39..c649a3ab 100644 --- a/src/supplicant-manager/tests/Makefile.in +++ b/src/supplicant-manager/tests/Makefile.in @@ -48,7 +48,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -170,6 +170,10 @@ 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@ @@ -265,6 +269,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -303,6 +310,8 @@ 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@ diff --git a/src/tests/Makefile.in b/src/tests/Makefile.in index 7d367415..3cc387ca 100644 --- a/src/tests/Makefile.in +++ b/src/tests/Makefile.in @@ -49,7 +49,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -187,6 +187,10 @@ 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@ @@ -282,6 +286,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -320,6 +327,8 @@ 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@ diff --git a/src/vpn-manager/Makefile.am b/src/vpn-manager/Makefile.am index c3c5b525..12e316d8 100644 --- a/src/vpn-manager/Makefile.am +++ b/src/vpn-manager/Makefile.am @@ -7,6 +7,7 @@ INCLUDES = \ -I${top_srcdir}/src/generated \ -I${top_builddir}/src/generated \ -I${top_srcdir}/src/logging \ + -I${top_srcdir}/src/posix-signals \ -I${top_srcdir}/src \ -I${top_srcdir}/src/dns-manager \ -DVPN_NAME_FILES_DIR=\""$(sysconfdir)/NetworkManager/VPN"\" @@ -31,6 +32,7 @@ libvpn_manager_la_CPPFLAGS = \ libvpn_manager_la_LIBADD = \ $(top_builddir)/src/generated/libnm-generated.la \ $(top_builddir)/src/logging/libnm-logging.la \ + $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ $(top_builddir)/libnm-util/libnm-util.la \ $(LIBNL_LIBS) \ $(DBUS_LIBS) \ diff --git a/src/vpn-manager/Makefile.in b/src/vpn-manager/Makefile.in index 9a7e5e42..64a9c8c3 100644 --- a/src/vpn-manager/Makefile.in +++ b/src/vpn-manager/Makefile.in @@ -47,7 +47,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -59,6 +59,7 @@ am__DEPENDENCIES_1 = libvpn_manager_la_DEPENDENCIES = \ $(top_builddir)/src/generated/libnm-generated.la \ $(top_builddir)/src/logging/libnm-logging.la \ + $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ $(top_builddir)/libnm-util/libnm-util.la $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libvpn_manager_la_OBJECTS = libvpn_manager_la-nm-vpn-manager.lo \ @@ -171,6 +172,10 @@ 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@ @@ -266,6 +271,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -304,6 +312,8 @@ 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@ @@ -333,6 +343,7 @@ INCLUDES = \ -I${top_srcdir}/src/generated \ -I${top_builddir}/src/generated \ -I${top_srcdir}/src/logging \ + -I${top_srcdir}/src/posix-signals \ -I${top_srcdir}/src \ -I${top_srcdir}/src/dns-manager \ -DVPN_NAME_FILES_DIR=\""$(sysconfdir)/NetworkManager/VPN"\" @@ -355,6 +366,7 @@ libvpn_manager_la_CPPFLAGS = \ libvpn_manager_la_LIBADD = \ $(top_builddir)/src/generated/libnm-generated.la \ $(top_builddir)/src/logging/libnm-logging.la \ + $(top_builddir)/src/posix-signals/libnm-posix-signals.la \ $(top_builddir)/libnm-util/libnm-util.la \ $(LIBNL_LIBS) \ $(DBUS_LIBS) \ diff --git a/src/vpn-manager/nm-vpn-connection.c b/src/vpn-manager/nm-vpn-connection.c index b391f1ec..5f64153b 100644 --- a/src/vpn-manager/nm-vpn-connection.c +++ b/src/vpn-manager/nm-vpn-connection.c @@ -43,7 +43,6 @@ #include "nm-properties-changed-signal.h" #include "nm-dbus-glib-types.h" #include "NetworkManagerUtils.h" -#include "nm-dns-manager.h" #include "nm-netlink-monitor.h" #include "nm-netlink-utils.h" #include "nm-glib-compat.h" @@ -78,16 +77,24 @@ typedef struct { NMDevice *parent_dev; gulong device_monitor; gulong device_ip4; + gulong device_ip6; NMVPNConnectionState vpn_state; NMVPNConnectionStateReason failure_reason; DBusGProxy *proxy; guint ipconfig_timeout; + gboolean has_ip4; NMIP4Config *ip4_config; guint32 ip4_internal_gw; + guint32 ip4_external_gw; + gboolean has_ip6; + NMIP6Config *ip6_config; + struct in6_addr *ip6_internal_gw; + struct in6_addr *ip6_external_gw; char *ip_iface; int ip_ifindex; char *banner; + guint32 mtu; struct rtnl_route *gw_route; } NMVPNConnectionPrivate; @@ -133,13 +140,61 @@ ac_state_from_vpn_state (NMVPNConnectionState vpn_state) } static void +call_plugin_disconnect (NMVPNConnection *self) +{ + NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self); + GError *error = NULL; + + if (priv->proxy) { + org_freedesktop_NetworkManager_VPN_Plugin_disconnect (priv->proxy, &error); + if (error) + nm_log_warn (LOGD_VPN, "error disconnecting VPN: %s", error->message); + g_clear_error (&error); + + g_object_unref (priv->proxy); + priv->proxy = NULL; + } +} + +static void +vpn_cleanup (NMVPNConnection *connection) +{ + NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); + + if (priv->ip_ifindex) { + nm_system_iface_set_up (priv->ip_ifindex, FALSE, NULL); + /* FIXME: use AF_UNSPEC here when we have IPv6 support */ + nm_system_iface_flush_routes (priv->ip_ifindex, AF_INET); + nm_system_iface_flush_addresses (priv->ip_ifindex, AF_UNSPEC); + } + + if (priv->gw_route) { + nm_netlink_route_delete (priv->gw_route); + rtnl_route_put (priv->gw_route); + priv->gw_route = NULL; + } + + g_free (priv->banner); + priv->banner = NULL; + + g_free (priv->ip_iface); + priv->ip_iface = NULL; + priv->ip_ifindex = 0; + + /* Clear out connection secrets to ensure that the settings service + * gets asked for them next time the connection is activated. + */ + if (priv->connection) + nm_connection_clear_secrets (priv->connection); +} + +static void nm_vpn_connection_set_vpn_state (NMVPNConnection *connection, NMVPNConnectionState vpn_state, NMVPNConnectionStateReason reason) { NMVPNConnectionPrivate *priv; NMVPNConnectionState old_vpn_state; - char *ip_iface; g_return_if_fail (NM_IS_VPN_CONNECTION (connection)); @@ -155,10 +210,12 @@ nm_vpn_connection_set_vpn_state (NMVPNConnection *connection, nm_active_connection_set_state (NM_ACTIVE_CONNECTION (connection), ac_state_from_vpn_state (vpn_state)); - /* Save ip_iface since when the VPN goes down it may get freed - * before we're done with it. - */ - ip_iface = g_strdup (priv->ip_iface); + /* Clear any in-progress secrets request */ + if (priv->secrets_id) { + nm_settings_connection_cancel_secrets (NM_SETTINGS_CONNECTION (priv->connection), priv->secrets_id); + priv->secrets_id = 0; + } + priv->secrets_idx = SECRETS_REQ_SYSTEM; /* The connection gets destroyed by the VPN manager when it enters the * disconnected/failed state, but we need to keep it around for a bit @@ -166,35 +223,50 @@ nm_vpn_connection_set_vpn_state (NMVPNConnection *connection, */ g_object_ref (connection); - g_signal_emit (connection, signals[VPN_STATE_CHANGED], 0, vpn_state, reason); + g_signal_emit (connection, signals[VPN_STATE_CHANGED], 0, vpn_state, old_vpn_state, reason); g_object_notify (G_OBJECT (connection), NM_VPN_CONNECTION_VPN_STATE); - /* Call dispatcher after the event gets processed internally */ switch (vpn_state) { + case NM_VPN_CONNECTION_STATE_NEED_AUTH: + /* Kick off the secrets requests; first we get existing system secrets + * and ask the plugin if these are sufficient, next we get all existing + * secrets from system and from user agents and ask the plugin again, + * and last we ask the user for new secrets if required. + */ + get_secrets (connection, SECRETS_REQ_SYSTEM); + break; case NM_VPN_CONNECTION_STATE_ACTIVATED: + /* Secrets no longer needed now that we're connected */ + nm_connection_clear_secrets (priv->connection); + + /* Let dispatcher scripts know we're up and running */ nm_utils_call_dispatcher ("vpn-up", priv->connection, priv->parent_dev, - ip_iface, + priv->ip_iface, priv->ip4_config, - NULL); + priv->ip6_config); break; case NM_VPN_CONNECTION_STATE_FAILED: case NM_VPN_CONNECTION_STATE_DISCONNECTED: if (old_vpn_state == NM_VPN_CONNECTION_STATE_ACTIVATED) { + /* Let dispatcher scripts know we're about to go down */ nm_utils_call_dispatcher ("vpn-down", priv->connection, priv->parent_dev, - ip_iface, + priv->ip_iface, NULL, NULL); } + + /* Tear down and clean up the connection */ + call_plugin_disconnect (connection); + vpn_cleanup (connection); break; default: break; } - g_free (ip_iface); g_object_unref (connection); } @@ -230,11 +302,34 @@ device_ip4_config_changed (NMDevice *device, || !nm_device_get_ip4_config (device)) return; - if (priv->gw_route) - rtnl_route_put (priv->gw_route); + /* Re-add the VPN gateway route */ + if (priv->ip4_external_gw) { + if (priv->gw_route) + rtnl_route_put (priv->gw_route); + priv->gw_route = nm_system_add_ip4_vpn_gateway_route (priv->parent_dev, + priv->ip4_external_gw); + } +} + +static void +device_ip6_config_changed (NMDevice *device, + GParamSpec *pspec, + gpointer user_data) +{ + NMVPNConnection *vpn = NM_VPN_CONNECTION (user_data); + NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (vpn); + + if ( (priv->vpn_state != NM_VPN_CONNECTION_STATE_ACTIVATED) + || !nm_device_get_ip6_config (device)) + return; /* Re-add the VPN gateway route */ - priv->gw_route = nm_system_add_ip4_vpn_gateway_route (priv->parent_dev, priv->ip4_config); + if (priv->ip6_external_gw) { + if (priv->gw_route) + rtnl_route_put (priv->gw_route); + priv->gw_route = nm_system_add_ip6_vpn_gateway_route (priv->parent_dev, + priv->ip6_external_gw); + } } NMVPNConnection * @@ -271,6 +366,9 @@ nm_vpn_connection_new (NMConnection *connection, priv->device_ip4 = g_signal_connect (parent_device, "notify::" NM_DEVICE_IP4_CONFIG, G_CALLBACK (device_ip4_config_changed), self); + priv->device_ip6 = g_signal_connect (parent_device, "notify::" NM_DEVICE_IP6_CONFIG, + G_CALLBACK (device_ip6_config_changed), + self); if (!nm_active_connection_export (NM_ACTIVE_CONNECTION (self), connection, @@ -372,17 +470,18 @@ plugin_state_changed (DBusGProxy *proxy, } } +static char addr_to_string_buf[INET6_ADDRSTRLEN + 1]; + static const char * ip_address_to_string (guint32 numeric) { struct in_addr temp_addr; - static char buf[INET_ADDRSTRLEN + 1]; - memset (&buf, '\0', sizeof (buf)); + memset (&addr_to_string_buf, '\0', sizeof (addr_to_string_buf)); temp_addr.s_addr = numeric; - if (inet_ntop (AF_INET, &temp_addr, buf, INET_ADDRSTRLEN)) { - return buf; + if (inet_ntop (AF_INET, &temp_addr, addr_to_string_buf, INET_ADDRSTRLEN)) { + return addr_to_string_buf; } else { nm_log_warn (LOGD_VPN, "error converting IP4 address 0x%X", ntohl (temp_addr.s_addr)); @@ -390,115 +489,340 @@ ip_address_to_string (guint32 numeric) } } +static const char * +ip6_address_to_string (const struct in6_addr *addr) +{ + memset (addr_to_string_buf, '\0', sizeof (addr_to_string_buf)); + if (inet_ntop (AF_INET6, addr, addr_to_string_buf, INET6_ADDRSTRLEN)) { + return addr_to_string_buf; + } else { + nm_log_warn (LOGD_VPN, "error converting IP6 address"); + return NULL; + } +} + static void -print_vpn_config (NMIP4Config *config, - guint32 internal_gw, - const char *ip_iface, - const char *banner) +print_vpn_config (NMVPNConnection *connection) { + NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); NMIP4Address *addr; + NMIP6Address *addr6; char *dns_domain = NULL; guint32 num, i; - g_return_if_fail (config != NULL); - - addr = nm_ip4_config_get_address (config, 0); - - nm_log_info (LOGD_VPN, "VPN Gateway: %s", ip_address_to_string (nm_ip4_address_get_gateway (addr))); - if (internal_gw) - nm_log_info (LOGD_VPN, "Internal Gateway: %s", ip_address_to_string (internal_gw)); - nm_log_info (LOGD_VPN, "Tunnel Device: %s", ip_iface); - nm_log_info (LOGD_VPN, "Internal IP4 Address: %s", ip_address_to_string (nm_ip4_address_get_address (addr))); - nm_log_info (LOGD_VPN, "Internal IP4 Prefix: %d", nm_ip4_address_get_prefix (addr)); - nm_log_info (LOGD_VPN, "Internal IP4 Point-to-Point Address: %s", - ip_address_to_string (nm_ip4_config_get_ptp_address (config))); - nm_log_info (LOGD_VPN, "Maximum Segment Size (MSS): %d", nm_ip4_config_get_mss (config)); - - num = nm_ip4_config_get_num_routes (config); - for (i = 0; i < num; i++) { - NMIP4Route *route; - - route = nm_ip4_config_get_route (config, i); - nm_log_info (LOGD_VPN, "Static Route: %s/%d Next Hop: %s", - ip_address_to_string (nm_ip4_route_get_dest (route)), - nm_ip4_route_get_prefix (route), - ip_address_to_string (nm_ip4_route_get_next_hop (route))); - } + if (priv->ip4_external_gw) { + nm_log_info (LOGD_VPN, "VPN Gateway: %s", + ip_address_to_string (priv->ip4_external_gw)); + } else if (priv->ip6_external_gw) { + nm_log_info (LOGD_VPN, "VPN Gateway: %s", + ip6_address_to_string (priv->ip6_external_gw)); + } - nm_log_info (LOGD_VPN, "Forbid Default Route: %s", - nm_ip4_config_get_never_default (config) ? "yes" : "no"); + nm_log_info (LOGD_VPN, "Tunnel Device: %s", priv->ip_iface); - num = nm_ip4_config_get_num_nameservers (config); - for (i = 0; i < num; i++) { - nm_log_info (LOGD_VPN, "Internal IP4 DNS: %s", - ip_address_to_string (nm_ip4_config_get_nameserver (config, i))); - } + if (priv->ip4_config) { + nm_log_info (LOGD_VPN, "IPv4 configuration:"); + + addr = nm_ip4_config_get_address (priv->ip4_config, 0); + + if (priv->ip4_internal_gw) + nm_log_info (LOGD_VPN, " Internal Gateway: %s", ip_address_to_string (priv->ip4_internal_gw)); + nm_log_info (LOGD_VPN, " Internal Address: %s", ip_address_to_string (nm_ip4_address_get_address (addr))); + nm_log_info (LOGD_VPN, " Internal Prefix: %d", nm_ip4_address_get_prefix (addr)); + nm_log_info (LOGD_VPN, " Internal Point-to-Point Address: %s", + ip_address_to_string (nm_ip4_config_get_ptp_address (priv->ip4_config))); + nm_log_info (LOGD_VPN, " Maximum Segment Size (MSS): %d", nm_ip4_config_get_mss (priv->ip4_config)); + + num = nm_ip4_config_get_num_routes (priv->ip4_config); + for (i = 0; i < num; i++) { + NMIP4Route *route; + + route = nm_ip4_config_get_route (priv->ip4_config, i); + nm_log_info (LOGD_VPN, " Static Route: %s/%d Next Hop: %s", + ip_address_to_string (nm_ip4_route_get_dest (route)), + nm_ip4_route_get_prefix (route), + ip_address_to_string (nm_ip4_route_get_next_hop (route))); + } + + nm_log_info (LOGD_VPN, " Forbid Default Route: %s", + nm_ip4_config_get_never_default (priv->ip4_config) ? "yes" : "no"); + + num = nm_ip4_config_get_num_nameservers (priv->ip4_config); + for (i = 0; i < num; i++) { + nm_log_info (LOGD_VPN, " Internal DNS: %s", + ip_address_to_string (nm_ip4_config_get_nameserver (priv->ip4_config, i))); + } + + if (nm_ip4_config_get_num_domains (priv->ip4_config) > 0) + dns_domain = (char *) nm_ip4_config_get_domain (priv->ip4_config, 0); + + nm_log_info (LOGD_VPN, " DNS Domain: '%s'", dns_domain ? dns_domain : "(none)"); + } else + nm_log_info (LOGD_VPN, "No IPv4 configuration"); + + if (priv->ip6_config) { + nm_log_info (LOGD_VPN, "IPv6 configuration:"); + + addr6 = nm_ip6_config_get_address (priv->ip6_config, 0); + + if (priv->ip6_internal_gw) + nm_log_info (LOGD_VPN, " Internal Gateway: %s", ip6_address_to_string (priv->ip6_internal_gw)); + nm_log_info (LOGD_VPN, " Internal Address: %s", ip6_address_to_string (nm_ip6_address_get_address (addr6))); + nm_log_info (LOGD_VPN, " Internal Prefix: %d", nm_ip6_address_get_prefix (addr6)); + nm_log_info (LOGD_VPN, " Internal Point-to-Point Address: %s", + ip6_address_to_string (nm_ip6_config_get_ptp_address (priv->ip6_config))); + nm_log_info (LOGD_VPN, " Maximum Segment Size (MSS): %d", nm_ip6_config_get_mss (priv->ip6_config)); - if (nm_ip4_config_get_num_domains (config) > 0) - dns_domain = (char *) nm_ip4_config_get_domain (config, 0); + num = nm_ip6_config_get_num_routes (priv->ip6_config); + for (i = 0; i < num; i++) { + NMIP6Route *route; - nm_log_info (LOGD_VPN, "DNS Domain: '%s'", dns_domain ? dns_domain : "(none)"); + route = nm_ip6_config_get_route (priv->ip6_config, i); + nm_log_info (LOGD_VPN, " Static Route: %s/%d Next Hop: %s", + ip6_address_to_string (nm_ip6_route_get_dest (route)), + nm_ip6_route_get_prefix (route), + ip6_address_to_string (nm_ip6_route_get_next_hop (route))); + } + + nm_log_info (LOGD_VPN, " Forbid Default Route: %s", + nm_ip6_config_get_never_default (priv->ip6_config) ? "yes" : "no"); + + num = nm_ip6_config_get_num_nameservers (priv->ip6_config); + for (i = 0; i < num; i++) { + nm_log_info (LOGD_VPN, " Internal DNS: %s", + ip6_address_to_string (nm_ip6_config_get_nameserver (priv->ip6_config, i))); + } - if (banner && strlen (banner)) { + if (nm_ip6_config_get_num_domains (priv->ip6_config) > 0) + dns_domain = (char *) nm_ip6_config_get_domain (priv->ip6_config, 0); + + nm_log_info (LOGD_VPN, " DNS Domain: '%s'", dns_domain ? dns_domain : "(none)"); + } else + nm_log_info (LOGD_VPN, "No IPv6 configuration"); + + if (priv->banner && strlen (priv->banner)) { nm_log_info (LOGD_VPN, "Login Banner:"); nm_log_info (LOGD_VPN, "-----------------------------------------"); - nm_log_info (LOGD_VPN, "%s", banner); + nm_log_info (LOGD_VPN, "%s", priv->banner); nm_log_info (LOGD_VPN, "-----------------------------------------"); } } -static void -nm_vpn_connection_ip4_config_get (DBusGProxy *proxy, - GHashTable *config_hash, - gpointer user_data) +static gboolean +nm_vpn_connection_apply_config (NMVPNConnection *connection) { - NMVPNConnection *connection = NM_VPN_CONNECTION (user_data); NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); - NMSettingIP4Config *s_ip4; - NMIP4Address *addr; - NMIP4Config *config; - GValue *val; - int i; - guint32 vpn_ext_gw = 0; - nm_log_info (LOGD_VPN, "VPN connection '%s' (IP Config Get) reply received.", + nm_system_iface_set_up (priv->ip_ifindex, TRUE, NULL); + + if (priv->ip4_config) { + if (!nm_system_apply_ip4_config (priv->ip_ifindex, priv->ip4_config, + 0, NM_IP4_COMPARE_FLAG_ALL)) + return FALSE; + } + + if (priv->ip6_config) { + if (!nm_system_apply_ip6_config (priv->ip_ifindex, priv->ip6_config, + 0, NM_IP6_COMPARE_FLAG_ALL)) + /* FIXME: remove ip4 config */ + return FALSE; + } + + /* Add any explicit route to the VPN gateway through the parent device */ + if (priv->ip4_external_gw) { + priv->gw_route = nm_system_add_ip4_vpn_gateway_route (priv->parent_dev, + priv->ip4_external_gw); + } else if (priv->ip6_external_gw) { + priv->gw_route = nm_system_add_ip6_vpn_gateway_route (priv->parent_dev, + priv->ip6_external_gw); + } else { + priv->gw_route = NULL; + } + + nm_log_info (LOGD_VPN, "VPN connection '%s' (IP Config Get) complete.", nm_vpn_connection_get_name (connection)); + nm_vpn_connection_set_vpn_state (connection, + NM_VPN_CONNECTION_STATE_ACTIVATED, + NM_VPN_CONNECTION_STATE_REASON_NONE); + return TRUE; +} + +static void +nm_vpn_connection_config_maybe_complete (NMVPNConnection *connection, + gboolean success) +{ + NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); + + if (priv->ipconfig_timeout == 0) { + /* config_complete() was already called with an error; + * ignore further calls. + */ + return; + } + + if (success) { + if ( (priv->has_ip4 && !priv->ip4_config) + || (priv->has_ip6 && !priv->ip6_config)) { + /* Need to wait for other config */ + return; + } + } g_source_remove (priv->ipconfig_timeout); priv->ipconfig_timeout = 0; - config = nm_ip4_config_new (); + if (success) { + print_vpn_config (connection); + + if (nm_vpn_connection_apply_config (connection)) + return; + } + + g_clear_object (&priv->ip4_config); + g_clear_object (&priv->ip6_config); - val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_TUNDEV); + nm_log_warn (LOGD_VPN, "VPN connection '%s' did not receive valid IP config information.", + nm_vpn_connection_get_name (connection)); + nm_vpn_connection_set_vpn_state (connection, + NM_VPN_CONNECTION_STATE_FAILED, + NM_VPN_CONNECTION_STATE_REASON_IP_CONFIG_INVALID); +} + +static gboolean +process_generic_config (NMVPNConnection *connection, + GHashTable *config_hash) +{ + NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); + GValue *val; + + val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_CONFIG_TUNDEV); if (val) priv->ip_iface = g_strdup (g_value_get_string (val)); else { nm_log_err (LOGD_VPN, "invalid or missing tunnel device received!"); - goto error; + nm_vpn_connection_config_maybe_complete (connection, FALSE); + return FALSE; } /* Grab the interface index for address/routing operations */ priv->ip_ifindex = nm_netlink_iface_to_index (priv->ip_iface); if (priv->ip_ifindex < 0) { nm_log_err (LOGD_VPN, "(%s): failed to look up VPN interface index", priv->ip_iface); - goto error; + nm_vpn_connection_config_maybe_complete (connection, FALSE); + return FALSE; + } + + val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_CONFIG_BANNER); + if (val) { + g_free (priv->banner); + priv->banner = g_strdup (g_value_get_string (val)); + } + + /* External world-visible address of the VPN server */ + priv->ip4_external_gw = 0; + priv->ip6_external_gw = NULL; + val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY); + if (val) { + if (G_VALUE_HOLDS (val, G_TYPE_UINT)) { + priv->ip4_external_gw = g_value_get_uint (val); + } else if (G_VALUE_HOLDS (val, DBUS_TYPE_G_UCHAR_ARRAY)) { + GByteArray *ba = g_value_get_boxed (val); + + if (ba->len == sizeof (struct in6_addr)) + priv->ip6_external_gw = g_memdup (ba->data, ba->len); + } else { + nm_log_err (LOGD_VPN, "(%s): VPN gateway is neither IPv4 nor IPv6", priv->ip_iface); + nm_vpn_connection_config_maybe_complete (connection, FALSE); + return FALSE; + } + } + + /* MTU; this is a per-connection value, though NM's API treats it + * like it's IP4-specific. So we store it for now and retrieve it + * later in ip4_config_get. + */ + val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_CONFIG_MTU); + if (val) + priv->mtu = g_value_get_uint (val); + else + priv->mtu = 0; + + return TRUE; +} + +static void +nm_vpn_connection_config_get (DBusGProxy *proxy, + GHashTable *config_hash, + gpointer user_data) +{ + NMVPNConnection *connection = NM_VPN_CONNECTION (user_data); + NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); + GValue *val; + + nm_log_info (LOGD_VPN, "VPN connection '%s' (IP Config Get) reply received.", + nm_vpn_connection_get_name (connection)); + + if (!process_generic_config (connection, config_hash)) + return; + + /* Note whether to expect IPv4 and IPv6 configs */ + val = g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_CONFIG_HAS_IP4); + priv->has_ip4 = val ? g_value_get_boolean (val) : FALSE; + g_clear_object (&priv->ip4_config); + + val = g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_CONFIG_HAS_IP6); + priv->has_ip6 = val ? g_value_get_boolean (val) : FALSE; + g_clear_object (&priv->ip6_config); +} + +static void +nm_vpn_connection_ip4_config_get (DBusGProxy *proxy, + GHashTable *config_hash, + gpointer user_data) +{ + NMVPNConnection *connection = NM_VPN_CONNECTION (user_data); + NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); + NMSettingIP4Config *s_ip4; + NMIP4Address *addr; + NMIP4Config *config; + GValue *val; + int i; + + if (priv->has_ip4) { + nm_log_info (LOGD_VPN, "VPN connection '%s' (IP4 Config Get) reply received.", + nm_vpn_connection_get_name (connection)); + + if (g_hash_table_size (config_hash) == 0) { + priv->has_ip4 = FALSE; + nm_vpn_connection_config_maybe_complete (connection, TRUE); + return; + } + } else { + nm_log_info (LOGD_VPN, "VPN connection '%s' (IP4 Config Get) reply received from old-style plugin.", + nm_vpn_connection_get_name (connection)); + + /* In the old API, the generic and IPv4 configuration items + * were mixed together. + */ + if (!process_generic_config (connection, config_hash)) + return; + + priv->has_ip4 = TRUE; + priv->has_ip6 = FALSE; } + config = nm_ip4_config_new (); + addr = nm_ip4_address_new (); nm_ip4_address_set_prefix (addr, 24); /* default to class C */ + if (priv->ip4_external_gw) + nm_ip4_address_set_gateway (addr, priv->ip4_external_gw); /* Internal address of the VPN subnet's gateway */ val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_INT_GATEWAY); if (val) priv->ip4_internal_gw = g_value_get_uint (val); - /* External world-visible address of the VPN server */ - val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_EXT_GATEWAY); - if (val) { - nm_ip4_address_set_gateway (addr, g_value_get_uint (val)); - vpn_ext_gw = g_value_get_uint (val); - } - val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS); if (val) nm_ip4_address_set_address (addr, g_value_get_uint (val)); @@ -516,7 +840,9 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy, } else { nm_log_err (LOGD_VPN, "invalid IP4 config received!"); nm_ip4_address_unref (addr); - goto error; + g_object_unref (config); + nm_vpn_connection_config_maybe_complete (connection, FALSE); + return; } val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_DNS); @@ -539,9 +865,8 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy, if (val) nm_ip4_config_set_mss (config, g_value_get_uint (val)); - val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_MTU); - if (val) - nm_ip4_config_set_mtu (config, g_value_get_uint (val)); + if (priv->mtu) + nm_ip4_config_set_mtu (config, priv->mtu); val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_DOMAIN); if (val) @@ -556,12 +881,6 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy, nm_ip4_config_add_domain (config, *domain); } - val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_BANNER); - if (val) { - g_free (priv->banner); - priv->banner = g_strdup (g_value_get_string (val)); - } - val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP4_CONFIG_ROUTES); if (val) { GSList *routes; @@ -576,10 +895,12 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy, * the VPN server, we want to use the NM created route instead of * whatever the server provides. */ - if ( vpn_ext_gw - && nm_ip4_route_get_dest (route) == vpn_ext_gw - && nm_ip4_route_get_prefix (route) == 32) + if ( priv->ip4_external_gw + && nm_ip4_route_get_dest (route) == priv->ip4_external_gw + && nm_ip4_route_get_prefix (route) == 32) { + nm_ip4_route_unref (route); continue; + } /* Otherwise accept the VPN-provided route */ nm_ip4_config_take_route (config, route); @@ -592,42 +913,149 @@ nm_vpn_connection_ip4_config_get (DBusGProxy *proxy, if (val && G_VALUE_HOLDS_BOOLEAN (val)) nm_ip4_config_set_never_default (config, g_value_get_boolean (val)); - print_vpn_config (config, priv->ip4_internal_gw, priv->ip_iface, priv->banner); - /* Merge in user overrides from the NMConnection's IPv4 setting */ s_ip4 = nm_connection_get_setting_ip4_config (priv->connection); nm_utils_merge_ip4_config (config, s_ip4); - nm_system_iface_set_up (priv->ip_ifindex, TRUE, NULL); + priv->ip4_config = config; + nm_vpn_connection_config_maybe_complete (connection, TRUE); +} - if (nm_system_apply_ip4_config (priv->ip_ifindex, config, 0, NM_IP4_COMPARE_FLAG_ALL)) { - NMDnsManager *dns_mgr; +static void +nm_vpn_connection_ip6_config_get (DBusGProxy *proxy, + GHashTable *config_hash, + gpointer user_data) +{ + NMVPNConnection *connection = NM_VPN_CONNECTION (user_data); + NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); + NMSettingIP6Config *s_ip6; + NMIP6Address *addr; + NMIP6Config *config; + GValue *val; + int i; - /* Add any explicit route to the VPN gateway through the parent device */ - priv->gw_route = nm_system_add_ip4_vpn_gateway_route (priv->parent_dev, config); + nm_log_info (LOGD_VPN, "VPN connection '%s' (IP6 Config Get) reply received.", + nm_vpn_connection_get_name (connection)); - /* Add the VPN to DNS */ - dns_mgr = nm_dns_manager_get (NULL); - nm_dns_manager_add_ip4_config (dns_mgr, priv->ip_iface, config, NM_DNS_IP_CONFIG_TYPE_VPN); - g_object_unref (dns_mgr); + if (g_hash_table_size (config_hash) == 0) { + priv->has_ip6 = FALSE; + nm_vpn_connection_config_maybe_complete (connection, TRUE); + return; + } - priv->ip4_config = config; + config = nm_ip6_config_new (); - nm_log_info (LOGD_VPN, "VPN connection '%s' (IP Config Get) complete.", - nm_vpn_connection_get_name (connection)); - nm_vpn_connection_set_vpn_state (connection, - NM_VPN_CONNECTION_STATE_ACTIVATED, - NM_VPN_CONNECTION_STATE_REASON_NONE); - return; + addr = nm_ip6_address_new (); + nm_ip6_address_set_prefix (addr, 128); /* default to class C */ + if (priv->ip6_external_gw) + nm_ip6_address_set_gateway (addr, priv->ip6_external_gw); + + /* Internal address of the VPN subnet's gateway */ + val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP6_CONFIG_INT_GATEWAY); + if (val) { + GByteArray *ba = g_value_get_boxed (val); + + if (ba->len == sizeof (struct in6_addr)) + priv->ip6_internal_gw = g_memdup (ba->data, ba->len); } -error: - nm_log_warn (LOGD_VPN, "VPN connection '%s' did not receive valid IP config information.", - nm_vpn_connection_get_name (connection)); - nm_vpn_connection_set_vpn_state (connection, - NM_VPN_CONNECTION_STATE_FAILED, - NM_VPN_CONNECTION_STATE_REASON_IP_CONFIG_INVALID); - g_object_unref (config); + val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP6_CONFIG_ADDRESS); + if (val) { + GByteArray *ba = g_value_get_boxed (val); + + if (ba->len == sizeof (struct in6_addr)) + nm_ip6_address_set_address (addr, (struct in6_addr *)ba->data); + } + + val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP6_CONFIG_PTP); + if (val) { + GByteArray *ba = g_value_get_boxed (val); + + if (ba->len == sizeof (struct in6_addr)) + nm_ip6_config_set_ptp_address (config, (struct in6_addr *)ba->data); + } + + val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP6_CONFIG_PREFIX); + if (val) + nm_ip6_address_set_prefix (addr, g_value_get_uint (val)); + + if (nm_ip6_address_get_address (addr) && nm_ip6_address_get_prefix (addr)) { + nm_ip6_config_take_address (config, addr); + } else { + nm_log_err (LOGD_VPN, "invalid IP6 config received!"); + nm_ip6_address_unref (addr); + g_object_unref (config); + nm_vpn_connection_config_maybe_complete (connection, FALSE); + } + + val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP6_CONFIG_DNS); + if (val) { + GPtrArray *dns = (GPtrArray *) g_value_get_boxed (val); + GByteArray *ba; + + for (i = 0; i < dns->len; i++) { + ba = dns->pdata[i]; + if (ba->len == sizeof (struct in6_addr)) + nm_ip6_config_add_nameserver (config, (struct in6_addr *)ba->data); + } + } + + val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP6_CONFIG_MSS); + if (val) + nm_ip6_config_set_mss (config, g_value_get_uint (val)); + + val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP6_CONFIG_DOMAIN); + if (val) + nm_ip6_config_add_domain (config, g_value_get_string (val)); + + val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP6_CONFIG_DOMAINS); + if (val) { + const char **domains = g_value_get_boxed (val); + const char **domain; + + for (domain = domains; domain && *domain; domain++) + nm_ip6_config_add_domain (config, *domain); + } + + val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP6_CONFIG_ROUTES); + if (val) { + GSList *routes; + GSList *iter; + + routes = nm_utils_ip6_routes_from_gvalue (val); + for (iter = routes; iter; iter = iter->next) { + NMIP6Route *route = iter->data; + + /* Ignore host routes to the VPN gateway since NM adds one itself + * below. Since NM knows more about the routing situation than + * the VPN server, we want to use the NM created route instead of + * whatever the server provides. + */ + if ( priv->ip6_external_gw + && nm_ip6_route_get_prefix (route) == 128 + && memcmp (nm_ip6_route_get_dest (route), priv->ip6_external_gw, + sizeof (struct in6_addr)) == 0) { + nm_ip6_route_unref (route); + continue; + } + + /* Otherwise accept the VPN-provided route */ + nm_ip6_config_take_route (config, route); + } + + g_slist_free (routes); + } + + val = (GValue *) g_hash_table_lookup (config_hash, NM_VPN_PLUGIN_IP6_CONFIG_NEVER_DEFAULT); + if (val && G_VALUE_HOLDS_BOOLEAN (val)) + nm_ip6_config_set_never_default (config, g_value_get_boolean (val)); + + /* Merge in user overrides from the NMConnection's IPv6 setting */ + s_ip6 = nm_connection_get_setting_ip6_config (priv->connection); + nm_utils_merge_ip6_config (config, s_ip6); + + priv->ip6_config = config; + nm_vpn_connection_config_maybe_complete (connection, TRUE); } static gboolean @@ -716,9 +1144,18 @@ really_activate (NMVPNConnection *connection, const char *username) priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); - /* Ip4Config signal */ dbus_g_object_register_marshaller (g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, G_TYPE_VALUE, G_TYPE_INVALID); + + /* Config signal */ + dbus_g_proxy_add_signal (priv->proxy, "Config", + DBUS_TYPE_G_MAP_OF_VARIANT, + G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, "Config", + G_CALLBACK (nm_vpn_connection_config_get), + connection, NULL); + + /* Ip4Config signal */ dbus_g_proxy_add_signal (priv->proxy, "Ip4Config", DBUS_TYPE_G_MAP_OF_VARIANT, G_TYPE_INVALID); @@ -726,6 +1163,14 @@ really_activate (NMVPNConnection *connection, const char *username) G_CALLBACK (nm_vpn_connection_ip4_config_get), connection, NULL); + /* Ip6Config signal */ + dbus_g_proxy_add_signal (priv->proxy, "Ip6Config", + DBUS_TYPE_G_MAP_OF_VARIANT, + G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, "Ip6Config", + G_CALLBACK (nm_vpn_connection_ip6_config_get), + connection, NULL); + hash = _hash_with_username (priv->connection, username); org_freedesktop_NetworkManager_VPN_Plugin_connect_async (priv->proxy, hash, @@ -818,6 +1263,14 @@ nm_vpn_connection_get_ip4_config (NMVPNConnection *connection) return NM_VPN_CONNECTION_GET_PRIVATE (connection)->ip4_config; } +NMIP6Config * +nm_vpn_connection_get_ip6_config (NMVPNConnection *connection) +{ + g_return_val_if_fail (NM_IS_VPN_CONNECTION (connection), NULL); + + return NM_VPN_CONNECTION_GET_PRIVATE (connection)->ip6_config; +} + const char * nm_vpn_connection_get_ip_iface (NMVPNConnection *connection) { @@ -850,6 +1303,14 @@ nm_vpn_connection_get_ip4_internal_gateway (NMVPNConnection *connection) return NM_VPN_CONNECTION_GET_PRIVATE (connection)->ip4_internal_gw; } +struct in6_addr * +nm_vpn_connection_get_ip6_internal_gateway (NMVPNConnection *connection) +{ + g_return_val_if_fail (NM_IS_VPN_CONNECTION (connection), 0); + + return NM_VPN_CONNECTION_GET_PRIVATE (connection)->ip6_internal_gw; +} + void nm_vpn_connection_fail (NMVPNConnection *connection, NMVPNConnectionStateReason reason) @@ -896,11 +1357,19 @@ plugin_need_secrets_cb (DBusGProxy *proxy, if (setting_name && strlen (setting_name)) { /* More secrets required */ - nm_log_dbg (LOGD_VPN, "(%s/%s) service indicated additional secrets required", - nm_connection_get_uuid (priv->connection), - nm_connection_get_id (priv->connection)); - get_secrets (self, priv->secrets_idx + 1); + if (priv->secrets_idx == SECRETS_REQ_NEW) { + nm_log_err (LOGD_VPN, "(%s/%s) final secrets request failed to provide sufficient secrets", + nm_connection_get_uuid (priv->connection), + nm_connection_get_id (priv->connection)); + nm_vpn_connection_fail (self, NM_VPN_CONNECTION_STATE_REASON_NO_SECRETS); + } else { + nm_log_dbg (LOGD_VPN, "(%s/%s) service indicated additional secrets required", + nm_connection_get_uuid (priv->connection), + nm_connection_get_id (priv->connection)); + + get_secrets (self, priv->secrets_idx + 1); + } return; } @@ -985,6 +1454,9 @@ get_secrets (NMVPNConnection *self, SecretsReq secrets_idx) g_assert_not_reached (); } + if (priv->user_requested) + flags |= NM_SETTINGS_GET_SECRETS_FLAG_USER_REQUESTED; + priv->secrets_id = nm_settings_connection_get_secrets (NM_SETTINGS_CONNECTION (priv->connection), filter_by_uid, priv->user_uid, @@ -1004,109 +1476,7 @@ get_secrets (NMVPNConnection *self, SecretsReq secrets_idx) } } -static void -vpn_cleanup (NMVPNConnection *connection) -{ - NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (connection); - - if (priv->ip_ifindex) { - nm_system_iface_set_up (priv->ip_ifindex, FALSE, NULL); - /* FIXME: use AF_UNSPEC here when we have IPv6 support */ - nm_system_iface_flush_routes (priv->ip_ifindex, AF_INET); - nm_system_iface_flush_addresses (priv->ip_ifindex, AF_UNSPEC); - } - - if (priv->ip4_config) { - NMIP4Config *parent_config; - NMDnsManager *dns_mgr; - - /* Remove attributes of the VPN's IP4 Config */ - dns_mgr = nm_dns_manager_get (NULL); - nm_dns_manager_remove_ip4_config (dns_mgr, priv->ip_iface, priv->ip4_config); - g_object_unref (dns_mgr); - - /* Remove any previously added VPN gateway host route */ - if (priv->gw_route) - nm_netlink_route_delete (priv->gw_route); - - /* Reset routes and addresses of the currently active device */ - parent_config = nm_device_get_ip4_config (priv->parent_dev); - if (parent_config) { - if (!nm_system_apply_ip4_config (nm_device_get_ip_ifindex (priv->parent_dev), - nm_device_get_ip4_config (priv->parent_dev), - nm_device_get_priority (priv->parent_dev), - NM_IP4_COMPARE_FLAG_ADDRESSES | NM_IP4_COMPARE_FLAG_ROUTES)) { - nm_log_err (LOGD_VPN, "failed to re-apply VPN parent device addresses and routes."); - } - } - } - - if (priv->gw_route) { - rtnl_route_put (priv->gw_route); - priv->gw_route = NULL; - } - - g_free (priv->banner); - priv->banner = NULL; - - g_free (priv->ip_iface); - priv->ip_iface = NULL; - priv->ip_ifindex = 0; - - /* Clear out connection secrets to ensure that the settings service - * gets asked for them next time the connection is activated. - */ - if (priv->connection) - nm_connection_clear_secrets (priv->connection); -} - -static void -connection_state_changed (NMVPNConnection *self, - NMVPNConnectionState state, - NMVPNConnectionStateReason reason) -{ - NMVPNConnectionPrivate *priv = NM_VPN_CONNECTION_GET_PRIVATE (self); - - /* Clear any in-progress secrets request */ - if (priv->secrets_id) { - nm_settings_connection_cancel_secrets (NM_SETTINGS_CONNECTION (priv->connection), priv->secrets_id); - priv->secrets_id = 0; - } - priv->secrets_idx = SECRETS_REQ_SYSTEM; - - switch (state) { - case NM_VPN_CONNECTION_STATE_NEED_AUTH: - /* Kick off the secrets requests; first we get existing system secrets - * and ask the plugin if these are sufficient, next we get all existing - * secrets from system and from user agents and ask the plugin again, - * and last we ask the user for new secrets if required. - */ - get_secrets (self, SECRETS_REQ_SYSTEM); - break; - case NM_VPN_CONNECTION_STATE_ACTIVATED: - /* Secrets no longer needed now that we're connected */ - nm_connection_clear_secrets (priv->connection); - break; - case NM_VPN_CONNECTION_STATE_DISCONNECTED: - case NM_VPN_CONNECTION_STATE_FAILED: - if (priv->proxy) { - GError *err = NULL; - - org_freedesktop_NetworkManager_VPN_Plugin_disconnect (priv->proxy, &err); - if (err) { - nm_log_warn (LOGD_VPN, "error disconnecting VPN: %s", err->message); - g_error_free (err); - } - - g_object_unref (priv->proxy); - priv->proxy = NULL; - } - vpn_cleanup (self); - break; - default: - break; - } -} +/******************************************************************************/ static void nm_vpn_connection_init (NMVPNConnection *self) @@ -1127,9 +1497,15 @@ dispose (GObject *object) if (priv->gw_route) rtnl_route_put (priv->gw_route); + if (priv->ip6_internal_gw) + g_free (priv->ip6_internal_gw); + if (priv->ip6_external_gw) + g_free (priv->ip6_external_gw); if (priv->device_ip4) g_signal_handler_disconnect (priv->parent_dev, priv->device_ip4); + if (priv->device_ip6) + g_signal_handler_disconnect (priv->parent_dev, priv->device_ip6); if (priv->device_monitor) g_signal_handler_disconnect (priv->parent_dev, priv->device_monitor); @@ -1138,6 +1514,8 @@ dispose (GObject *object) if (priv->ip4_config) g_object_unref (priv->ip4_config); + if (priv->ip6_config) + g_object_unref (priv->ip6_config); if (priv->ipconfig_timeout) g_source_remove (priv->ipconfig_timeout); @@ -1197,7 +1575,6 @@ nm_vpn_connection_class_init (NMVPNConnectionClass *connection_class) g_type_class_add_private (connection_class, sizeof (NMVPNConnectionPrivate)); /* virtual methods */ - connection_class->vpn_state_changed = connection_state_changed; object_class->get_property = get_property; object_class->dispose = dispose; object_class->finalize = finalize; @@ -1223,16 +1600,14 @@ nm_vpn_connection_class_init (NMVPNConnectionClass *connection_class) /* signals */ signals[VPN_STATE_CHANGED] = - g_signal_new ("vpn-state-changed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMVPNConnectionClass, vpn_state_changed), - NULL, NULL, - _nm_marshal_VOID__UINT_UINT, - G_TYPE_NONE, 2, - G_TYPE_UINT, G_TYPE_UINT); + g_signal_new (NM_VPN_CONNECTION_VPN_STATE_CHANGED, + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + 0, NULL, NULL, + _nm_marshal_VOID__UINT_UINT_UINT, + G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT); dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (object_class), - &dbus_glib_nm_vpn_connection_object_info); + &dbus_glib_nm_vpn_connection_object_info); } diff --git a/src/vpn-manager/nm-vpn-connection.h b/src/vpn-manager/nm-vpn-connection.h index 93cc06d1..0e4f1a04 100644 --- a/src/vpn-manager/nm-vpn-connection.h +++ b/src/vpn-manager/nm-vpn-connection.h @@ -34,9 +34,14 @@ #define NM_IS_VPN_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_VPN_CONNECTION)) #define NM_VPN_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_VPN_CONNECTION, NMVPNConnectionClass)) +/* Properties */ #define NM_VPN_CONNECTION_VPN_STATE "vpn-state" #define NM_VPN_CONNECTION_BANNER "banner" +/* Signals */ +#define NM_VPN_CONNECTION_VPN_STATE_CHANGED "vpn-state-changed" + + typedef struct { NMActiveConnection parent; } NMVPNConnection; @@ -46,7 +51,8 @@ typedef struct { /* Signals */ void (*vpn_state_changed) (NMVPNConnection *connection, - NMVPNConnectionState state, + NMVPNConnectionState new_state, + NMVPNConnectionState old_state, NMVPNConnectionStateReason reason); } NMVPNConnectionClass; @@ -68,9 +74,11 @@ void nm_vpn_connection_fail (NMVPNConnection *connect void nm_vpn_connection_disconnect (NMVPNConnection *connection, NMVPNConnectionStateReason reason); NMIP4Config * nm_vpn_connection_get_ip4_config (NMVPNConnection *connection); +NMIP6Config * nm_vpn_connection_get_ip6_config (NMVPNConnection *connection); const char * nm_vpn_connection_get_ip_iface (NMVPNConnection *connection); int nm_vpn_connection_get_ip_ifindex (NMVPNConnection *connection); NMDevice * nm_vpn_connection_get_parent_device (NMVPNConnection *connection); guint32 nm_vpn_connection_get_ip4_internal_gateway (NMVPNConnection *connection); +struct in6_addr * nm_vpn_connection_get_ip6_internal_gateway (NMVPNConnection *connection); #endif /* NM_VPN_CONNECTION_H */ diff --git a/src/vpn-manager/nm-vpn-manager.c b/src/vpn-manager/nm-vpn-manager.c index 34131964..a462f547 100644 --- a/src/vpn-manager/nm-vpn-manager.c +++ b/src/vpn-manager/nm-vpn-manager.c @@ -115,19 +115,20 @@ find_active_vpn_connection_by_connection (NMVPNManager *self, NMConnection *conn static void connection_vpn_state_changed (NMVPNConnection *connection, - NMVPNConnectionState state, + NMVPNConnectionState new_state, + NMVPNConnectionState old_state, NMVPNConnectionStateReason reason, gpointer user_data) { NMVPNManager *manager = NM_VPN_MANAGER (user_data); - switch (state) { + switch (new_state) { case NM_VPN_CONNECTION_STATE_ACTIVATED: g_signal_emit (manager, signals[CONNECTION_ACTIVATED], 0, connection); break; case NM_VPN_CONNECTION_STATE_FAILED: case NM_VPN_CONNECTION_STATE_DISCONNECTED: - g_signal_emit (manager, signals[CONNECTION_DEACTIVATED], 0, connection, state, reason); + g_signal_emit (manager, signals[CONNECTION_DEACTIVATED], 0, connection, new_state, old_state, reason); break; default: break; @@ -188,7 +189,7 @@ nm_vpn_manager_activate_connection (NMVPNManager *manager, vpn = nm_vpn_service_activate (service, connection, device, specific_object, user_requested, user_uid, error); if (vpn) { - g_signal_connect (vpn, "vpn-state-changed", + g_signal_connect (vpn, NM_VPN_CONNECTION_VPN_STATE_CHANGED, G_CALLBACK (connection_vpn_state_changed), manager); } @@ -518,11 +519,9 @@ nm_vpn_manager_class_init (NMVPNManagerClass *manager_class) g_signal_new ("connection-deactivated", G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMVPNManagerClass, connection_deactivated), - NULL, NULL, - _nm_marshal_VOID__OBJECT_UINT_UINT, - G_TYPE_NONE, 3, - G_TYPE_OBJECT, G_TYPE_UINT, G_TYPE_UINT); + 0, NULL, NULL, + _nm_marshal_VOID__OBJECT_UINT_UINT_UINT, + G_TYPE_NONE, 4, G_TYPE_OBJECT, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT); dbus_g_error_domain_register (NM_VPN_MANAGER_ERROR, NULL, NM_TYPE_VPN_MANAGER_ERROR); } diff --git a/src/vpn-manager/nm-vpn-manager.h b/src/vpn-manager/nm-vpn-manager.h index cec370c8..17225b44 100644 --- a/src/vpn-manager/nm-vpn-manager.h +++ b/src/vpn-manager/nm-vpn-manager.h @@ -55,9 +55,13 @@ typedef struct { GObjectClass parent; /* Signals */ + void (*connection_activated) (NMVPNManager *manager, + NMVPNConnection *connection); + void (*connection_deactivated) (NMVPNManager *manager, NMVPNConnection *connection, - NMVPNConnectionState state, + NMVPNConnectionState new_state, + NMVPNConnectionState old_state, NMVPNConnectionStateReason reason); } NMVPNManagerClass; diff --git a/src/vpn-manager/nm-vpn-service.c b/src/vpn-manager/nm-vpn-service.c index 95e4f2b1..a2c8b100 100644 --- a/src/vpn-manager/nm-vpn-service.c +++ b/src/vpn-manager/nm-vpn-service.c @@ -15,7 +15,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright (C) 2005 - 2011 Red Hat, Inc. + * Copyright (C) 2005 - 2012 Red Hat, Inc. * Copyright (C) 2005 - 2008 Novell, Inc. */ @@ -31,6 +31,7 @@ #include "nm-vpn-service.h" #include "nm-dbus-manager.h" #include "nm-logging.h" +#include "nm-posix-signals.h" #include "nm-vpn-manager.h" #include "nm-glib-compat.h" @@ -168,6 +169,12 @@ nm_vpn_service_child_setup (gpointer user_data G_GNUC_UNUSED) /* We are in the child process at this point */ pid_t pid = getpid (); setpgid (pid, pid); + + /* + * We blocked signals in main(). We need to restore original signal + * mask for VPN service here so that it can receive signals. + */ + nm_unblock_posix_signals (NULL); } static void @@ -296,13 +303,14 @@ service_quit (gpointer user_data) static void connection_vpn_state_changed (NMVPNConnection *connection, - NMVPNConnectionState state, + NMVPNConnectionState new_state, + NMVPNConnectionState old_state, NMVPNConnectionStateReason reason, gpointer user_data) { NMVPNServicePrivate *priv = NM_VPN_SERVICE_GET_PRIVATE (user_data); - switch (state) { + switch (new_state) { case NM_VPN_CONNECTION_STATE_FAILED: case NM_VPN_CONNECTION_STATE_DISCONNECTED: /* Remove the connection from our list */ @@ -343,9 +351,9 @@ nm_vpn_service_activate (NMVPNService *service, clear_quit_timeout (service); vpn = nm_vpn_connection_new (connection, device, specific_object, user_requested, user_uid); - g_signal_connect (vpn, "vpn-state-changed", - G_CALLBACK (connection_vpn_state_changed), - service); + g_signal_connect (vpn, NM_VPN_CONNECTION_VPN_STATE_CHANGED, + G_CALLBACK (connection_vpn_state_changed), + service); priv->connections = g_slist_prepend (priv->connections, vpn); diff --git a/src/wifi/Makefile.in b/src/wifi/Makefile.in index 028469bf..5e77bae3 100644 --- a/src/wifi/Makefile.in +++ b/src/wifi/Makefile.in @@ -48,7 +48,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -174,6 +174,10 @@ 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@ @@ -269,6 +273,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -307,6 +314,8 @@ 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@ diff --git a/src/wifi/wifi-utils-nl80211.c b/src/wifi/wifi-utils-nl80211.c index 4a4e661e..663cbc26 100644 --- a/src/wifi/wifi-utils-nl80211.c +++ b/src/wifi/wifi-utils-nl80211.c @@ -535,7 +535,9 @@ struct nl80211_device_info { guint32 *freqs; int num_freqs; guint32 caps; - gboolean can_scan, can_scan_ssid; + gboolean can_scan; + gboolean can_scan_ssid; + gboolean supported; gboolean success; }; @@ -579,11 +581,24 @@ static int nl80211_wiphy_info_handler (struct nl_msg *msg, void *arg) struct nlattr *nl_cmd; int i; - nla_for_each_nested (nl_cmd, - tb[NL80211_ATTR_SUPPORTED_COMMANDS], i) { - guint32 cmd = nla_get_u32 (nl_cmd); - if (cmd == NL80211_CMD_TRIGGER_SCAN) + nla_for_each_nested (nl_cmd, tb[NL80211_ATTR_SUPPORTED_COMMANDS], i) { + switch (nla_get_u32 (nl_cmd)) { + case NL80211_CMD_TRIGGER_SCAN: info->can_scan = TRUE; + break; + case NL80211_CMD_CONNECT: + case NL80211_CMD_AUTHENTICATE: + /* Only devices that support CONNECT or AUTH actually support + * 802.11, unlike say ipw2x00 (up to at least kernel 3.4) which + * has minimal info support, but no actual command support. + * This check mirrors what wpa_supplicant does to determine + * whether or not to use the nl80211 driver. + */ + info->supported = TRUE; + break; + default: + break; + } } } @@ -650,6 +665,9 @@ static int nl80211_wiphy_info_handler (struct nl_msg *msg, void *arg) info->caps |= NM_WIFI_DEVICE_CAP_CIPHER_CCMP | NM_WIFI_DEVICE_CAP_RSN; break; + default: + nm_log_err (LOGD_HW | LOGD_WIFI, "Don't know the meaning of NL80211_ATTR_CIPHER_SUITES %#8.8x.", ciphers[i]); + break; } } } @@ -721,6 +739,13 @@ wifi_nl80211_init (const char *iface, int ifindex) goto error; } + if (!device_info.supported) { + nm_log_dbg (LOGD_HW | LOGD_WIFI, + "(%s): driver does not fully support nl80211, falling back to WEXT", + nl80211->parent.iface); + goto error; + } + if (!device_info.can_scan_ssid) { nm_log_err (LOGD_HW | LOGD_WIFI, "(%s): driver does not support SSID scans", @@ -735,6 +760,13 @@ wifi_nl80211_init (const char *iface, int ifindex) goto error; } + if (device_info.caps == 0) { + nm_log_err (LOGD_HW | LOGD_WIFI, + "(%s): driver doesn't report support of any encryption", + nl80211->parent.iface); + goto error; + } + nl80211->freqs = device_info.freqs; nl80211->num_freqs = device_info.num_freqs; nl80211->parent.can_scan_ssid = device_info.can_scan_ssid; diff --git a/src/wimax/Makefile.in b/src/wimax/Makefile.in index 2de52180..e463cf2d 100644 --- a/src/wimax/Makefile.in +++ b/src/wimax/Makefile.in @@ -47,7 +47,7 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/compiler_warnings.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/nls.m4 \ $(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/progtest.m4 \ - $(top_srcdir)/configure.ac + $(top_srcdir)/m4/vapigen.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -199,6 +199,10 @@ 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@ @@ -294,6 +298,9 @@ UDEV_BASE_DIR = @UDEV_BASE_DIR@ USE_NLS = @USE_NLS@ UUID_CFLAGS = @UUID_CFLAGS@ UUID_LIBS = @UUID_LIBS@ +VAPIGEN = @VAPIGEN@ +VAPIGEN_MAKEFILE = @VAPIGEN_MAKEFILE@ +VAPIGEN_VAPIDIR = @VAPIGEN_VAPIDIR@ VERSION = @VERSION@ XGETTEXT = @XGETTEXT@ XGETTEXT_015 = @XGETTEXT_015@ @@ -332,6 +339,8 @@ 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@ |