upgrade to version 1.3 56/1656/1 submit/trunk/20120912.071821
authorchengyix,zhao <chengyix.zhao@intel.com>
Fri, 7 Sep 2012 02:47:41 +0000 (10:47 +0800)
committerchengyix,zhao <chengyix.zhao@intel.com>
Fri, 7 Sep 2012 02:47:41 +0000 (10:47 +0800)
70 files changed:
AUTHORS
ChangeLog
Makefile.am
Makefile.in
Makefile.plugins
README
TODO
aclocal.m4
compile
config.sub
configure
configure.ac
depcomp
doc/agent-api.txt
doc/config-format.txt
doc/service-api.txt
doc/technology-api.txt
gdbus/gdbus.h
gdbus/object.c
gdbus/watch.c
gdhcp/client.c
gsupplicant/supplicant.c
gweb/giognutls.c
gweb/giognutls.h
gweb/gionotls.c
gweb/gresolv.c
gweb/gweb.c
gweb/gweb.h
include/device.h
include/inet.h
include/network.h
include/setting.h
packaging/connman.spec
plugins/bluetooth.c
plugins/dundee.c [new file with mode: 0644]
plugins/nmcompat.c
plugins/ofono.c
plugins/vpn.c
plugins/wifi.c
src/agent.c
src/clock.c
src/config.c
src/connection.c
src/connman.h
src/device.c
src/dhcp.c
src/dhcpv6.c
src/dnsproxy.c
src/inet.c
src/ipconfig.c
src/ippool.c
src/iptables.c
src/main.c
src/manager.c
src/network.c
src/ntp.c
src/resolver.c
src/rtnl.c
src/service.c
src/session.c
src/storage.c
src/technology.c
src/tethering.c
src/timeserver.c
src/wispr.c
tools/iptables-test.c
tools/supplicant.c
tools/wispr.c
unit/session-api.c
unit/utils.c

diff --git a/AUTHORS b/AUTHORS
index 5551fbb..33404c4 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -41,3 +41,8 @@ Mario Domenech Goulart <mario.goulart@gmail.com>
 Otavio Salvador <otavio@ossystems.com.br>
 Tim Sander <tim01@iss.tu-darmstadt.de>
 Adrien Bustany <adrien.bustany@nokia.com>
+Henrique Dante de Almeida <hdante@profusion.mobi>
+Lucas De Marchi <lucas.demarchi@profusion.mobi>
+Elena Tebesoi <elena.tebesoi@gmail.com>
+Mikel Astiz <mikel.astiz@bmw-carit.de>
+Paulo Pizarro <paulo.pizarro@gmail.com>
index 24a58be..a069a74 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,42 @@
+ver 1.3:
+       Fix issue with default configuration values.
+       Fix issue with timeserver canonical name entries.
+       Fix issue with crash from cellular dummy context.
+       Fix issue with incorrect index for private networks.
+
+ver 1.2:
+       Fix issue with not handling WiFi security changes.
+       Fix issue with not stopping WiFi scanning on shutdown.
+       Fix issue with auto-scanning and network discovery.
+       Fix issue with D-Bus reply for hidden WiFi networks.
+       Fix issue with overlapping memory areas and DNS requests.
+       Add support for randomized DNS transaction identifiers.
+       Add support for DNS caching over TCP connections.
+       Add support for using default IPv6 privacy setting.
+       Add support for providing previous passphrase to agent.
+       Add support for configuration unprovisioning handling.
+       Add support for NetworkInterfaceBlacklist configuration.
+       Add support for Bluetooth DUN daemon (dundee).
+
+ver 1.1:
+       Fix issue with missing message type and DHCPv4 support.
+       Fix issue with potential NULL pointer in DHCPv6 handling.
+       Fix issue with potential NULL pointer in VPN handling.
+       Fix issue with potential NULL pointer for WiFi SSID.
+       Fix issue with missing conversion of raw WiFi PSK input.
+       Fix issue with missing stop for WiFi auto-scanning handling.
+       Fix issue with uninitialized IPv6 prefix length in oFono plugin.
+       Fix issue with domain search list handling according to RFC 6106.
+       Fix issue with domain name list notifications.
+       Fix issue with nameserver list notifications.
+       Fix issue with incorrect fixed IP configuration.
+       Fix issue with incorrect cleanup of resolver timers.
+       Fix issue with handling of RDNSS lifetime expiration.
+       Fix issue with crash on wrong domain length information.
+       Add support for favorite service database migration.
+       Add support for disabling WISPr functionality.
+       Add support for configurable agent timeouts.
+
 ver 1.0:
        Fix issue with missing WiFi disconnecting flag.
        Fix issue with missing GPRS context attached check.
index 9eeb2f5..9d713ae 100644 (file)
@@ -27,8 +27,13 @@ gdbus_sources = gdbus/gdbus.h gdbus/mainloop.c gdbus/watch.c \
 gdhcp_sources = gdhcp/gdhcp.h gdhcp/common.h gdhcp/common.c gdhcp/client.c \
                gdhcp/server.c gdhcp/ipv4ll.h gdhcp/ipv4ll.c
 
-gweb_sources = gweb/gweb.h gweb/gweb.c gweb/gresolv.h gweb/gresolv.c \
-                                       gweb/giognutls.h gweb/giognutls.c
+gweb_sources = gweb/gweb.h gweb/gweb.c gweb/gresolv.h gweb/gresolv.c
+
+if WISPR
+gweb_sources += gweb/giognutls.h gweb/giognutls.c
+else
+gweb_sources += gweb/giognutls.h gweb/gionotls.c
+endif
 
 if DATAFILES
 
@@ -62,10 +67,7 @@ unit_objects =
 
 sbin_PROGRAMS = src/connmand
 
-src_connmand_SOURCES = $(gdbus_sources) $(gdhcp_sources) \
-                       gweb/gweb.h gweb/gweb.c \
-                       gweb/gresolv.h gweb/gresolv.c \
-                       gweb/giognutls.h gweb/giognutls.c \
+src_connmand_SOURCES = $(gdbus_sources) $(gdhcp_sources) $(gweb_sources) \
                        $(builtin_sources) src/connman.ver \
                        src/main.c src/connman.h src/log.c \
                        src/error.c src/plugin.c src/task.c \
@@ -122,7 +124,7 @@ AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @XTABLES_CFLAGS@ \
 INCLUDES = -I$(builddir)/include -I$(builddir)/src -I$(srcdir)/gdbus
 
 EXTRA_DIST = src/genbuiltin src/connman-dbus.conf src/connman-polkit.conf \
-               plugins/connman-nmcompat.conf gweb/gionotls.c
+                                               plugins/connman-nmcompat.conf
 
 
 script_DATA =
@@ -138,8 +140,15 @@ client_cm_SOURCES = client/main.c
 client_cm_LDADD = @DBUS_LIBS@
 endif
 
+if WISPR
+noinst_PROGRAMS += tools/wispr
+
+tools_wispr_SOURCES = $(gweb_sources) tools/wispr.c
+tools_wispr_LDADD = @GLIB_LIBS@ @GNUTLS_LIBS@ -lresolv
+endif
+
 if TOOLS
-noinst_PROGRAMS += tools/wispr tools/supplicant-test \
+noinst_PROGRAMS += tools/supplicant-test \
                        tools/dhcp-test tools/dhcp-server-test \
                        tools/addr-test tools/web-test tools/resolv-test \
                        tools/dbus-test tools/polkit-test \
@@ -147,9 +156,6 @@ noinst_PROGRAMS += tools/wispr tools/supplicant-test \
                        tools/stats-tool tools/private-network-test \
                        unit/test-session unit/test-ippool unit/test-nat
 
-tools_wispr_SOURCES = $(gweb_sources) tools/wispr.c
-tools_wispr_LDADD = @GLIB_LIBS@ @GNUTLS_LIBS@ -lresolv
-
 tools_supplicant_test_SOURCES = $(gdbus_sources) tools/supplicant-test.c \
                        tools/supplicant-dbus.h tools/supplicant-dbus.c \
                        tools/supplicant.h tools/supplicant.c
index a23023d..0d9fd07 100644 (file)
@@ -1,4 +1,4 @@
-# Makefile.in generated by automake 1.11.3 from Makefile.am.
+# Makefile.in generated by automake 1.11.5 from Makefile.am.
 # @configure_input@
 
 # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
 
 
 VPATH = @srcdir@
+am__make_dryrun = \
+  { \
+    am__dry=no; \
+    case $$MAKEFLAGS in \
+      *\\[\ \  ]*) \
+        echo 'am--echo: ; @echo "AM"  OK' | $(MAKE) -f - 2>/dev/null \
+          | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+      *) \
+        for am__flg in $$MAKEFLAGS; do \
+          case $$am__flg in \
+            *=*|--*) ;; \
+            *n*) am__dry=yes; break;; \
+          esac; \
+        done;; \
+    esac; \
+    test $$am__dry = yes; \
+  }
 pkgdatadir = $(datadir)/@PACKAGE@
 pkgincludedir = $(includedir)/@PACKAGE@
 pkglibdir = $(libdir)/@PACKAGE@
@@ -38,9 +55,11 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
-noinst_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2)
+@WISPR_TRUE@am__append_1 = gweb/giognutls.h gweb/giognutls.c
+@WISPR_FALSE@am__append_2 = gweb/giognutls.h gweb/gionotls.c
+noinst_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3)
 sbin_PROGRAMS = src/connmand$(EXEEXT)
-script_PROGRAMS = $(am__EXEEXT_3) $(am__EXEEXT_4) $(am__EXEEXT_5)
+script_PROGRAMS = $(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6)
 DIST_COMMON = README $(am__configure_deps) $(include_HEADERS) \
        $(noinst_HEADERS) $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
        $(srcdir)/Makefile.plugins $(srcdir)/config.h.in \
@@ -51,66 +70,69 @@ DIST_COMMON = README $(am__configure_deps) $(include_HEADERS) \
        $(top_srcdir)/src/connman.service.in AUTHORS COPYING ChangeLog \
        INSTALL NEWS TODO compile config.guess config.sub depcomp \
        install-sh ltmain.sh missing
-@LOOPBACK_TRUE@am__append_1 = loopback
-@LOOPBACK_TRUE@am__append_2 = plugins/loopback.c
-@ETHERNET_TRUE@am__append_3 = ethernet
-@ETHERNET_TRUE@am__append_4 = plugins/ethernet.c
-@WIFI_TRUE@am__append_5 = wifi
-@WIFI_TRUE@am__append_6 = plugins/wifi.c $(gsupplicant_sources)
-@BLUETOOTH_TRUE@am__append_7 = bluetooth
-@BLUETOOTH_TRUE@am__append_8 = plugins/bluetooth.c
-@HH2SERIAL_GPS_BUILTIN_TRUE@@HH2SERIAL_GPS_TRUE@am__append_9 = hh2serial_gps
-@HH2SERIAL_GPS_BUILTIN_TRUE@@HH2SERIAL_GPS_TRUE@am__append_10 = plugins/hh2serial-gps.c
-@HH2SERIAL_GPS_BUILTIN_FALSE@@HH2SERIAL_GPS_TRUE@am__append_11 = plugins/hh2serial-gps.la
-@HH2SERIAL_GPS_BUILTIN_FALSE@@HH2SERIAL_GPS_TRUE@am__append_12 = $(plugins_hh2serial_gps_la_OBJECTS)
-@OFONO_TRUE@am__append_13 = ofono
-@OFONO_TRUE@am__append_14 = plugins/mcc.h plugins/ofono.c
-@OPENCONNECT_BUILTIN_TRUE@@OPENCONNECT_TRUE@am__append_15 = openconnect
-@OPENCONNECT_BUILTIN_TRUE@@OPENCONNECT_TRUE@am__append_16 = plugins/openconnect.c
-@OPENCONNECT_BUILTIN_TRUE@@OPENCONNECT_TRUE@am__append_17 = -DOPENCONNECT=\"@OPENCONNECT@\"
-@OPENCONNECT_BUILTIN_FALSE@@OPENCONNECT_TRUE@am__append_18 = plugins/openconnect.la
-@OPENCONNECT_BUILTIN_FALSE@@OPENCONNECT_TRUE@am__append_19 = $(plugins_openconnect_la_OBJECTS)
-@OPENVPN_BUILTIN_TRUE@@OPENVPN_TRUE@am__append_20 = openvpn
-@OPENVPN_BUILTIN_TRUE@@OPENVPN_TRUE@am__append_21 = plugins/openvpn.c
-@OPENVPN_BUILTIN_TRUE@@OPENVPN_TRUE@am__append_22 = -DOPENVPN=\"@OPENVPN@\"
-@OPENVPN_BUILTIN_FALSE@@OPENVPN_TRUE@am__append_23 = plugins/openvpn.la
-@OPENVPN_BUILTIN_FALSE@@OPENVPN_TRUE@am__append_24 = $(plugins_openvpn_la_OBJECTS)
-@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__append_25 = vpnc
-@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__append_26 = plugins/vpnc.c
-@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__append_27 = -DVPNC=\"@VPNC@\"
-@VPNC_BUILTIN_FALSE@@VPNC_TRUE@am__append_28 = plugins/vpnc.la
-@VPNC_BUILTIN_FALSE@@VPNC_TRUE@am__append_29 = $(plugins_vpnc_la_OBJECTS)
-@L2TP_BUILTIN_TRUE@@L2TP_TRUE@am__append_30 = l2tp
-@L2TP_BUILTIN_TRUE@@L2TP_TRUE@am__append_31 = plugins/l2tp.c
-@L2TP_BUILTIN_TRUE@@L2TP_TRUE@am__append_32 = -DL2TP=\"@L2TP@\"
-@L2TP_BUILTIN_FALSE@@L2TP_TRUE@am__append_33 = plugins/l2tp.la
-@L2TP_BUILTIN_FALSE@@L2TP_TRUE@am__append_34 = $(plugins_l2tp_la_OBJECTS)
-@PPTP_BUILTIN_TRUE@@PPTP_TRUE@am__append_35 = pptp
-@PPTP_BUILTIN_TRUE@@PPTP_TRUE@am__append_36 = plugins/pptp.c
-@PPTP_BUILTIN_TRUE@@PPTP_TRUE@am__append_37 = -DPPPD=\"@PPPD@\" -DPPTP=\"@PPTP@\"
-@PPTP_BUILTIN_FALSE@@PPTP_TRUE@am__append_38 = plugins/pptp.la
-@PPTP_BUILTIN_FALSE@@PPTP_TRUE@am__append_39 = $(plugins_pptp_la_OBJECTS)
-@PPTP_TRUE@am__append_40 = scripts/libppp-plugin.la
-@L2TP_TRUE@@PPTP_FALSE@am__append_41 = scripts/libppp-plugin.la
-@PACRUNNER_TRUE@am__append_42 = pacrunner
-@PACRUNNER_TRUE@am__append_43 = plugins/pacrunner.c
-@POLKIT_TRUE@am__append_44 = polkit
-@POLKIT_TRUE@am__append_45 = plugins/polkit.c
-@IWMX_TRUE@am__append_46 = plugins/iwmxsdk.la
-@IWMX_TRUE@am__append_47 = $(plugins_iwmxsdk_la_OBJECTS)
-@IOSPM_TRUE@am__append_48 = plugins/iospm.la
-@IOSPM_TRUE@am__append_49 = $(plugins_iospm_la_OBJECTS)
-@OPENCONNECT_TRUE@am__append_50 = scripts/openconnect-script
-@OPENCONNECT_FALSE@@VPNC_TRUE@am__append_51 = scripts/openconnect-script
-@OPENVPN_TRUE@am__append_52 = scripts/openvpn-script
-@NMCOMPAT_TRUE@am__append_53 = nmcompat
-@NMCOMPAT_TRUE@am__append_54 = plugins/nmcompat.c
-@TIST_BUILTIN_TRUE@@TIST_TRUE@am__append_55 = tist
-@TIST_BUILTIN_TRUE@@TIST_TRUE@am__append_56 = plugins/tist.c
-@TIST_BUILTIN_FALSE@@TIST_TRUE@am__append_57 = plugins/tist.la
-@TIST_BUILTIN_FALSE@@TIST_TRUE@am__append_58 = $(plugins_tist_la_OBJECTS)
-@CLIENT_TRUE@am__append_59 = client/cm
-@TOOLS_TRUE@am__append_60 = tools/wispr tools/supplicant-test \
+@LOOPBACK_TRUE@am__append_3 = loopback
+@LOOPBACK_TRUE@am__append_4 = plugins/loopback.c
+@ETHERNET_TRUE@am__append_5 = ethernet
+@ETHERNET_TRUE@am__append_6 = plugins/ethernet.c
+@WIFI_TRUE@am__append_7 = wifi
+@WIFI_TRUE@am__append_8 = plugins/wifi.c $(gsupplicant_sources)
+@BLUETOOTH_TRUE@am__append_9 = bluetooth
+@BLUETOOTH_TRUE@am__append_10 = plugins/bluetooth.c
+@HH2SERIAL_GPS_BUILTIN_TRUE@@HH2SERIAL_GPS_TRUE@am__append_11 = hh2serial_gps
+@HH2SERIAL_GPS_BUILTIN_TRUE@@HH2SERIAL_GPS_TRUE@am__append_12 = plugins/hh2serial-gps.c
+@HH2SERIAL_GPS_BUILTIN_FALSE@@HH2SERIAL_GPS_TRUE@am__append_13 = plugins/hh2serial-gps.la
+@HH2SERIAL_GPS_BUILTIN_FALSE@@HH2SERIAL_GPS_TRUE@am__append_14 = $(plugins_hh2serial_gps_la_OBJECTS)
+@OFONO_TRUE@am__append_15 = ofono
+@OFONO_TRUE@am__append_16 = plugins/mcc.h plugins/ofono.c
+@DUNDEE_TRUE@am__append_17 = dundee
+@DUNDEE_TRUE@am__append_18 = plugins/dundee.c
+@OPENCONNECT_BUILTIN_TRUE@@OPENCONNECT_TRUE@am__append_19 = openconnect
+@OPENCONNECT_BUILTIN_TRUE@@OPENCONNECT_TRUE@am__append_20 = plugins/openconnect.c
+@OPENCONNECT_BUILTIN_TRUE@@OPENCONNECT_TRUE@am__append_21 = -DOPENCONNECT=\"@OPENCONNECT@\"
+@OPENCONNECT_BUILTIN_FALSE@@OPENCONNECT_TRUE@am__append_22 = plugins/openconnect.la
+@OPENCONNECT_BUILTIN_FALSE@@OPENCONNECT_TRUE@am__append_23 = $(plugins_openconnect_la_OBJECTS)
+@OPENVPN_BUILTIN_TRUE@@OPENVPN_TRUE@am__append_24 = openvpn
+@OPENVPN_BUILTIN_TRUE@@OPENVPN_TRUE@am__append_25 = plugins/openvpn.c
+@OPENVPN_BUILTIN_TRUE@@OPENVPN_TRUE@am__append_26 = -DOPENVPN=\"@OPENVPN@\"
+@OPENVPN_BUILTIN_FALSE@@OPENVPN_TRUE@am__append_27 = plugins/openvpn.la
+@OPENVPN_BUILTIN_FALSE@@OPENVPN_TRUE@am__append_28 = $(plugins_openvpn_la_OBJECTS)
+@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__append_29 = vpnc
+@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__append_30 = plugins/vpnc.c
+@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__append_31 = -DVPNC=\"@VPNC@\"
+@VPNC_BUILTIN_FALSE@@VPNC_TRUE@am__append_32 = plugins/vpnc.la
+@VPNC_BUILTIN_FALSE@@VPNC_TRUE@am__append_33 = $(plugins_vpnc_la_OBJECTS)
+@L2TP_BUILTIN_TRUE@@L2TP_TRUE@am__append_34 = l2tp
+@L2TP_BUILTIN_TRUE@@L2TP_TRUE@am__append_35 = plugins/l2tp.c
+@L2TP_BUILTIN_TRUE@@L2TP_TRUE@am__append_36 = -DL2TP=\"@L2TP@\"
+@L2TP_BUILTIN_FALSE@@L2TP_TRUE@am__append_37 = plugins/l2tp.la
+@L2TP_BUILTIN_FALSE@@L2TP_TRUE@am__append_38 = $(plugins_l2tp_la_OBJECTS)
+@PPTP_BUILTIN_TRUE@@PPTP_TRUE@am__append_39 = pptp
+@PPTP_BUILTIN_TRUE@@PPTP_TRUE@am__append_40 = plugins/pptp.c
+@PPTP_BUILTIN_TRUE@@PPTP_TRUE@am__append_41 = -DPPPD=\"@PPPD@\" -DPPTP=\"@PPTP@\"
+@PPTP_BUILTIN_FALSE@@PPTP_TRUE@am__append_42 = plugins/pptp.la
+@PPTP_BUILTIN_FALSE@@PPTP_TRUE@am__append_43 = $(plugins_pptp_la_OBJECTS)
+@PPTP_TRUE@am__append_44 = scripts/libppp-plugin.la
+@L2TP_TRUE@@PPTP_FALSE@am__append_45 = scripts/libppp-plugin.la
+@PACRUNNER_TRUE@am__append_46 = pacrunner
+@PACRUNNER_TRUE@am__append_47 = plugins/pacrunner.c
+@POLKIT_TRUE@am__append_48 = polkit
+@POLKIT_TRUE@am__append_49 = plugins/polkit.c
+@IWMX_TRUE@am__append_50 = plugins/iwmxsdk.la
+@IWMX_TRUE@am__append_51 = $(plugins_iwmxsdk_la_OBJECTS)
+@IOSPM_TRUE@am__append_52 = plugins/iospm.la
+@IOSPM_TRUE@am__append_53 = $(plugins_iospm_la_OBJECTS)
+@OPENCONNECT_TRUE@am__append_54 = scripts/openconnect-script
+@OPENCONNECT_FALSE@@VPNC_TRUE@am__append_55 = scripts/openconnect-script
+@OPENVPN_TRUE@am__append_56 = scripts/openvpn-script
+@NMCOMPAT_TRUE@am__append_57 = nmcompat
+@NMCOMPAT_TRUE@am__append_58 = plugins/nmcompat.c
+@TIST_BUILTIN_TRUE@@TIST_TRUE@am__append_59 = tist
+@TIST_BUILTIN_TRUE@@TIST_TRUE@am__append_60 = plugins/tist.c
+@TIST_BUILTIN_FALSE@@TIST_TRUE@am__append_61 = plugins/tist.la
+@TIST_BUILTIN_FALSE@@TIST_TRUE@am__append_62 = $(plugins_tist_la_OBJECTS)
+@CLIENT_TRUE@am__append_63 = client/cm
+@WISPR_TRUE@am__append_64 = tools/wispr
+@TOOLS_TRUE@am__append_65 = tools/supplicant-test \
 @TOOLS_TRUE@                   tools/dhcp-test tools/dhcp-server-test \
 @TOOLS_TRUE@                   tools/addr-test tools/web-test tools/resolv-test \
 @TOOLS_TRUE@                   tools/dbus-test tools/polkit-test \
@@ -118,7 +140,7 @@ DIST_COMMON = README $(am__configure_deps) $(include_HEADERS) \
 @TOOLS_TRUE@                   tools/stats-tool tools/private-network-test \
 @TOOLS_TRUE@                   unit/test-session unit/test-ippool unit/test-nat
 
-@TOOLS_TRUE@am__append_61 = $(unit_test_session_OBJECTS) \
+@TOOLS_TRUE@am__append_66 = $(unit_test_session_OBJECTS) \
 @TOOLS_TRUE@   $(unit_test_ippool_OBJECTS) \
 @TOOLS_TRUE@   $(unit_nat_ippool_OBJECTS)
 subdir = .
@@ -287,8 +309,8 @@ scripts_libppp_plugin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 @L2TP_TRUE@@PPTP_FALSE@        $(scriptdir)
 @PPTP_TRUE@am_scripts_libppp_plugin_la_rpath = -rpath $(scriptdir)
 @CLIENT_TRUE@am__EXEEXT_1 = client/cm$(EXEEXT)
-@TOOLS_TRUE@am__EXEEXT_2 = tools/wispr$(EXEEXT) \
-@TOOLS_TRUE@   tools/supplicant-test$(EXEEXT) \
+@WISPR_TRUE@am__EXEEXT_2 = tools/wispr$(EXEEXT)
+@TOOLS_TRUE@am__EXEEXT_3 = tools/supplicant-test$(EXEEXT) \
 @TOOLS_TRUE@   tools/dhcp-test$(EXEEXT) \
 @TOOLS_TRUE@   tools/dhcp-server-test$(EXEEXT) \
 @TOOLS_TRUE@   tools/addr-test$(EXEEXT) tools/web-test$(EXEEXT) \
@@ -301,9 +323,9 @@ scripts_libppp_plugin_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
 @TOOLS_TRUE@   tools/private-network-test$(EXEEXT) \
 @TOOLS_TRUE@   unit/test-session$(EXEEXT) \
 @TOOLS_TRUE@   unit/test-ippool$(EXEEXT) unit/test-nat$(EXEEXT)
-@OPENCONNECT_TRUE@am__EXEEXT_3 = scripts/openconnect-script$(EXEEXT)
-@OPENCONNECT_FALSE@@VPNC_TRUE@am__EXEEXT_4 = scripts/openconnect-script$(EXEEXT)
-@OPENVPN_TRUE@am__EXEEXT_5 = scripts/openvpn-script$(EXEEXT)
+@OPENCONNECT_TRUE@am__EXEEXT_4 = scripts/openconnect-script$(EXEEXT)
+@OPENCONNECT_FALSE@@VPNC_TRUE@am__EXEEXT_5 = scripts/openconnect-script$(EXEEXT)
+@OPENVPN_TRUE@am__EXEEXT_6 = scripts/openvpn-script$(EXEEXT)
 PROGRAMS = $(noinst_PROGRAMS) $(sbin_PROGRAMS) $(script_PROGRAMS)
 am__client_cm_SOURCES_DIST = client/main.c
 @CLIENT_TRUE@am_client_cm_OBJECTS = client/main.$(OBJEXT)
@@ -321,86 +343,91 @@ am__src_connmand_SOURCES_DIST = gdbus/gdbus.h gdbus/mainloop.c \
        gdhcp/common.h gdhcp/common.c gdhcp/client.c gdhcp/server.c \
        gdhcp/ipv4ll.h gdhcp/ipv4ll.c gweb/gweb.h gweb/gweb.c \
        gweb/gresolv.h gweb/gresolv.c gweb/giognutls.h \
-       gweb/giognutls.c plugins/loopback.c plugins/ethernet.c \
-       plugins/wifi.c gsupplicant/gsupplicant.h gsupplicant/dbus.h \
-       gsupplicant/supplicant.c gsupplicant/dbus.c \
+       gweb/giognutls.c gweb/gionotls.c plugins/loopback.c \
+       plugins/ethernet.c plugins/wifi.c gsupplicant/gsupplicant.h \
+       gsupplicant/dbus.h gsupplicant/supplicant.c gsupplicant/dbus.c \
        plugins/bluetooth.c plugins/hh2serial-gps.c plugins/mcc.h \
-       plugins/ofono.c plugins/openconnect.c plugins/openvpn.c \
-       plugins/vpnc.c plugins/l2tp.c plugins/pptp.c plugins/vpn.c \
-       plugins/vpn.h plugins/pacrunner.c plugins/polkit.c \
-       plugins/nmcompat.c plugins/tist.c src/connman.ver src/main.c \
-       src/connman.h src/log.c src/error.c src/plugin.c src/task.c \
-       src/device.c src/network.c src/connection.c src/manager.c \
-       src/service.c src/clock.c src/timezone.c src/agent.c \
-       src/notifier.c src/provider.c src/resolver.c src/ipconfig.c \
-       src/detect.c src/inet.c src/dhcp.c src/dhcpv6.c src/rtnl.c \
-       src/proxy.c src/utsname.c src/timeserver.c src/rfkill.c \
-       src/storage.c src/dbus.c src/config.c src/technology.c \
-       src/counter.c src/ntp.c src/session.c src/tethering.c \
-       src/wpad.c src/wispr.c src/stats.c src/iptables.c \
-       src/dnsproxy.c src/6to4.c src/ippool.c src/bridge.c src/nat.c
+       plugins/ofono.c plugins/dundee.c plugins/openconnect.c \
+       plugins/openvpn.c plugins/vpnc.c plugins/l2tp.c plugins/pptp.c \
+       plugins/vpn.c plugins/vpn.h plugins/pacrunner.c \
+       plugins/polkit.c plugins/nmcompat.c plugins/tist.c \
+       src/connman.ver src/main.c src/connman.h src/log.c src/error.c \
+       src/plugin.c src/task.c src/device.c src/network.c \
+       src/connection.c src/manager.c src/service.c src/clock.c \
+       src/timezone.c src/agent.c src/notifier.c src/provider.c \
+       src/resolver.c src/ipconfig.c src/detect.c src/inet.c \
+       src/dhcp.c src/dhcpv6.c src/rtnl.c src/proxy.c src/utsname.c \
+       src/timeserver.c src/rfkill.c src/storage.c src/dbus.c \
+       src/config.c src/technology.c src/counter.c src/ntp.c \
+       src/session.c src/tethering.c src/wpad.c src/wispr.c \
+       src/stats.c src/iptables.c src/dnsproxy.c src/6to4.c \
+       src/ippool.c src/bridge.c src/nat.c
 am__objects_1 = gdbus/mainloop.$(OBJEXT) gdbus/watch.$(OBJEXT) \
        gdbus/object.$(OBJEXT) gdbus/polkit.$(OBJEXT)
 am__objects_2 = gdhcp/common.$(OBJEXT) gdhcp/client.$(OBJEXT) \
        gdhcp/server.$(OBJEXT) gdhcp/ipv4ll.$(OBJEXT)
-@LOOPBACK_TRUE@am__objects_3 = plugins/loopback.$(OBJEXT)
-@ETHERNET_TRUE@am__objects_4 = plugins/ethernet.$(OBJEXT)
-am__objects_5 = gsupplicant/supplicant.$(OBJEXT) \
+@WISPR_TRUE@am__objects_3 = gweb/giognutls.$(OBJEXT)
+@WISPR_FALSE@am__objects_4 = gweb/gionotls.$(OBJEXT)
+am__objects_5 = gweb/gweb.$(OBJEXT) gweb/gresolv.$(OBJEXT) \
+       $(am__objects_3) $(am__objects_4)
+@LOOPBACK_TRUE@am__objects_6 = plugins/loopback.$(OBJEXT)
+@ETHERNET_TRUE@am__objects_7 = plugins/ethernet.$(OBJEXT)
+am__objects_8 = gsupplicant/supplicant.$(OBJEXT) \
        gsupplicant/dbus.$(OBJEXT)
-@WIFI_TRUE@am__objects_6 = plugins/wifi.$(OBJEXT) $(am__objects_5)
-@BLUETOOTH_TRUE@am__objects_7 = plugins/bluetooth.$(OBJEXT)
-@HH2SERIAL_GPS_BUILTIN_TRUE@@HH2SERIAL_GPS_TRUE@am__objects_8 = plugins/hh2serial-gps.$(OBJEXT)
-@OFONO_TRUE@am__objects_9 = plugins/ofono.$(OBJEXT)
-@OPENCONNECT_BUILTIN_TRUE@@OPENCONNECT_TRUE@am__objects_10 = plugins/openconnect.$(OBJEXT)
-@OPENVPN_BUILTIN_TRUE@@OPENVPN_TRUE@am__objects_11 =  \
+@WIFI_TRUE@am__objects_9 = plugins/wifi.$(OBJEXT) $(am__objects_8)
+@BLUETOOTH_TRUE@am__objects_10 = plugins/bluetooth.$(OBJEXT)
+@HH2SERIAL_GPS_BUILTIN_TRUE@@HH2SERIAL_GPS_TRUE@am__objects_11 = plugins/hh2serial-gps.$(OBJEXT)
+@OFONO_TRUE@am__objects_12 = plugins/ofono.$(OBJEXT)
+@DUNDEE_TRUE@am__objects_13 = plugins/dundee.$(OBJEXT)
+@OPENCONNECT_BUILTIN_TRUE@@OPENCONNECT_TRUE@am__objects_14 = plugins/openconnect.$(OBJEXT)
+@OPENVPN_BUILTIN_TRUE@@OPENVPN_TRUE@am__objects_15 =  \
 @OPENVPN_BUILTIN_TRUE@@OPENVPN_TRUE@   plugins/openvpn.$(OBJEXT)
-@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_12 = plugins/vpnc.$(OBJEXT)
-@L2TP_BUILTIN_TRUE@@L2TP_TRUE@am__objects_13 = plugins/l2tp.$(OBJEXT)
-@PPTP_BUILTIN_TRUE@@PPTP_TRUE@am__objects_14 = plugins/pptp.$(OBJEXT)
-@L2TP_BUILTIN_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_BUILTIN_FALSE@@PPTP_BUILTIN_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_BUILTIN_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_BUILTIN_FALSE@@PPTP_BUILTIN_TRUE@@PPTP_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_BUILTIN_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_BUILTIN_FALSE@@PPTP_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_BUILTIN_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_BUILTIN_TRUE@@OPENVPN_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_BUILTIN_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_FALSE@@PPTP_BUILTIN_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_BUILTIN_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_FALSE@@PPTP_BUILTIN_TRUE@@PPTP_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_BUILTIN_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_FALSE@@PPTP_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_BUILTIN_FALSE@@OPENCONNECT_BUILTIN_TRUE@@OPENCONNECT_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_BUILTIN_FALSE@@OPENCONNECT_FALSE@@OPENVPN_BUILTIN_FALSE@@PPTP_BUILTIN_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_BUILTIN_FALSE@@OPENCONNECT_FALSE@@OPENVPN_BUILTIN_FALSE@@PPTP_BUILTIN_TRUE@@PPTP_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_BUILTIN_FALSE@@OPENCONNECT_FALSE@@OPENVPN_BUILTIN_FALSE@@PPTP_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_BUILTIN_FALSE@@OPENCONNECT_FALSE@@OPENVPN_BUILTIN_TRUE@@OPENVPN_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_BUILTIN_FALSE@@OPENCONNECT_FALSE@@OPENVPN_FALSE@@PPTP_BUILTIN_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_BUILTIN_FALSE@@OPENCONNECT_FALSE@@OPENVPN_FALSE@@PPTP_BUILTIN_TRUE@@PPTP_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_BUILTIN_FALSE@@OPENCONNECT_FALSE@@OPENVPN_FALSE@@PPTP_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_BUILTIN_TRUE@@L2TP_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_BUILTIN_FALSE@@PPTP_BUILTIN_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_BUILTIN_FALSE@@PPTP_BUILTIN_TRUE@@PPTP_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_BUILTIN_FALSE@@PPTP_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_BUILTIN_TRUE@@OPENVPN_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_FALSE@@PPTP_BUILTIN_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_FALSE@@PPTP_BUILTIN_TRUE@@PPTP_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_FALSE@@PPTP_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_FALSE@@OPENCONNECT_BUILTIN_TRUE@@OPENCONNECT_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_FALSE@@OPENCONNECT_FALSE@@OPENVPN_BUILTIN_FALSE@@PPTP_BUILTIN_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_FALSE@@OPENCONNECT_FALSE@@OPENVPN_BUILTIN_FALSE@@PPTP_BUILTIN_TRUE@@PPTP_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_FALSE@@OPENCONNECT_FALSE@@OPENVPN_BUILTIN_FALSE@@PPTP_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_FALSE@@OPENCONNECT_FALSE@@OPENVPN_BUILTIN_TRUE@@OPENVPN_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_FALSE@@OPENCONNECT_FALSE@@OPENVPN_FALSE@@PPTP_BUILTIN_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_FALSE@@OPENCONNECT_FALSE@@OPENVPN_FALSE@@PPTP_BUILTIN_TRUE@@PPTP_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@L2TP_FALSE@@OPENCONNECT_FALSE@@OPENVPN_FALSE@@PPTP_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_15 = plugins/vpn.$(OBJEXT)
-@PACRUNNER_TRUE@am__objects_16 = plugins/pacrunner.$(OBJEXT)
-@POLKIT_TRUE@am__objects_17 = plugins/polkit.$(OBJEXT)
-@NMCOMPAT_TRUE@am__objects_18 = plugins/nmcompat.$(OBJEXT)
-@TIST_BUILTIN_TRUE@@TIST_TRUE@am__objects_19 = plugins/tist.$(OBJEXT)
-am__objects_20 = $(am__objects_3) $(am__objects_4) $(am__objects_6) \
-       $(am__objects_7) $(am__objects_8) $(am__objects_9) \
+@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_16 = plugins/vpnc.$(OBJEXT)
+@L2TP_BUILTIN_TRUE@@L2TP_TRUE@am__objects_17 = plugins/l2tp.$(OBJEXT)
+@PPTP_BUILTIN_TRUE@@PPTP_TRUE@am__objects_18 = plugins/pptp.$(OBJEXT)
+@L2TP_BUILTIN_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_BUILTIN_FALSE@@PPTP_BUILTIN_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_BUILTIN_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_BUILTIN_FALSE@@PPTP_BUILTIN_TRUE@@PPTP_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_BUILTIN_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_BUILTIN_FALSE@@PPTP_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_BUILTIN_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_BUILTIN_TRUE@@OPENVPN_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_BUILTIN_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_FALSE@@PPTP_BUILTIN_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_BUILTIN_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_FALSE@@PPTP_BUILTIN_TRUE@@PPTP_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_BUILTIN_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_FALSE@@PPTP_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_BUILTIN_FALSE@@OPENCONNECT_BUILTIN_TRUE@@OPENCONNECT_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_BUILTIN_FALSE@@OPENCONNECT_FALSE@@OPENVPN_BUILTIN_FALSE@@PPTP_BUILTIN_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_BUILTIN_FALSE@@OPENCONNECT_FALSE@@OPENVPN_BUILTIN_FALSE@@PPTP_BUILTIN_TRUE@@PPTP_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_BUILTIN_FALSE@@OPENCONNECT_FALSE@@OPENVPN_BUILTIN_FALSE@@PPTP_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_BUILTIN_FALSE@@OPENCONNECT_FALSE@@OPENVPN_BUILTIN_TRUE@@OPENVPN_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_BUILTIN_FALSE@@OPENCONNECT_FALSE@@OPENVPN_FALSE@@PPTP_BUILTIN_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_BUILTIN_FALSE@@OPENCONNECT_FALSE@@OPENVPN_FALSE@@PPTP_BUILTIN_TRUE@@PPTP_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_BUILTIN_FALSE@@OPENCONNECT_FALSE@@OPENVPN_FALSE@@PPTP_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_BUILTIN_TRUE@@L2TP_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_BUILTIN_FALSE@@PPTP_BUILTIN_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_BUILTIN_FALSE@@PPTP_BUILTIN_TRUE@@PPTP_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_BUILTIN_FALSE@@PPTP_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_BUILTIN_TRUE@@OPENVPN_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_FALSE@@PPTP_BUILTIN_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_FALSE@@PPTP_BUILTIN_TRUE@@PPTP_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_FALSE@@OPENCONNECT_BUILTIN_FALSE@@OPENVPN_FALSE@@PPTP_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_FALSE@@OPENCONNECT_BUILTIN_TRUE@@OPENCONNECT_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_FALSE@@OPENCONNECT_FALSE@@OPENVPN_BUILTIN_FALSE@@PPTP_BUILTIN_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_FALSE@@OPENCONNECT_FALSE@@OPENVPN_BUILTIN_FALSE@@PPTP_BUILTIN_TRUE@@PPTP_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_FALSE@@OPENCONNECT_FALSE@@OPENVPN_BUILTIN_FALSE@@PPTP_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_FALSE@@OPENCONNECT_FALSE@@OPENVPN_BUILTIN_TRUE@@OPENVPN_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_FALSE@@OPENCONNECT_FALSE@@OPENVPN_FALSE@@PPTP_BUILTIN_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_FALSE@@OPENCONNECT_FALSE@@OPENVPN_FALSE@@PPTP_BUILTIN_TRUE@@PPTP_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@L2TP_FALSE@@OPENCONNECT_FALSE@@OPENVPN_FALSE@@PPTP_FALSE@@VPNC_BUILTIN_TRUE@@VPNC_TRUE@am__objects_19 = plugins/vpn.$(OBJEXT)
+@PACRUNNER_TRUE@am__objects_20 = plugins/pacrunner.$(OBJEXT)
+@POLKIT_TRUE@am__objects_21 = plugins/polkit.$(OBJEXT)
+@NMCOMPAT_TRUE@am__objects_22 = plugins/nmcompat.$(OBJEXT)
+@TIST_BUILTIN_TRUE@@TIST_TRUE@am__objects_23 = plugins/tist.$(OBJEXT)
+am__objects_24 = $(am__objects_6) $(am__objects_7) $(am__objects_9) \
        $(am__objects_10) $(am__objects_11) $(am__objects_12) \
        $(am__objects_13) $(am__objects_14) $(am__objects_15) \
        $(am__objects_16) $(am__objects_17) $(am__objects_18) \
-       $(am__objects_19)
+       $(am__objects_19) $(am__objects_20) $(am__objects_21) \
+       $(am__objects_22) $(am__objects_23)
 am_src_connmand_OBJECTS = $(am__objects_1) $(am__objects_2) \
-       gweb/gweb.$(OBJEXT) gweb/gresolv.$(OBJEXT) \
-       gweb/giognutls.$(OBJEXT) $(am__objects_20) src/main.$(OBJEXT) \
+       $(am__objects_5) $(am__objects_24) src/main.$(OBJEXT) \
        src/log.$(OBJEXT) src/error.$(OBJEXT) src/plugin.$(OBJEXT) \
        src/task.$(OBJEXT) src/device.$(OBJEXT) src/network.$(OBJEXT) \
        src/connection.$(OBJEXT) src/manager.$(OBJEXT) \
@@ -481,17 +508,16 @@ tools_tap_test_OBJECTS = tools/tap-test.$(OBJEXT)
 tools_tap_test_LDADD = $(LDADD)
 am__tools_web_test_SOURCES_DIST = gweb/gweb.h gweb/gweb.c \
        gweb/gresolv.h gweb/gresolv.c gweb/giognutls.h \
-       gweb/giognutls.c tools/web-test.c
-am__objects_21 = gweb/gweb.$(OBJEXT) gweb/gresolv.$(OBJEXT) \
-       gweb/giognutls.$(OBJEXT)
-@TOOLS_TRUE@am_tools_web_test_OBJECTS = $(am__objects_21) \
+       gweb/giognutls.c gweb/gionotls.c tools/web-test.c
+@TOOLS_TRUE@am_tools_web_test_OBJECTS = $(am__objects_5) \
 @TOOLS_TRUE@   tools/web-test.$(OBJEXT)
 tools_web_test_OBJECTS = $(am_tools_web_test_OBJECTS)
 tools_web_test_DEPENDENCIES =
 am__tools_wispr_SOURCES_DIST = gweb/gweb.h gweb/gweb.c gweb/gresolv.h \
-       gweb/gresolv.c gweb/giognutls.h gweb/giognutls.c tools/wispr.c
-@TOOLS_TRUE@am_tools_wispr_OBJECTS = $(am__objects_21) \
-@TOOLS_TRUE@   tools/wispr.$(OBJEXT)
+       gweb/gresolv.c gweb/giognutls.h gweb/giognutls.c \
+       gweb/gionotls.c tools/wispr.c
+@WISPR_TRUE@am_tools_wispr_OBJECTS = $(am__objects_5) \
+@WISPR_TRUE@   tools/wispr.$(OBJEXT)
 tools_wispr_OBJECTS = $(am_tools_wispr_OBJECTS)
 tools_wispr_DEPENDENCIES =
 am__tools_wpad_test_SOURCES_DIST = gweb/gresolv.h gweb/gresolv.c \
@@ -592,6 +618,11 @@ DIST_SOURCES = plugins/hh2serial-gps.c plugins/iospm.c \
        $(am__unit_test_ippool_SOURCES_DIST) \
        $(am__unit_test_nat_SOURCES_DIST) \
        $(am__unit_test_session_SOURCES_DIST)
+am__can_run_installinfo = \
+  case $$AM_UPDATE_INFO_DIR in \
+    n|no|NO) false;; \
+    *) (install-info --version) >/dev/null 2>&1;; \
+  esac
 DATA = $(dbusconf_DATA) $(pkgconfig_DATA) $(policy_DATA) \
        $(script_DATA) $(systemdunit_DATA)
 HEADERS = $(include_HEADERS) $(nodist_include_HEADERS) \
@@ -780,39 +811,36 @@ gdhcp_sources = gdhcp/gdhcp.h gdhcp/common.h gdhcp/common.c gdhcp/client.c \
                gdhcp/server.c gdhcp/ipv4ll.h gdhcp/ipv4ll.c
 
 gweb_sources = gweb/gweb.h gweb/gweb.c gweb/gresolv.h gweb/gresolv.c \
-                                       gweb/giognutls.h gweb/giognutls.c
-
+       $(am__append_1) $(am__append_2)
 @DATAFILES_TRUE@@NMCOMPAT_TRUE@nmcompat_conf = plugins/connman-nmcompat.conf
 @DATAFILES_TRUE@dbusconfdir = @DBUS_CONFDIR@
 @DATAFILES_TRUE@dbusconf_DATA = src/connman.conf $(nmcompat_conf)
 @DATAFILES_TRUE@@SYSTEMD_TRUE@systemdunitdir = @SYSTEMD_UNITDIR@
 @DATAFILES_TRUE@@SYSTEMD_TRUE@systemdunit_DATA = src/connman.service
-plugin_LTLIBRARIES = $(am__append_11) $(am__append_18) \
-       $(am__append_23) $(am__append_28) $(am__append_33) \
-       $(am__append_38) $(am__append_46) $(am__append_48) \
-       $(am__append_57)
-plugin_objects = $(am__append_12) $(am__append_19) $(am__append_24) \
+plugin_LTLIBRARIES = $(am__append_13) $(am__append_22) \
+       $(am__append_27) $(am__append_32) $(am__append_37) \
+       $(am__append_42) $(am__append_50) $(am__append_52) \
+       $(am__append_61)
+plugin_objects = $(am__append_14) $(am__append_23) $(am__append_28) \
+       $(am__append_33) $(am__append_38) $(am__append_43) \
+       $(am__append_51) $(am__append_53) $(am__append_62)
+builtin_modules = $(am__append_3) $(am__append_5) $(am__append_7) \
+       $(am__append_9) $(am__append_11) $(am__append_15) \
+       $(am__append_17) $(am__append_19) $(am__append_24) \
        $(am__append_29) $(am__append_34) $(am__append_39) \
-       $(am__append_47) $(am__append_49) $(am__append_58)
-builtin_modules = $(am__append_1) $(am__append_3) $(am__append_5) \
-       $(am__append_7) $(am__append_9) $(am__append_13) \
-       $(am__append_15) $(am__append_20) $(am__append_25) \
-       $(am__append_30) $(am__append_35) $(am__append_42) \
-       $(am__append_44) $(am__append_53) $(am__append_55)
-builtin_sources = $(am__append_2) $(am__append_4) $(am__append_6) \
-       $(am__append_8) $(am__append_10) $(am__append_14) \
-       $(am__append_16) $(am__append_21) $(am__append_26) \
-       $(am__append_31) $(am__append_36) $(builtin_vpn_sources) \
-       $(am__append_43) $(am__append_45) $(am__append_54) \
-       $(am__append_56)
+       $(am__append_46) $(am__append_48) $(am__append_57) \
+       $(am__append_59)
+builtin_sources = $(am__append_4) $(am__append_6) $(am__append_8) \
+       $(am__append_10) $(am__append_12) $(am__append_16) \
+       $(am__append_18) $(am__append_20) $(am__append_25) \
+       $(am__append_30) $(am__append_35) $(am__append_40) \
+       $(builtin_vpn_sources) $(am__append_47) $(am__append_49) \
+       $(am__append_58) $(am__append_60)
 builtin_libadd = 
-builtin_cflags = $(am__append_17) $(am__append_22) $(am__append_27) \
-       $(am__append_32) $(am__append_37)
-unit_objects = $(am__append_61)
-src_connmand_SOURCES = $(gdbus_sources) $(gdhcp_sources) \
-                       gweb/gweb.h gweb/gweb.c \
-                       gweb/gresolv.h gweb/gresolv.c \
-                       gweb/giognutls.h gweb/giognutls.c \
+builtin_cflags = $(am__append_21) $(am__append_26) $(am__append_31) \
+       $(am__append_36) $(am__append_41)
+unit_objects = $(am__append_66)
+src_connmand_SOURCES = $(gdbus_sources) $(gdhcp_sources) $(gweb_sources) \
                        $(builtin_sources) src/connman.ver \
                        src/main.c src/connman.h src/log.c \
                        src/error.c src/plugin.c src/task.c \
@@ -858,15 +886,15 @@ AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @XTABLES_CFLAGS@ \
 INCLUDES = -I$(builddir)/include -I$(builddir)/src -I$(srcdir)/gdbus
 EXTRA_DIST = src/genbuiltin src/connman-dbus.conf \
        src/connman-polkit.conf plugins/connman-nmcompat.conf \
-       gweb/gionotls.c plugins/polkit.policy $(test_scripts) \
-       doc/overview-api.txt doc/behavior-api.txt doc/ipconfig-api.txt \
-       doc/plugin-api.txt doc/manager-api.txt doc/agent-api.txt \
-       doc/service-api.txt doc/technology-api.txt doc/counter-api.txt \
+       plugins/polkit.policy $(test_scripts) doc/overview-api.txt \
+       doc/behavior-api.txt doc/ipconfig-api.txt doc/plugin-api.txt \
+       doc/manager-api.txt doc/agent-api.txt doc/service-api.txt \
+       doc/technology-api.txt doc/counter-api.txt \
        doc/config-format.txt doc/clock-api.txt doc/session-api.txt \
        doc/session-overview.txt doc/backtrace.txt \
        doc/advanced-configuration.txt
 script_DATA = 
-script_LTLIBRARIES = $(am__append_40) $(am__append_41)
+script_LTLIBRARIES = $(am__append_44) $(am__append_45)
 plugin_cflags = -fvisibility=hidden -I$(srcdir)/gdbus \
                                        @DBUS_CFLAGS@ @GLIB_CFLAGS@
 
@@ -944,8 +972,8 @@ gsupplicant_sources = gsupplicant/gsupplicant.h gsupplicant/dbus.h \
 @TIST_BUILTIN_FALSE@@TIST_TRUE@plugins_tist_la_LDFLAGS = $(plugin_ldflags)
 @CLIENT_TRUE@client_cm_SOURCES = client/main.c
 @CLIENT_TRUE@client_cm_LDADD = @DBUS_LIBS@
-@TOOLS_TRUE@tools_wispr_SOURCES = $(gweb_sources) tools/wispr.c
-@TOOLS_TRUE@tools_wispr_LDADD = @GLIB_LIBS@ @GNUTLS_LIBS@ -lresolv
+@WISPR_TRUE@tools_wispr_SOURCES = $(gweb_sources) tools/wispr.c
+@WISPR_TRUE@tools_wispr_LDADD = @GLIB_LIBS@ @GNUTLS_LIBS@ -lresolv
 @TOOLS_TRUE@tools_supplicant_test_SOURCES = $(gdbus_sources) tools/supplicant-test.c \
 @TOOLS_TRUE@                   tools/supplicant-dbus.h tools/supplicant-dbus.c \
 @TOOLS_TRUE@                   tools/supplicant.h tools/supplicant.c
@@ -1078,7 +1106,6 @@ connman.pc: $(top_builddir)/config.status $(srcdir)/connman.pc.in
        cd $(top_builddir) && $(SHELL) ./config.status $@
 install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
        @$(NORMAL_INSTALL)
-       test -z "$(plugindir)" || $(MKDIR_P) "$(DESTDIR)$(plugindir)"
        @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
        list2=; for p in $$list; do \
          if test -f $$p; then \
@@ -1086,6 +1113,8 @@ install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
          else :; fi; \
        done; \
        test -z "$$list2" || { \
+         echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \
          echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
          $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
        }
@@ -1109,7 +1138,6 @@ clean-pluginLTLIBRARIES:
        done
 install-scriptLTLIBRARIES: $(script_LTLIBRARIES)
        @$(NORMAL_INSTALL)
-       test -z "$(scriptdir)" || $(MKDIR_P) "$(DESTDIR)$(scriptdir)"
        @list='$(script_LTLIBRARIES)'; test -n "$(scriptdir)" || list=; \
        list2=; for p in $$list; do \
          if test -f $$p; then \
@@ -1117,6 +1145,8 @@ install-scriptLTLIBRARIES: $(script_LTLIBRARIES)
          else :; fi; \
        done; \
        test -z "$$list2" || { \
+         echo " $(MKDIR_P) '$(DESTDIR)$(scriptdir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(scriptdir)" || exit 1; \
          echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(scriptdir)'"; \
          $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(scriptdir)"; \
        }
@@ -1213,8 +1243,11 @@ clean-noinstPROGRAMS:
        rm -f $$list
 install-sbinPROGRAMS: $(sbin_PROGRAMS)
        @$(NORMAL_INSTALL)
-       test -z "$(sbindir)" || $(MKDIR_P) "$(DESTDIR)$(sbindir)"
        @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \
+       fi; \
        for p in $$list; do echo "$$p $$p"; done | \
        sed 's/$(EXEEXT)$$//' | \
        while read p p1; do if test -f $$p || test -f $$p1; \
@@ -1256,8 +1289,11 @@ clean-sbinPROGRAMS:
        rm -f $$list
 install-scriptPROGRAMS: $(script_PROGRAMS)
        @$(NORMAL_INSTALL)
-       test -z "$(scriptdir)" || $(MKDIR_P) "$(DESTDIR)$(scriptdir)"
        @list='$(script_PROGRAMS)'; test -n "$(scriptdir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(scriptdir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(scriptdir)" || exit 1; \
+       fi; \
        for p in $$list; do echo "$$p $$p"; done | \
        sed 's/$(EXEEXT)$$//' | \
        while read p p1; do if test -f $$p || test -f $$p1; \
@@ -1358,6 +1394,8 @@ gweb/gresolv.$(OBJEXT): gweb/$(am__dirstamp) \
        gweb/$(DEPDIR)/$(am__dirstamp)
 gweb/giognutls.$(OBJEXT): gweb/$(am__dirstamp) \
        gweb/$(DEPDIR)/$(am__dirstamp)
+gweb/gionotls.$(OBJEXT): gweb/$(am__dirstamp) \
+       gweb/$(DEPDIR)/$(am__dirstamp)
 plugins/loopback.$(OBJEXT): plugins/$(am__dirstamp) \
        plugins/$(DEPDIR)/$(am__dirstamp)
 plugins/ethernet.$(OBJEXT): plugins/$(am__dirstamp) \
@@ -1380,6 +1418,8 @@ plugins/hh2serial-gps.$(OBJEXT): plugins/$(am__dirstamp) \
        plugins/$(DEPDIR)/$(am__dirstamp)
 plugins/ofono.$(OBJEXT): plugins/$(am__dirstamp) \
        plugins/$(DEPDIR)/$(am__dirstamp)
+plugins/dundee.$(OBJEXT): plugins/$(am__dirstamp) \
+       plugins/$(DEPDIR)/$(am__dirstamp)
 plugins/openconnect.$(OBJEXT): plugins/$(am__dirstamp) \
        plugins/$(DEPDIR)/$(am__dirstamp)
 plugins/openvpn.$(OBJEXT): plugins/$(am__dirstamp) \
@@ -1587,8 +1627,11 @@ unit/test-session$(EXEEXT): $(unit_test_session_OBJECTS) $(unit_test_session_DEP
        $(AM_V_CCLD)$(LINK) $(unit_test_session_OBJECTS) $(unit_test_session_LDADD) $(LIBS)
 install-testSCRIPTS: $(test_SCRIPTS)
        @$(NORMAL_INSTALL)
-       test -z "$(testdir)" || $(MKDIR_P) "$(DESTDIR)$(testdir)"
        @list='$(test_SCRIPTS)'; test -n "$(testdir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(testdir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(testdir)" || exit 1; \
+       fi; \
        for p in $$list; do \
          if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
          if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \
@@ -1632,9 +1675,11 @@ mostlyclean-compile:
        -rm -f gsupplicant/dbus.$(OBJEXT)
        -rm -f gsupplicant/supplicant.$(OBJEXT)
        -rm -f gweb/giognutls.$(OBJEXT)
+       -rm -f gweb/gionotls.$(OBJEXT)
        -rm -f gweb/gresolv.$(OBJEXT)
        -rm -f gweb/gweb.$(OBJEXT)
        -rm -f plugins/bluetooth.$(OBJEXT)
+       -rm -f plugins/dundee.$(OBJEXT)
        -rm -f plugins/ethernet.$(OBJEXT)
        -rm -f plugins/hh2serial-gps.$(OBJEXT)
        -rm -f plugins/l2tp.$(OBJEXT)
@@ -1765,9 +1810,11 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@gsupplicant/$(DEPDIR)/dbus.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@gsupplicant/$(DEPDIR)/supplicant.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@gweb/$(DEPDIR)/giognutls.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@gweb/$(DEPDIR)/gionotls.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@gweb/$(DEPDIR)/gresolv.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@gweb/$(DEPDIR)/gweb.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/bluetooth.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/dundee.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/ethernet.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/hh2serial-gps.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/l2tp.Po@am__quote@
@@ -2012,8 +2059,11 @@ distclean-libtool:
        -rm -f libtool config.lt
 install-dbusconfDATA: $(dbusconf_DATA)
        @$(NORMAL_INSTALL)
-       test -z "$(dbusconfdir)" || $(MKDIR_P) "$(DESTDIR)$(dbusconfdir)"
        @list='$(dbusconf_DATA)'; test -n "$(dbusconfdir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(dbusconfdir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(dbusconfdir)" || exit 1; \
+       fi; \
        for p in $$list; do \
          if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
          echo "$$d$$p"; \
@@ -2030,8 +2080,11 @@ uninstall-dbusconfDATA:
        dir='$(DESTDIR)$(dbusconfdir)'; $(am__uninstall_files_from_dir)
 install-pkgconfigDATA: $(pkgconfig_DATA)
        @$(NORMAL_INSTALL)
-       test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)"
        @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \
+       fi; \
        for p in $$list; do \
          if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
          echo "$$d$$p"; \
@@ -2048,8 +2101,11 @@ uninstall-pkgconfigDATA:
        dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir)
 install-policyDATA: $(policy_DATA)
        @$(NORMAL_INSTALL)
-       test -z "$(policydir)" || $(MKDIR_P) "$(DESTDIR)$(policydir)"
        @list='$(policy_DATA)'; test -n "$(policydir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(policydir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(policydir)" || exit 1; \
+       fi; \
        for p in $$list; do \
          if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
          echo "$$d$$p"; \
@@ -2066,8 +2122,11 @@ uninstall-policyDATA:
        dir='$(DESTDIR)$(policydir)'; $(am__uninstall_files_from_dir)
 install-scriptDATA: $(script_DATA)
        @$(NORMAL_INSTALL)
-       test -z "$(scriptdir)" || $(MKDIR_P) "$(DESTDIR)$(scriptdir)"
        @list='$(script_DATA)'; test -n "$(scriptdir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(scriptdir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(scriptdir)" || exit 1; \
+       fi; \
        for p in $$list; do \
          if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
          echo "$$d$$p"; \
@@ -2084,8 +2143,11 @@ uninstall-scriptDATA:
        dir='$(DESTDIR)$(scriptdir)'; $(am__uninstall_files_from_dir)
 install-systemdunitDATA: $(systemdunit_DATA)
        @$(NORMAL_INSTALL)
-       test -z "$(systemdunitdir)" || $(MKDIR_P) "$(DESTDIR)$(systemdunitdir)"
        @list='$(systemdunit_DATA)'; test -n "$(systemdunitdir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(systemdunitdir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(systemdunitdir)" || exit 1; \
+       fi; \
        for p in $$list; do \
          if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
          echo "$$d$$p"; \
@@ -2102,8 +2164,11 @@ uninstall-systemdunitDATA:
        dir='$(DESTDIR)$(systemdunitdir)'; $(am__uninstall_files_from_dir)
 install-includeHEADERS: $(include_HEADERS)
        @$(NORMAL_INSTALL)
-       test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
        @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \
+       fi; \
        for p in $$list; do \
          if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
          echo "$$d$$p"; \
@@ -2120,8 +2185,11 @@ uninstall-includeHEADERS:
        dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir)
 install-nodist_includeHEADERS: $(nodist_include_HEADERS)
        @$(NORMAL_INSTALL)
-       test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
        @list='$(nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \
+       if test -n "$$list"; then \
+         echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \
+         $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \
+       fi; \
        for p in $$list; do \
          if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
          echo "$$d$$p"; \
index 9018d31..f959152 100644 (file)
@@ -46,6 +46,11 @@ builtin_modules += ofono
 builtin_sources += plugins/mcc.h plugins/ofono.c
 endif
 
+if DUNDEE
+builtin_modules += dundee
+builtin_sources += plugins/dundee.c
+endif
+
 if OPENCONNECT
 if OPENCONNECT_BUILTIN
 builtin_modules += openconnect
diff --git a/README b/README
index 11d40ff..6215e96 100644 (file)
--- a/README
+++ b/README
@@ -39,8 +39,8 @@ In order to compile Connection Manager you need following software packages:
        - GCC compiler
        - GLib library
        - D-Bus library
-       - GnuTLS library
        - IP-Tables library
+       - GnuTLS library (optional)
        - PolicyKit (optional)
 
 To configure run:
@@ -52,21 +52,6 @@ To compile and install run:
        make && make install
 
 
-VPN
-===
-
-In order to compile pptp and l2tp VPN plugins, you need ppp development
-package.
-
-To run l2tp you will need
-       - xl2tpd, http://www.xelerance.com/services/software/xl2tpd
-
-To run pptp you will need
-       - pptp client, http://pptpclient.sourceforge.net
-
-Both l2tp and pptp also need pppd.
-
-
 Configuration and options
 =========================
 
@@ -103,7 +88,7 @@ For a working system, certain configuration options need to be enabled:
 
                It is safe to build a daemon with Bluetooth support and no
                running bluetoothd. The start of bluetoothd is automatically
-               detected and only a runtime depedency. It is not needed to
+               detected and only a runtime dependency. It is not needed to
                build ConnMan.
 
        --disable-ofono
@@ -116,7 +101,20 @@ For a working system, certain configuration options need to be enabled:
 
                It is safe to build a daemon with oFono support and no
                running ofonod. That start of ofonod is automatically
-               detected and only a runtime dependecy. It is not needed to
+               detected and only a runtime dependency. It is not needed to
+               build ConnMan.
+
+       --disable-dundee
+
+               Disable support for Bluetooth DUN devices
+
+               By default Bluetooth DUN technology (dundee) support is
+               built-in and enabled. This option can be used to build a
+               small daemon for a specific system where dundee is not used.
+
+               It is safe to build a daemon with dundee support and no
+               running dundee. That start of dundee is automatically
+               detected and only a runtime dependency. It is not needed to
                build ConnMan.
 
        --disable-pacrunner
@@ -144,6 +142,24 @@ For a working system, certain configuration options need to be enabled:
                scripts are in place. It detects an already configured
                loopback device and leaves it as it is.
 
+       --disable-wispr
+
+               Disable support for WISPr hotspot logins
+
+               For systems with really minimal memory requirements, this
+               will disable the support for WISPr hotspot logins. The code
+               for WISPr will be still compiled into the daemon, but its
+               requirement on GnuTLS for secure connections will be lifted.
+
+               The missing GnuTLS support shrinks the memory requirements
+               by about 30% and for systems that are more stationary and do
+               not log into hotspots this might be a better trade off.
+
+               Disabling WISPr support is not disabling the portal detection
+               support. A portal will still be detected, but instead of being
+               asked for login credentials, the request for a browser session
+               will be made through the agent.
+
        --enable-polkit
 
                Enable support for PolicyKit authorization
@@ -179,3 +195,38 @@ This last option will enable the support of background scanning while being
 connected, which is necessary when roaming on wifi.
 
 It is recommended to use wpa_supplicant 0.8.x or 1.x or later.
+
+
+VPN
+===
+
+In order to compile pptp and l2tp VPN plugins, you need ppp development
+package.
+
+To run l2tp you will need
+       - xl2tpd, http://www.xelerance.com/services/software/xl2tpd
+
+To run pptp you will need
+       - pptp client, http://pptpclient.sourceforge.net
+
+Both l2tp and pptp also need pppd.
+
+
+OpenVPN
+=======
+
+Up to version 2.2 of OpenVPN, pushing additional routes from the
+server will not always work. Some of the symptons are that additional
+routes will not be set by ConnMan if the uplink is a cellular
+network. While the same setup works well for a WiFi or ethernet
+uplink.
+
+
+Information
+===========
+
+Mailing list:
+       connman@connman.net
+
+For additional information about the project visit ConnMan web site:
+       http://www.connman.net
diff --git a/TODO b/TODO
index b9a3af1..a9287b7 100644 (file)
--- a/TODO
+++ b/TODO
@@ -45,6 +45,15 @@ Core
    security integration.
 
 
+- Favorite service migration removal
+
+  Priority: Medium
+  Complexity: C1
+  When: 12/2012
+
+  Remove service migration code that moves services from default.profile
+  to the current directory-based structure.
+
 
 WiFi
 ====
@@ -71,7 +80,7 @@ WiFi
 
    Priority: Medium
    Complexity: C4
-   Owner: Samuel Ortiz <sameo@linux.intel.com>
+   Owner: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
 
    While connected ConnMan should offload the background scanning to
    wpa_supplicant. Wpa_supplicant allows for a fancy background scan
@@ -88,16 +97,16 @@ WiFi
    Complexity: C2
 
 
+- Previous WPS pin code sending
 
-Bluetooth
-=========
+  Priority: Medium
+  Complexity: C2
 
-- DUN client
+  Provide previous WPS pin code in PreviousPassphrase field if WPS was used.
 
-   Priority: Low
-   Complexity: C4
-   Owner: Mario Tokarz <mario.tokarz@bmw-carit.de>
 
+Bluetooth
+=========
 
 
 Cellular
index 1bfe0eb..9f26960 100644 (file)
@@ -1,4 +1,4 @@
-# generated automatically by aclocal 1.11.3 -*- Autoconf -*-
+# generated automatically by aclocal 1.11.5 -*- Autoconf -*-
 
 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
 # 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation,
@@ -14,8 +14,8 @@
 
 m4_ifndef([AC_AUTOCONF_VERSION],
   [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
-m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.68],,
-[m4_warning([this file was generated for autoconf 2.68.
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],,
+[m4_warning([this file was generated for autoconf 2.69.
 You have another version of autoconf.  It may work, but is not guaranteed to.
 If you have problems, you may need to regenerate the build system entirely.
 To do so, use the procedure documented by the package, typically `autoreconf'.])])
@@ -8804,7 +8804,7 @@ AC_DEFUN([AM_AUTOMAKE_VERSION],
 [am__api_version='1.11'
 dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
 dnl require some minimum version.  Point them to the right macro.
-m4_if([$1], [1.11.3], [],
+m4_if([$1], [1.11.5], [],
       [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
 ])
 
@@ -8820,7 +8820,7 @@ m4_define([_AM_AUTOCONF_VERSION], [])
 # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
 # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
 AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
-[AM_AUTOMAKE_VERSION([1.11.3])dnl
+[AM_AUTOMAKE_VERSION([1.11.5])dnl
 m4_ifndef([AC_AUTOCONF_VERSION],
   [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
 _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
diff --git a/compile b/compile
index b1f4749..862a14e 100644 (file)
--- a/compile
+++ b/compile
@@ -1,7 +1,7 @@
 #! /bin/sh
 # Wrapper for compilers which do not understand '-c -o'.
 
-scriptversion=2012-01-04.17; # UTC
+scriptversion=2012-03-05.13; # UTC
 
 # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009, 2010, 2012 Free
 # Software Foundation, Inc.
@@ -79,6 +79,48 @@ func_file_conv ()
   esac
 }
 
+# func_cl_dashL linkdir
+# Make cl look for libraries in LINKDIR
+func_cl_dashL ()
+{
+  func_file_conv "$1"
+  if test -z "$lib_path"; then
+    lib_path=$file
+  else
+    lib_path="$lib_path;$file"
+  fi
+  linker_opts="$linker_opts -LIBPATH:$file"
+}
+
+# func_cl_dashl library
+# Do a library search-path lookup for cl
+func_cl_dashl ()
+{
+  lib=$1
+  found=no
+  save_IFS=$IFS
+  IFS=';'
+  for dir in $lib_path $LIB
+  do
+    IFS=$save_IFS
+    if $shared && test -f "$dir/$lib.dll.lib"; then
+      found=yes
+      lib=$dir/$lib.dll.lib
+      break
+    fi
+    if test -f "$dir/$lib.lib"; then
+      found=yes
+      lib=$dir/$lib.lib
+      break
+    fi
+  done
+  IFS=$save_IFS
+
+  if test "$found" != yes; then
+    lib=$lib.lib
+  fi
+}
+
 # func_cl_wrapper cl arg...
 # Adjust compile command to suit cl
 func_cl_wrapper ()
@@ -109,43 +151,34 @@ func_cl_wrapper ()
              ;;
          esac
          ;;
+       -I)
+         eat=1
+         func_file_conv "$2" mingw
+         set x "$@" -I"$file"
+         shift
+         ;;
        -I*)
          func_file_conv "${1#-I}" mingw
          set x "$@" -I"$file"
          shift
          ;;
+       -l)
+         eat=1
+         func_cl_dashl "$2"
+         set x "$@" "$lib"
+         shift
+         ;;
        -l*)
-         lib=${1#-l}
-         found=no
-         save_IFS=$IFS
-         IFS=';'
-         for dir in $lib_path $LIB
-         do
-           IFS=$save_IFS
-           if $shared && test -f "$dir/$lib.dll.lib"; then
-             found=yes
-             set x "$@" "$dir/$lib.dll.lib"
-             break
-           fi
-           if test -f "$dir/$lib.lib"; then
-             found=yes
-             set x "$@" "$dir/$lib.lib"
-             break
-           fi
-         done
-         IFS=$save_IFS
-
-         test "$found" != yes && set x "$@" "$lib.lib"
+         func_cl_dashl "${1#-l}"
+         set x "$@" "$lib"
          shift
          ;;
+       -L)
+         eat=1
+         func_cl_dashL "$2"
+         ;;
        -L*)
-         func_file_conv "${1#-L}"
-         if test -z "$lib_path"; then
-           lib_path=$file
-         else
-           lib_path="$lib_path;$file"
-         fi
-         linker_opts="$linker_opts -LIBPATH:$file"
+         func_cl_dashL "${1#-L}"
          ;;
        -static)
          shared=false
index c894da4..6205f84 100644 (file)
@@ -4,7 +4,7 @@
 #   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
 #   2011, 2012 Free Software Foundation, Inc.
 
-timestamp='2012-02-10'
+timestamp='2012-04-18'
 
 # This file is (in principle) common to ALL GNU software.
 # The presence of a machine in this file suggests that SOME GNU software
@@ -225,6 +225,12 @@ case $os in
        -isc*)
                basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
                ;;
+       -lynx*178)
+               os=-lynxos178
+               ;;
+       -lynx*5)
+               os=-lynxos5
+               ;;
        -lynx*)
                os=-lynxos
                ;;
@@ -1537,6 +1543,9 @@ case $basic_machine in
        c4x-* | tic4x-*)
                os=-coff
                ;;
+       hexagon-*)
+               os=-elf
+               ;;
        tic54x-*)
                os=-coff
                ;;
index 4918383..1364d05 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,11 +1,9 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68 for connman 1.0.
+# Generated by GNU Autoconf 2.69 for connman 1.3.
 #
 #
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
-# Foundation, Inc.
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
 #
 #
 # This configure script is free software; the Free Software Foundation
@@ -134,6 +132,31 @@ export LANGUAGE
 # CDPATH.
 (unset CDPATH) >/dev/null 2>&1 && unset CDPATH
 
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
 if test "x$CONFIG_SHELL" = x; then
   as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
   emulate sh
@@ -167,7 +190,8 @@ if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
 else
   exitcode=1; echo positional parameters were not saved.
 fi
-test x\$exitcode = x0 || exit 1"
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
   as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
   as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
   eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
@@ -220,21 +244,25 @@ IFS=$as_save_IFS
 
 
       if test "x$CONFIG_SHELL" != x; then :
-  # We cannot yet assume a decent shell, so we have to provide a
-       # neutralization value for shells without unset; and this also
-       # works around shells that cannot unset nonexistent variables.
-       # Preserve -v and -x to the replacement shell.
-       BASH_ENV=/dev/null
-       ENV=/dev/null
-       (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
-       export CONFIG_SHELL
-       case $- in # ((((
-         *v*x* | *x*v* ) as_opts=-vx ;;
-         *v* ) as_opts=-v ;;
-         *x* ) as_opts=-x ;;
-         * ) as_opts= ;;
-       esac
-       exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
 fi
 
     if test x$as_have_required = xno; then :
@@ -336,6 +364,14 @@ $as_echo X"$as_dir" |
 
 
 } # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
 # as_fn_append VAR VALUE
 # ----------------------
 # Append the text in VALUE to the end of the definition contained in VAR. Take
@@ -457,6 +493,10 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
   chmod +x "$as_me.lineno" ||
     { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
 
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
   # Don't try to exec as it changes $[0], causing all sort of problems
   # (the dirname of $[0] is not the place where we might find the
   # original and so on.  Autoconf is especially sensitive to this).
@@ -491,16 +531,16 @@ if (echo >conf$$.file) 2>/dev/null; then
     # ... but there are two gotchas:
     # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
     # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
-    # In both cases, we have to default to `cp -p'.
+    # In both cases, we have to default to `cp -pR'.
     ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
-      as_ln_s='cp -p'
+      as_ln_s='cp -pR'
   elif ln conf$$.file conf$$ 2>/dev/null; then
     as_ln_s=ln
   else
-    as_ln_s='cp -p'
+    as_ln_s='cp -pR'
   fi
 else
-  as_ln_s='cp -p'
+  as_ln_s='cp -pR'
 fi
 rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
 rmdir conf$$.dir 2>/dev/null
@@ -512,28 +552,8 @@ else
   as_mkdir_p=false
 fi
 
-if test -x / >/dev/null 2>&1; then
-  as_test_x='test -x'
-else
-  if ls -dL / >/dev/null 2>&1; then
-    as_ls_L_option=L
-  else
-    as_ls_L_option=
-  fi
-  as_test_x='
-    eval sh -c '\''
-      if test -d "$1"; then
-       test -d "$1/.";
-      else
-       case $1 in #(
-       -*)set "./$1";;
-       esac;
-       case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
-       ???[sx]*):;;*)false;;esac;fi
-    '\'' sh
-  '
-fi
-as_executable_p=$as_test_x
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
 
 # Sed expression to map a string onto a valid CPP name.
 as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -567,8 +587,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='connman'
 PACKAGE_TARNAME='connman'
-PACKAGE_VERSION='1.0'
-PACKAGE_STRING='connman 1.0'
+PACKAGE_VERSION='1.3'
+PACKAGE_STRING='connman 1.3'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
@@ -616,12 +636,18 @@ LIBOBJS
 DATAFILES_FALSE
 DATAFILES_TRUE
 WPASUPPLICANT
-TOOLS_FALSE
-TOOLS_TRUE
+GNUTLS_LIBS
+GNUTLS_CFLAGS
 CLIENT_FALSE
 CLIENT_TRUE
+TOOLS_FALSE
+TOOLS_TRUE
+WISPR_FALSE
+WISPR_TRUE
 PACRUNNER_FALSE
 PACRUNNER_TRUE
+DUNDEE_FALSE
+DUNDEE_TRUE
 OFONO_FALSE
 OFONO_TRUE
 BLUETOOTH_FALSE
@@ -641,8 +667,6 @@ TEST_FALSE
 TEST_TRUE
 XTABLES_LIBS
 XTABLES_CFLAGS
-GNUTLS_LIBS
-GNUTLS_CFLAGS
 SYSTEMD_FALSE
 SYSTEMD_TRUE
 SYSTEMD_UNITDIR
@@ -864,9 +888,11 @@ enable_ethernet
 enable_wifi
 enable_bluetooth
 enable_ofono
+enable_dundee
 enable_pacrunner
-enable_client
+enable_wispr
 enable_tools
+enable_client
 enable_datafiles
 '
       ac_precious_vars='build_alias
@@ -889,10 +915,10 @@ GTHREAD_CFLAGS
 GTHREAD_LIBS
 DBUS_CFLAGS
 DBUS_LIBS
-GNUTLS_CFLAGS
-GNUTLS_LIBS
 XTABLES_CFLAGS
-XTABLES_LIBS'
+XTABLES_LIBS
+GNUTLS_CFLAGS
+GNUTLS_LIBS'
 
 
 # Initialize some variables set by options.
@@ -1348,8 +1374,6 @@ target=$target_alias
 if test "x$host_alias" != x; then
   if test "x$build_alias" = x; then
     cross_compiling=maybe
-    $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
-    If a cross compiler is detected then cross compile mode will be used" >&2
   elif test "x$build_alias" != "x$host_alias"; then
     cross_compiling=yes
   fi
@@ -1435,7 +1459,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures connman 1.0 to adapt to many kinds of systems.
+\`configure' configures connman 1.3 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1505,7 +1529,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of connman 1.0:";;
+     short | recursive ) echo "Configuration of connman 1.3:";;
    esac
   cat <<\_ACEOF
 
@@ -1546,9 +1570,11 @@ Optional Features:
   --disable-wifi          disable WiFi support
   --disable-bluetooth     disable Bluetooth support
   --disable-ofono         disable oFono support
+  --disable-dundee        disable dundee support (Bluetooth DUN)
   --disable-pacrunner     disable PACrunner support
-  --disable-client        disable command line client
+  --disable-wispr         disable WISPr support
   --disable-tools         disable testing tools
+  --disable-client        disable command line client
   --disable-datafiles     don't install configuration and data files
 
 Optional Packages:
@@ -1598,13 +1624,13 @@ Some influential environment variables:
               linker flags for GTHREAD, overriding pkg-config
   DBUS_CFLAGS C compiler flags for DBUS, overriding pkg-config
   DBUS_LIBS   linker flags for DBUS, overriding pkg-config
-  GNUTLS_CFLAGS
-              C compiler flags for GNUTLS, overriding pkg-config
-  GNUTLS_LIBS linker flags for GNUTLS, overriding pkg-config
   XTABLES_CFLAGS
               C compiler flags for XTABLES, overriding pkg-config
   XTABLES_LIBS
               linker flags for XTABLES, overriding pkg-config
+  GNUTLS_CFLAGS
+              C compiler flags for GNUTLS, overriding pkg-config
+  GNUTLS_LIBS linker flags for GNUTLS, overriding pkg-config
 
 Use these variables to override the choices made by `configure' or to help
 it to find libraries and programs with nonstandard names/locations.
@@ -1672,10 +1698,10 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-connman configure 1.0
-generated by GNU Autoconf 2.68
+connman configure 1.3
+generated by GNU Autoconf 2.69
 
-Copyright (C) 2010 Free Software Foundation, Inc.
+Copyright (C) 2012 Free Software Foundation, Inc.
 This configure script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it.
 _ACEOF
@@ -1751,7 +1777,7 @@ $as_echo "$ac_try_echo"; } >&5
         test ! -s conftest.err
        } && test -s conftest$ac_exeext && {
         test "$cross_compiling" = yes ||
-        $as_test_x conftest$ac_exeext
+        test -x conftest$ac_exeext
        }; then :
   ac_retval=0
 else
@@ -2137,8 +2163,8 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by connman $as_me 1.0, which was
-generated by GNU Autoconf 2.68.  Invocation command line was
+It was created by connman $as_me 1.3, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
 
@@ -2554,7 +2580,7 @@ case $as_dir/ in #((
     # by default.
     for ac_prog in ginstall scoinst install; do
       for ac_exec_ext in '' $ac_executable_extensions; do
-       if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+       if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
          if test $ac_prog = install &&
            grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
            # AIX install.  It has an incompatible calling convention.
@@ -2723,7 +2749,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_STRIP="${ac_tool_prefix}strip"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2763,7 +2789,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_STRIP="strip"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2814,7 +2840,7 @@ do
   test -z "$as_dir" && as_dir=.
     for ac_prog in mkdir gmkdir; do
         for ac_exec_ext in '' $ac_executable_extensions; do
-          { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
+          as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue
           case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
             'mkdir (GNU coreutils) '* | \
             'mkdir (coreutils) '* | \
@@ -2867,7 +2893,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_AWK="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2953,7 +2979,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='connman'
- VERSION='1.0'
+ VERSION='1.3'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -3089,7 +3115,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3132,7 +3158,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3231,7 +3257,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="${ac_tool_prefix}gcc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3271,7 +3297,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CC="gcc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3324,7 +3350,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="${ac_tool_prefix}cc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3365,7 +3391,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
        ac_prog_rejected=yes
        continue
@@ -3423,7 +3449,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3467,7 +3493,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CC="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3913,8 +3939,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #include <stdarg.h>
 #include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+struct stat;
 /* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
 struct buf { int x; };
 FILE * (*rcsopen) (struct buf *, struct stat *, int);
@@ -4564,7 +4589,7 @@ do
     for ac_prog in sed gsed; do
     for ac_exec_ext in '' $ac_executable_extensions; do
       ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
-      { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue
+      as_fn_executable_p "$ac_path_SED" || continue
 # Check for GNU ac_path_SED and select it if it is found.
   # Check for GNU $ac_path_SED
 case `"$ac_path_SED" --version 2>&1` in
@@ -4640,7 +4665,7 @@ do
     for ac_prog in grep ggrep; do
     for ac_exec_ext in '' $ac_executable_extensions; do
       ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
-      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+      as_fn_executable_p "$ac_path_GREP" || continue
 # Check for GNU ac_path_GREP and select it if it is found.
   # Check for GNU $ac_path_GREP
 case `"$ac_path_GREP" --version 2>&1` in
@@ -4706,7 +4731,7 @@ do
     for ac_prog in egrep; do
     for ac_exec_ext in '' $ac_executable_extensions; do
       ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
-      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+      as_fn_executable_p "$ac_path_EGREP" || continue
 # Check for GNU ac_path_EGREP and select it if it is found.
   # Check for GNU $ac_path_EGREP
 case `"$ac_path_EGREP" --version 2>&1` in
@@ -4773,7 +4798,7 @@ do
     for ac_prog in fgrep; do
     for ac_exec_ext in '' $ac_executable_extensions; do
       ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext"
-      { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue
+      as_fn_executable_p "$ac_path_FGREP" || continue
 # Check for GNU ac_path_FGREP and select it if it is found.
   # Check for GNU $ac_path_FGREP
 case `"$ac_path_FGREP" --version 2>&1` in
@@ -5029,7 +5054,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -5073,7 +5098,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_DUMPBIN="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -5497,7 +5522,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -5537,7 +5562,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_OBJDUMP="objdump"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -5843,7 +5868,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -5883,7 +5908,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_DLLTOOL="dlltool"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -5987,7 +6012,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_AR="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6031,7 +6056,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_AR="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6156,7 +6181,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_STRIP="${ac_tool_prefix}strip"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6196,7 +6221,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_STRIP="strip"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6255,7 +6280,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6295,7 +6320,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_RANLIB="ranlib"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6944,7 +6969,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6984,7 +7009,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_MANIFEST_TOOL="mt"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7064,7 +7089,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7104,7 +7129,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_DSYMUTIL="dsymutil"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7156,7 +7181,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7196,7 +7221,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_NMEDIT="nmedit"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7248,7 +7273,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_LIPO="${ac_tool_prefix}lipo"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7288,7 +7313,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_LIPO="lipo"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7340,7 +7365,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_OTOOL="${ac_tool_prefix}otool"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7380,7 +7405,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_OTOOL="otool"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7432,7 +7457,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7472,7 +7497,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_OTOOL64="otool64"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -12010,7 +12035,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_GTKDOC_CHECK="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -12144,7 +12169,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_OPENCONNECT="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -12226,7 +12251,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_OPENVPN="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -12308,7 +12333,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_VPNC="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -12383,7 +12408,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_PPPD="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -12444,7 +12469,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_L2TP="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -12517,7 +12542,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_PPPD="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -12578,7 +12603,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_PPTP="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
 
 
 pkg_failed=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNUTLS" >&5
-$as_echo_n "checking for GNUTLS... " >&6; }
-
-if test -n "$GNUTLS_CFLAGS"; then
-    pkg_cv_GNUTLS_CFLAGS="$GNUTLS_CFLAGS"
- elif test -n "$PKG_CONFIG"; then
-    if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gnutls\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "gnutls") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then
-  pkg_cv_GNUTLS_CFLAGS=`$PKG_CONFIG --cflags "gnutls" 2>/dev/null`
-                     test "x$?" != "x0" && pkg_failed=yes
-else
-  pkg_failed=yes
-fi
- else
-    pkg_failed=untried
-fi
-if test -n "$GNUTLS_LIBS"; then
-    pkg_cv_GNUTLS_LIBS="$GNUTLS_LIBS"
- elif test -n "$PKG_CONFIG"; then
-    if test -n "$PKG_CONFIG" && \
-    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gnutls\""; } >&5
-  ($PKG_CONFIG --exists --print-errors "gnutls") 2>&5
-  ac_status=$?
-  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
-  test $ac_status = 0; }; then
-  pkg_cv_GNUTLS_LIBS=`$PKG_CONFIG --libs "gnutls" 2>/dev/null`
-                     test "x$?" != "x0" && pkg_failed=yes
-else
-  pkg_failed=yes
-fi
- else
-    pkg_failed=untried
-fi
-
-
-
-if test $pkg_failed = yes; then
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-
-if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
-        _pkg_short_errors_supported=yes
-else
-        _pkg_short_errors_supported=no
-fi
-        if test $_pkg_short_errors_supported = yes; then
-               GNUTLS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gnutls" 2>&1`
-        else
-               GNUTLS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gnutls" 2>&1`
-        fi
-       # Put the nasty error message in config.log where it belongs
-       echo "$GNUTLS_PKG_ERRORS" >&5
-
-       as_fn_error $? "GnuTLS library is required" "$LINENO" 5
-elif test $pkg_failed = untried; then
-       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-       as_fn_error $? "GnuTLS library is required" "$LINENO" 5
-else
-       GNUTLS_CFLAGS=$pkg_cv_GNUTLS_CFLAGS
-       GNUTLS_LIBS=$pkg_cv_GNUTLS_LIBS
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-       dummy=yes
-fi
-
-
-
-
-pkg_failed=no
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XTABLES" >&5
 $as_echo_n "checking for XTABLES... " >&6; }
 
@@ -13530,6 +13481,20 @@ else
 fi
 
 
+# Check whether --enable-dundee was given.
+if test "${enable_dundee+set}" = set; then :
+  enableval=$enable_dundee; enable_dundee=${enableval}
+fi
+
+ if test "${enable_dundee}" != "no"; then
+  DUNDEE_TRUE=
+  DUNDEE_FALSE='#'
+else
+  DUNDEE_TRUE='#'
+  DUNDEE_FALSE=
+fi
+
+
 # Check whether --enable-pacrunner was given.
 if test "${enable_pacrunner+set}" = set; then :
   enableval=$enable_pacrunner; enable_pacrunner=${enableval}
@@ -13544,17 +13509,17 @@ else
 fi
 
 
-# Check whether --enable-client was given.
-if test "${enable_client+set}" = set; then :
-  enableval=$enable_client; disable_client=${enableval}
+# Check whether --enable-wispr was given.
+if test "${enable_wispr+set}" = set; then :
+  enableval=$enable_wispr; enable_wispr=${enableval}
 fi
 
- if test "${enable_client}" != "no"; then
-  CLIENT_TRUE=
-  CLIENT_FALSE='#'
+ if test "${enable_wispr}" != "no"; then
+  WISPR_TRUE=
+  WISPR_FALSE='#'
 else
-  CLIENT_TRUE='#'
-  CLIENT_FALSE=
+  WISPR_TRUE='#'
+  WISPR_FALSE=
 fi
 
 
@@ -13572,6 +13537,99 @@ else
 fi
 
 
+# Check whether --enable-client was given.
+if test "${enable_client+set}" = set; then :
+  enableval=$enable_client; disable_client=${enableval}
+fi
+
+ if test "${enable_client}" != "no"; then
+  CLIENT_TRUE=
+  CLIENT_FALSE='#'
+else
+  CLIENT_TRUE='#'
+  CLIENT_FALSE=
+fi
+
+
+if (test "${enable_wispr}" != "no"); then
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNUTLS" >&5
+$as_echo_n "checking for GNUTLS... " >&6; }
+
+if test -n "$GNUTLS_CFLAGS"; then
+    pkg_cv_GNUTLS_CFLAGS="$GNUTLS_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gnutls\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "gnutls") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_GNUTLS_CFLAGS=`$PKG_CONFIG --cflags "gnutls" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+if test -n "$GNUTLS_LIBS"; then
+    pkg_cv_GNUTLS_LIBS="$GNUTLS_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+    if test -n "$PKG_CONFIG" && \
+    { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gnutls\""; } >&5
+  ($PKG_CONFIG --exists --print-errors "gnutls") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then
+  pkg_cv_GNUTLS_LIBS=`$PKG_CONFIG --libs "gnutls" 2>/dev/null`
+                     test "x$?" != "x0" && pkg_failed=yes
+else
+  pkg_failed=yes
+fi
+ else
+    pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi
+        if test $_pkg_short_errors_supported = yes; then
+               GNUTLS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gnutls" 2>&1`
+        else
+               GNUTLS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gnutls" 2>&1`
+        fi
+       # Put the nasty error message in config.log where it belongs
+       echo "$GNUTLS_PKG_ERRORS" >&5
+
+       as_fn_error $? "GnuTLS library is required" "$LINENO" 5
+elif test $pkg_failed = untried; then
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+       as_fn_error $? "GnuTLS library is required" "$LINENO" 5
+else
+       GNUTLS_CFLAGS=$pkg_cv_GNUTLS_CFLAGS
+       GNUTLS_LIBS=$pkg_cv_GNUTLS_LIBS
+        { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+       dummy=yes
+fi
+else
+       GNUTLS_CFLAGS=""
+       GNUTLS_LIBS=""
+fi
+
+
+
 if (test "${enable_loopback}" != "no"); then
        for ac_header in sys/inotify.h
 do :
@@ -13652,7 +13710,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_path_WPASUPPLICANT="$as_dir/$ac_word$ac_exec_ext"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -13929,18 +13987,26 @@ if test -z "${OFONO_TRUE}" && test -z "${OFONO_FALSE}"; then
   as_fn_error $? "conditional \"OFONO\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${DUNDEE_TRUE}" && test -z "${DUNDEE_FALSE}"; then
+  as_fn_error $? "conditional \"DUNDEE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${PACRUNNER_TRUE}" && test -z "${PACRUNNER_FALSE}"; then
   as_fn_error $? "conditional \"PACRUNNER\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
-if test -z "${CLIENT_TRUE}" && test -z "${CLIENT_FALSE}"; then
-  as_fn_error $? "conditional \"CLIENT\" was never defined.
+if test -z "${WISPR_TRUE}" && test -z "${WISPR_FALSE}"; then
+  as_fn_error $? "conditional \"WISPR\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
 if test -z "${TOOLS_TRUE}" && test -z "${TOOLS_FALSE}"; then
   as_fn_error $? "conditional \"TOOLS\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${CLIENT_TRUE}" && test -z "${CLIENT_FALSE}"; then
+  as_fn_error $? "conditional \"CLIENT\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${DATAFILES_TRUE}" && test -z "${DATAFILES_FALSE}"; then
   as_fn_error $? "conditional \"DATAFILES\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -14243,16 +14309,16 @@ if (echo >conf$$.file) 2>/dev/null; then
     # ... but there are two gotchas:
     # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
     # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
-    # In both cases, we have to default to `cp -p'.
+    # In both cases, we have to default to `cp -pR'.
     ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
-      as_ln_s='cp -p'
+      as_ln_s='cp -pR'
   elif ln conf$$.file conf$$ 2>/dev/null; then
     as_ln_s=ln
   else
-    as_ln_s='cp -p'
+    as_ln_s='cp -pR'
   fi
 else
-  as_ln_s='cp -p'
+  as_ln_s='cp -pR'
 fi
 rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
 rmdir conf$$.dir 2>/dev/null
@@ -14312,28 +14378,16 @@ else
   as_mkdir_p=false
 fi
 
-if test -x / >/dev/null 2>&1; then
-  as_test_x='test -x'
-else
-  if ls -dL / >/dev/null 2>&1; then
-    as_ls_L_option=L
-  else
-    as_ls_L_option=
-  fi
-  as_test_x='
-    eval sh -c '\''
-      if test -d "$1"; then
-       test -d "$1/.";
-      else
-       case $1 in #(
-       -*)set "./$1";;
-       esac;
-       case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
-       ???[sx]*):;;*)false;;esac;fi
-    '\'' sh
-  '
-fi
-as_executable_p=$as_test_x
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
 
 # Sed expression to map a string onto a valid CPP name.
 as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -14354,8 +14408,8 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by connman $as_me 1.0, which was
-generated by GNU Autoconf 2.68.  Invocation command line was
+This file was extended by connman $as_me 1.3, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
   CONFIG_HEADERS  = $CONFIG_HEADERS
@@ -14420,11 +14474,11 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-connman config.status 1.0
-configured by $0, generated by GNU Autoconf 2.68,
+connman config.status 1.3
+configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
-Copyright (C) 2010 Free Software Foundation, Inc.
+Copyright (C) 2012 Free Software Foundation, Inc.
 This config.status script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it."
 
@@ -14515,7 +14569,7 @@ fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 if \$ac_cs_recheck; then
-  set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
   shift
   \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
   CONFIG_SHELL='$SHELL'
index 1f2b81e..284e637 100644 (file)
@@ -1,5 +1,5 @@
 AC_PREREQ(2.60)
-AC_INIT(connman, 1.0)
+AC_INIT(connman, 1.3)
 
 AM_INIT_AUTOMAKE([foreign subdir-objects color-tests])
 AM_CONFIG_HEADER(config.h)
@@ -310,11 +310,6 @@ if (test -n "${path_systemdunit}"); then
 fi
 AM_CONDITIONAL(SYSTEMD, test -n "${path_systemdunit}")
 
-PKG_CHECK_MODULES(GNUTLS, gnutls, dummy=yes,
-                               AC_MSG_ERROR(GnuTLS library is required))
-AC_SUBST(GNUTLS_CFLAGS)
-AC_SUBST(GNUTLS_LIBS)
-
 PKG_CHECK_MODULES(XTABLES, xtables, dummy=yes,
                                AC_MSG_ERROR(Xtables library is required))
 AC_SUBST(XTABLES_CFLAGS)
@@ -367,21 +362,41 @@ AC_ARG_ENABLE(ofono, AC_HELP_STRING([--disable-ofono],
                                        [enable_ofono=${enableval}])
 AM_CONDITIONAL(OFONO, test "${enable_ofono}" != "no")
 
+AC_ARG_ENABLE(dundee, AC_HELP_STRING([--disable-dundee],
+                               [disable dundee support (Bluetooth DUN)]),
+                                       [enable_dundee=${enableval}])
+AM_CONDITIONAL(DUNDEE, test "${enable_dundee}" != "no")
+
 AC_ARG_ENABLE(pacrunner, AC_HELP_STRING([--disable-pacrunner],
                                [disable PACrunner support]),
                                        [enable_pacrunner=${enableval}])
 AM_CONDITIONAL(PACRUNNER, test "${enable_pacrunner}" != "no")
 
-AC_ARG_ENABLE(client, AC_HELP_STRING([--disable-client],
-                               [disable command line client]),
-                                       [disable_client=${enableval}])
-AM_CONDITIONAL(CLIENT, test "${enable_client}" != "no")
+AC_ARG_ENABLE(wispr, AC_HELP_STRING([--disable-wispr],
+                               [disable WISPr support]),
+                                       [enable_wispr=${enableval}])
+AM_CONDITIONAL(WISPR, test "${enable_wispr}" != "no")
 
 AC_ARG_ENABLE(tools, AC_HELP_STRING([--disable-tools],
                                [disable testing tools]),
                                        [enable_tools=${enableval}])
 AM_CONDITIONAL(TOOLS, test "${enable_tools}" != "no")
 
+AC_ARG_ENABLE(client, AC_HELP_STRING([--disable-client],
+                               [disable command line client]),
+                                       [disable_client=${enableval}])
+AM_CONDITIONAL(CLIENT, test "${enable_client}" != "no")
+
+if (test "${enable_wispr}" != "no"); then
+       PKG_CHECK_MODULES(GNUTLS, gnutls, dummy=yes,
+                               AC_MSG_ERROR(GnuTLS library is required))
+else
+       GNUTLS_CFLAGS=""
+       GNUTLS_LIBS=""
+fi
+AC_SUBST(GNUTLS_CFLAGS)
+AC_SUBST(GNUTLS_LIBS)
+
 if (test "${enable_loopback}" != "no"); then
        AC_CHECK_HEADERS(sys/inotify.h, dummy=yes,
                        AC_MSG_ERROR(inotify header files are required))
diff --git a/depcomp b/depcomp
index bd0ac08..25a39e6 100644 (file)
--- a/depcomp
+++ b/depcomp
@@ -1,10 +1,10 @@
 #! /bin/sh
 # depcomp - compile a program generating dependencies as side-effects
 
-scriptversion=2011-12-04.11; # UTC
+scriptversion=2012-03-27.16; # UTC
 
 # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009, 2010,
-# 2011 Free Software Foundation, Inc.
+# 2011, 2012 Free Software Foundation, Inc.
 
 # 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
@@ -28,7 +28,7 @@ scriptversion=2011-12-04.11; # UTC
 
 case $1 in
   '')
-     echo "$0: No command.  Try \`$0 --help' for more information." 1>&2
+     echo "$0: No command.  Try '$0 --help' for more information." 1>&2
      exit 1;
      ;;
   -h | --h*)
@@ -40,8 +40,8 @@ as side-effects.
 
 Environment variables:
   depmode     Dependency tracking mode.
-  source      Source file read by `PROGRAMS ARGS'.
-  object      Object file output by `PROGRAMS ARGS'.
+  source      Source file read by 'PROGRAMS ARGS'.
+  object      Object file output by 'PROGRAMS ARGS'.
   DEPDIR      directory where to store dependencies.
   depfile     Dependency file to output.
   tmpdepfile  Temporary file to use when outputting dependencies.
@@ -57,6 +57,12 @@ EOF
     ;;
 esac
 
+# A tabulation character.
+tab='  '
+# A newline character.
+nl='
+'
+
 if test -z "$depmode" || test -z "$source" || test -z "$object"; then
   echo "depcomp: Variables source, object and depmode must be set" 1>&2
   exit 1
@@ -102,6 +108,12 @@ if test "$depmode" = msvc7msys; then
    depmode=msvc7
 fi
 
+if test "$depmode" = xlc; then
+   # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency informations.
+   gccflag=-qmakedep=gcc,-MF
+   depmode=gcc
+fi
+
 case "$depmode" in
 gcc3)
 ## gcc 3 implements dependency tracking that does exactly what
@@ -156,15 +168,14 @@ gcc)
 ## The second -e expression handles DOS-style file names with drive letters.
   sed -e 's/^[^:]*: / /' \
       -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
-## This next piece of magic avoids the `deleted header file' problem.
+## This next piece of magic avoids the "deleted header file" problem.
 ## The problem is that when a header file which appears in a .P file
 ## is deleted, the dependency causes make to die (because there is
 ## typically no way to rebuild the header).  We avoid this by adding
 ## dummy dependencies for each header file.  Too bad gcc doesn't do
 ## this for us directly.
-  tr ' ' '
-' < "$tmpdepfile" |
-## Some versions of gcc put a space before the `:'.  On the theory
+  tr ' ' "$nl" < "$tmpdepfile" |
+## Some versions of gcc put a space before the ':'.  On the theory
 ## that the space means something, we add a space to the output as
 ## well.  hp depmode also adds that space, but also prefixes the VPATH
 ## to the object.  Take care to not repeat it in the output.
@@ -203,18 +214,15 @@ sgi)
     # clever and replace this with sed code, as IRIX sed won't handle
     # lines with more than a fixed number of characters (4096 in
     # IRIX 6.2 sed, 8192 in IRIX 6.5).  We also remove comment lines;
-    # the IRIX cc adds comments like `#:fec' to the end of the
+    # the IRIX cc adds comments like '#:fec' to the end of the
     # dependency line.
-    tr ' ' '
-' < "$tmpdepfile" \
+    tr ' ' "$nl" < "$tmpdepfile" \
     | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
-    tr '
-' ' ' >> "$depfile"
+    tr "$nl" ' ' >> "$depfile"
     echo >> "$depfile"
 
     # The second pass generates a dummy entry for each header file.
-    tr ' ' '
-' < "$tmpdepfile" \
+    tr ' ' "$nl" < "$tmpdepfile" \
    | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
    >> "$depfile"
   else
@@ -226,10 +234,17 @@ sgi)
   rm -f "$tmpdepfile"
   ;;
 
+xlc)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
 aix)
   # The C for AIX Compiler uses -M and outputs the dependencies
   # in a .u file.  In older versions, this file always lives in the
-  # current directory.  Also, the AIX compiler puts `$object:' at the
+  # current directory.  Also, the AIX compiler puts '$object:' at the
   # start of each line; $object doesn't have directory information.
   # Version 6 uses the directory in both cases.
   dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
@@ -259,12 +274,11 @@ aix)
     test -f "$tmpdepfile" && break
   done
   if test -f "$tmpdepfile"; then
-    # Each line is of the form `foo.o: dependent.h'.
+    # Each line is of the form 'foo.o: dependent.h'.
     # Do two passes, one to just change these to
-    # `$object: dependent.h' and one to simply `dependent.h:'.
+    # '$object: dependent.h' and one to simply 'dependent.h:'.
     sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
-    # That's a tab and a space in the [].
-    sed -e 's,^.*\.[a-z]*:[     ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+    sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
   else
     # The sourcefile does not contain any dependencies, so just
     # store a dummy comment line, to avoid errors with the Makefile
@@ -275,23 +289,26 @@ aix)
   ;;
 
 icc)
-  # Intel's C compiler understands `-MD -MF file'.  However on
-  #    icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
+  # Intel's C compiler anf tcc (Tiny C Compiler) understand '-MD -MF file'.
+  # However on
+  #    $CC -MD -MF foo.d -c -o sub/foo.o sub/foo.c
   # ICC 7.0 will fill foo.d with something like
   #    foo.o: sub/foo.c
   #    foo.o: sub/foo.h
-  # which is wrong.  We want:
+  # which is wrong.  We want
   #    sub/foo.o: sub/foo.c
   #    sub/foo.o: sub/foo.h
   #    sub/foo.c:
   #    sub/foo.h:
   # ICC 7.1 will output
   #    foo.o: sub/foo.c sub/foo.h
-  # and will wrap long lines using :
+  # and will wrap long lines using '\':
   #    foo.o: sub/foo.c ... \
   #     sub/foo.h ... \
   #     ...
-
+  # tcc 0.9.26 (FIXME still under development at the moment of writing)
+  # will emit a similar output, but also prepend the continuation lines
+  # with horizontal tabulation characters.
   "$@" -MD -MF "$tmpdepfile"
   stat=$?
   if test $stat -eq 0; then :
@@ -300,15 +317,21 @@ icc)
     exit $stat
   fi
   rm -f "$depfile"
-  # Each line is of the form `foo.o: dependent.h',
-  # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+  # Each line is of the form 'foo.o: dependent.h',
+  # or 'foo.o: dep1.h dep2.h \', or ' dep3.h dep4.h \'.
   # Do two passes, one to just change these to
-  # `$object: dependent.h' and one to simply `dependent.h:'.
-  sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
-  # Some versions of the HPUX 10.20 sed can't process this invocation
-  # correctly.  Breaking it into two sed invocations is a workaround.
-  sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
-    sed -e 's/$/ :/' >> "$depfile"
+  # '$object: dependent.h' and one to simply 'dependent.h:'.
+  sed -e "s/^[ $tab][ $tab]*/  /" -e "s,^[^:]*:,$object :," \
+    < "$tmpdepfile" > "$depfile"
+  sed '
+    s/[ '"$tab"'][ '"$tab"']*/ /g
+    s/^ *//
+    s/ *\\*$//
+    s/^[^:]*: *//
+    /^$/d
+    /:$/d
+    s/$/ :/
+  ' < "$tmpdepfile" >> "$depfile"
   rm -f "$tmpdepfile"
   ;;
 
@@ -344,7 +367,7 @@ hp2)
   done
   if test -f "$tmpdepfile"; then
     sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
-    # Add `dependent.h:' lines.
+    # Add 'dependent.h:' lines.
     sed -ne '2,${
               s/^ *//
               s/ \\*$//
@@ -359,9 +382,9 @@ hp2)
 
 tru64)
    # The Tru64 compiler uses -MD to generate dependencies as a side
-   # effect.  `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+   # effect.  'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
    # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
-   # dependencies in `foo.d' instead, so we check for that too.
+   # dependencies in 'foo.d' instead, so we check for that too.
    # Subdirectories are respected.
    dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
    test "x$dir" = "x$object" && dir=
@@ -407,8 +430,7 @@ tru64)
    done
    if test -f "$tmpdepfile"; then
       sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
-      # That's a tab and a space in the [].
-      sed -e 's,^.*\.[a-z]*:[   ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+      sed -e 's,^.*\.[a-z]*:['"$tab"' ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
    else
       echo "#dummy" > "$depfile"
    fi
@@ -443,11 +465,11 @@ msvc7)
   p
 }' | $cygpath_u | sort -u | sed -n '
 s/ /\\ /g
-s/\(.*\)/      \1 \\/p
+s/\(.*\)/'"$tab"'\1 \\/p
 s/.\(.*\) \\/\1:/
 H
 $ {
-  s/.*/        /
+  s/.*/'"$tab"'/
   G
   p
 }' >> "$depfile"
@@ -478,7 +500,7 @@ dashmstdout)
     shift
   fi
 
-  # Remove `-o $object'.
+  # Remove '-o $object'.
   IFS=" "
   for arg
   do
@@ -498,15 +520,14 @@ dashmstdout)
   done
 
   test -z "$dashmflag" && dashmflag=-M
-  # Require at least two characters before searching for `:'
+  # Require at least two characters before searching for ':'
   # in the target name.  This is to cope with DOS-style filenames:
-  # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
+  # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
   "$@" $dashmflag |
-    sed 's:^[  ]*[^: ][^:][^:]*\:[    ]*:'"$object"'\: :' > "$tmpdepfile"
+    sed 's:^['"$tab"' ]*[^:'"$tab"' ][^:][^:]*\:['"$tab"' ]*:'"$object"'\: :' > "$tmpdepfile"
   rm -f "$depfile"
   cat < "$tmpdepfile" > "$depfile"
-  tr ' ' '
-' < "$tmpdepfile" | \
+  tr ' ' "$nl" < "$tmpdepfile" | \
 ## Some versions of the HPUX 10.20 sed can't process this invocation
 ## correctly.  Breaking it into two sed invocations is a workaround.
     sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
@@ -562,8 +583,7 @@ makedepend)
   # makedepend may prepend the VPATH from the source file name to the object.
   # No need to regex-escape $object, excess matching of '.' is harmless.
   sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
-  sed '1,2d' "$tmpdepfile" | tr ' ' '
-' | \
+  sed '1,2d' "$tmpdepfile" | tr ' ' "$nl" | \
 ## Some versions of the HPUX 10.20 sed can't process this invocation
 ## correctly.  Breaking it into two sed invocations is a workaround.
     sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
@@ -583,7 +603,7 @@ cpp)
     shift
   fi
 
-  # Remove `-o $object'.
+  # Remove '-o $object'.
   IFS=" "
   for arg
   do
@@ -652,8 +672,8 @@ msvisualcpp)
   sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
   rm -f "$depfile"
   echo "$object : \\" > "$depfile"
-  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::     \1 \\:p' >> "$depfile"
-  echo "       " >> "$depfile"
+  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
+  echo "$tab" >> "$depfile"
   sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
   rm -f "$tmpdepfile"
   ;;
index 71a0281..91371af 100644 (file)
@@ -87,6 +87,15 @@ Fields               string Name
                        key, a PSK passphrase or a passphrase for EAP
                        authentication methods.
 
+               string PreviousPassphrase
+
+                       The previous passphrase successfully saved, i.e.
+                       which lead to a successfull connection. This field is
+                       provided as an informational argument when connecting
+                       with it does not work anymore, for instance when it
+                       has been changed on the AP. Such argument appears when
+                       a RequestInput is raised after a retry.
+
                string WPS
 
                        This field requests the use of WPS to get associated.
@@ -115,7 +124,8 @@ Arguments   string Type
                string Requirement
 
                        Contains the requirement option. Valid values are
-                       "mandatory", "optional" or "alternate".
+                       "mandatory", "optional", "alternate" or
+                       "informational".
 
                        The "alternate" value specifies that this field can be
                        returned as an alternative to another one. An example
@@ -124,11 +134,20 @@ Arguments string Type
                        All "mandatory" fields must be returned, while the
                        "optional" can be returned if available.
 
+                       Nothing needs to be returned for "informational", as it
+                       is here only to provide an information so a value is
+                       attached to it.
+
                array{string} Alternates
 
                        Contains the list of alternate field names this
                        field can be represented by.
 
+               string Value
+
+                       Contains data as a string, relatively to an
+                       "informational" argument.
+
 Examples       Requesting a passphrase for WPA2 network
 
                        RequestInput("/service1",
@@ -138,6 +157,19 @@ Examples   Requesting a passphrase for WPA2 network
                                }
                        ==> { "Passphrase" : "secret123" }
 
+               Requesting a passphrase after an error on the previous one:
+
+                       RequestInput("/service1",
+                               { "Passphrase" : { "Type"        : "psk",
+                                                  "Requirement" : "mandatory"
+                                                },
+                                 "PreviousPassphrase" :
+                                       { "Type"       : "psk",
+                                         "Requirement : "informational",
+                                         "Value"      : "secret123"
+                                       }
+                               }
+
                Requesting name for hidden network
 
                        RequestInput("/service2",
index cf89c09..4f76832 100644 (file)
@@ -8,6 +8,12 @@ characters than letters or numbers and must have a .config suffix.
 Those configuration files are text files with a simple format and we typically
 have one file per provisioned network.
 
+If the config file is removed, then Connman tries to remove the
+provisioned service. If individual service entry inside config is removed,
+then the corresponding provisioned service is removed. If service
+entry is changed, then corresponding service is removed and then
+immediately re-provisioned.
+
 
 Global entry [global]
 =====================
@@ -25,26 +31,27 @@ Service entry [service_*]
 =========================
 
 Each provisioned service must start with the [service_*] tag. Replace * with
-your service identifier.
-The service identifier can be anything and will be used internally by connman
-to store the different services into an hash table.
+an identifier unique to the config file.
 
 Allowed fields:
 - Type: Service type. We currently only support wifi.
-- SSID: An hexadecimal or a string representation of a 802.11 SSID.
+- Name: A string representation of an 802.11 SSID. If the SSID field is
+  present, the Name field is ignored.
+- SSID: A hexadecimal representation of an 802.11 SSID. If the SSID field is
+  omitted, the Name field is used instead.
 - EAP: EAP type. We currently only support tls, ttls or peap.
 - CACertFile: File path to CA certificate file (PEM/DER).
 - ClientCertFile: File path to client certificate file (PEM/DER).
 - PrivateKeyFile: File path to client private key file (PEM/DER/PFX).
 - PrivateKeyPassphrase: Password/passphrase for private key file.
 - PrivateKeyPassphraseType: We only support the fsid passphrase type for now.
-This is for private keys generated by using their own filesystem UUID as the
-passphrase. The PrivateKeyPassphrase field is ignored when this field is set
-to fsid.
+  This is for private keys generated by using their own filesystem UUID as the
+  passphrase. The PrivateKeyPassphrase field is ignored when this field is set
+  to fsid.
 - Identity: Identity string for EAP.
 - Phase2: Phase2 (inner authentication with TLS tunnel) authentication method.
-Prefix the value with "EAP-" to indicate the usage of an EAP-based inner
-authentication method (should only be used with EAP = TTLS).
+  Prefix the value with "EAP-" to indicate the usage of an EAP-based inner
+  authentication method (should only be used with EAP = TTLS).
 - Passphrase: RSN/WPA/WPA2 Passphrase
 
 
index 084bc05..7cc6fb4 100644 (file)
@@ -5,11 +5,14 @@ Service               net.connman
 Interface      net.connman.Service
 Object path    [variable prefix]/{service0,service1,...}
 
-Methods                dict GetProperties()
+Methods                dict GetProperties()  [deprecated]
 
                        Returns properties for the service object. See
                        the properties section for available properties.
 
+                       Usage of this method is highly discouraged. Use
+                       the Manager.GetServices() method instead.
+
                        Possible Errors: [service].Error.InvalidArguments
 
                void SetProperty(string name, variant value)
@@ -147,10 +150,11 @@ Properties        string State [readonly]
                        The service name (for example "Wireless" etc.)
 
                        This name can be used for directly displaying it in
-                       the application. It has pure informational purpose.
+                       the application. It has pure informational purpose
+                       and no attempt should be made to translate it.
 
-                       For Ethernet devices and hidden WiFi networks it is
-                       not guaranteed that this property is present.
+                       For Ethernet devices and hidden WiFi networks this
+                       property is not present.
 
                string Type [readonly]
 
@@ -160,6 +164,9 @@ Properties  string State [readonly]
                        advanced properties or showing the correct icon
                        to the user.
 
+                       Together with a missing Name property, this can
+                       be used to identify hidden WiFi networks.
+
                array{string} Security [readonly]
 
                        If the service type is WiFi, then this property is
@@ -275,7 +282,9 @@ Properties  string State [readonly]
 
                array{string} Domains [readonly]
 
-                       The list of currently used search domains.
+                       The list of currently used search domains taken
+                       from Domains.Configurations if set, otherwise a
+                       domain name if provided by DHCP or VPNs.
 
                array{string} Domains.Configuration [readwrite]
 
index f7eb57a..6429776 100644 (file)
@@ -5,11 +5,14 @@ Service               net.connman
 Interface      net.connman.Technology
 Object path    [variable prefix]/{technology0,technology1,...}
 
-Methods                dict GetProperties()
+Methods                dict GetProperties()  [deprecated]
 
                        Returns properties for the technology object. See
                        the properties section for available properties.
 
+                       Usage of this method is highly discouraged. Use
+                       the Manager.GetTechnologies() method instead.
+
                        Possible Errors: [service].Error.InvalidArguments
 
                void SetProperty(string name, variant value)
@@ -26,7 +29,9 @@ Methods               dict GetProperties()
 
                        Trigger a scan for this specific technology. The
                        method call will return when a scan has been
-                       finished and results are available.
+                       finished and results are available. So setting
+                       a longer D-Bus timeout might be a really good
+                       idea.
 
                        Results will be signaled via the ServicesChanged
                        signal from the manager interface.
index a0583e6..0a8a27c 100644 (file)
@@ -85,16 +85,21 @@ typedef enum {
 typedef struct {
        const char *name;
        const char *signature;
-       const char *reply;
+} GDBusArgInfo;
+
+typedef struct {
+       const char *name;
        GDBusMethodFunction function;
        GDBusMethodFlags flags;
        unsigned int privilege;
+       const GDBusArgInfo *in_args;
+       const GDBusArgInfo *out_args;
 } GDBusMethodTable;
 
 typedef struct {
        const char *name;
-       const char *signature;
        GDBusSignalFlags flags;
+       const GDBusArgInfo *args;
 } GDBusSignalTable;
 
 typedef struct {
@@ -110,6 +115,51 @@ typedef struct {
        GDBusSecurityFunction function;
 } GDBusSecurityTable;
 
+#define GDBUS_ARGS(args...) (const GDBusArgInfo[]) { args, { } }
+
+#define GDBUS_METHOD(_name, _in_args, _out_args, _function) \
+       .name = _name, \
+       .in_args = _in_args, \
+       .out_args = _out_args, \
+       .function = _function
+
+#define GDBUS_ASYNC_METHOD(_name, _in_args, _out_args, _function) \
+       .name = _name, \
+       .in_args = _in_args, \
+       .out_args = _out_args, \
+       .function = _function, \
+       .flags = G_DBUS_METHOD_FLAG_ASYNC
+
+#define GDBUS_DEPRECATED_METHOD(_name, _in_args, _out_args, _function) \
+       .name = _name, \
+       .in_args = _in_args, \
+       .out_args = _out_args, \
+       .function = _function, \
+       .flags = G_DBUS_METHOD_FLAG_DEPRECATED
+
+#define GDBUS_DEPRECATED_ASYNC_METHOD(_name, _in_args, _out_args, _function) \
+       .name = _name, \
+       .in_args = _in_args, \
+       .out_args = _out_args, \
+       .function = _function, \
+       .flags = G_DBUS_METHOD_FLAG_ASYNC | G_DBUS_METHOD_FLAG_DEPRECATED
+
+#define GDBUS_NOREPLY_METHOD(_name, _in_args, _out_args, _function) \
+       .name = _name, \
+       .in_args = _in_args, \
+       .out_args = _out_args, \
+       .function = _function, \
+       .flags = G_DBUS_METHOD_FLAG_NOREPLY
+
+#define GDBUS_SIGNAL(_name, _args) \
+       .name = _name, \
+       .args = _args
+
+#define GDBUS_DEPRECATED_SIGNAL(_name, _args) \
+       .name = _name, \
+       .args = _args, \
+       .flags = G_DBUS_SIGNAL_FLAG_DEPRECATED
+
 gboolean g_dbus_register_interface(DBusConnection *connection,
                                        const char *path, const char *name,
                                        const GDBusMethodTable *methods,
index 8bc12f5..900e7ab 100644 (file)
@@ -59,63 +59,20 @@ struct security_data {
        void *iface_user_data;
 };
 
-static void print_arguments(GString *gstr, const char *sig,
+static void print_arguments(GString *gstr, const GDBusArgInfo *args,
                                                const char *direction)
 {
-       int i;
-
-       for (i = 0; sig[i]; i++) {
-               char type[32];
-               int struct_level, dict_level;
-               unsigned int len;
-               gboolean complete;
-
-               complete = FALSE;
-               struct_level = dict_level = 0;
-               memset(type, 0, sizeof(type));
-
-               /* Gather enough data to have a single complete type */
-               for (len = 0; len < (sizeof(type) - 1) && sig[i]; len++, i++) {
-                       switch (sig[i]) {
-                       case '(':
-                               struct_level++;
-                               break;
-                       case ')':
-                               struct_level--;
-                               if (struct_level <= 0 && dict_level <= 0)
-                                       complete = TRUE;
-                               break;
-                       case '{':
-                               dict_level++;
-                               break;
-                       case '}':
-                               dict_level--;
-                               if (struct_level <= 0 && dict_level <= 0)
-                                       complete = TRUE;
-                               break;
-                       case 'a':
-                               break;
-                       default:
-                               if (struct_level <= 0 && dict_level <= 0)
-                                       complete = TRUE;
-                               break;
-                       }
-
-                       type[len] = sig[i];
-
-                       if (complete)
-                               break;
-               }
-
+       for (; args && args->name; args++) {
+               g_string_append_printf(gstr,
+                                       "\t\t\t<arg name=\"%s\" type=\"%s\"",
+                                       args->name, args->signature);
 
                if (direction)
                        g_string_append_printf(gstr,
-                                       "\t\t\t<arg type=\"%s\" direction=\"%s\"/>\n",
-                                       type, direction);
+                                       " direction=\"%s\"/>\n", direction);
                else
-                       g_string_append_printf(gstr,
-                                       "\t\t\t<arg type=\"%s\"/>\n",
-                                       type);
+                       g_string_append_printf(gstr, "/>\n");
+
        }
 }
 
@@ -125,26 +82,47 @@ static void generate_interface_xml(GString *gstr, struct interface_data *iface)
        const GDBusSignalTable *signal;
 
        for (method = iface->methods; method && method->name; method++) {
-               if (!strlen(method->signature) && !strlen(method->reply))
+               gboolean deprecated = method->flags &
+                                               G_DBUS_METHOD_FLAG_DEPRECATED;
+               gboolean noreply = method->flags &
+                                               G_DBUS_METHOD_FLAG_NOREPLY;
+
+               if (!deprecated && !noreply &&
+                               !(method->in_args && method->in_args->name) &&
+                               !(method->out_args && method->out_args->name))
                        g_string_append_printf(gstr, "\t\t<method name=\"%s\"/>\n",
                                                                method->name);
                else {
                        g_string_append_printf(gstr, "\t\t<method name=\"%s\">\n",
                                                                method->name);
-                       print_arguments(gstr, method->signature, "in");
-                       print_arguments(gstr, method->reply, "out");
+                       print_arguments(gstr, method->in_args, "in");
+                       print_arguments(gstr, method->out_args, "out");
+
+                       if (deprecated)
+                               g_string_append_printf(gstr, "\t\t\t<annotation name=\"org.freedesktop.DBus.Deprecated\" value=\"true\"/>\n");
+
+                       if (noreply)
+                               g_string_append_printf(gstr, "\t\t\t<annotation name=\"org.freedesktop.DBus.Method.NoReply\" value=\"true\"/>\n");
+
                        g_string_append_printf(gstr, "\t\t</method>\n");
                }
        }
 
        for (signal = iface->signals; signal && signal->name; signal++) {
-               if (!strlen(signal->signature))
+               gboolean deprecated = signal->flags &
+                                               G_DBUS_SIGNAL_FLAG_DEPRECATED;
+
+               if (!deprecated && !(signal->args && signal->args->name))
                        g_string_append_printf(gstr, "\t\t<signal name=\"%s\"/>\n",
                                                                signal->name);
                else {
                        g_string_append_printf(gstr, "\t\t<signal name=\"%s\">\n",
                                                                signal->name);
-                       print_arguments(gstr, signal->signature, NULL);
+                       print_arguments(gstr, signal->args, NULL);
+
+                       if (deprecated)
+                               g_string_append_printf(gstr, "\t\t\t<annotation name=\"org.freedesktop.DBus.Deprecated\" value=\"true\"/>\n");
+
                        g_string_append_printf(gstr, "\t\t</signal>\n");
                }
        }
@@ -196,11 +174,6 @@ static DBusMessage *introspect(DBusConnection *connection,
        struct generic_data *data = user_data;
        DBusMessage *reply;
 
-       if (!dbus_message_has_signature(message, DBUS_TYPE_INVALID_AS_STRING)) {
-               error("Unexpected signature to introspect call");
-               return NULL;
-       }
-
        if (data->introspect == NULL)
                generate_introspection_xml(connection, data,
                                                dbus_message_get_path(message));
@@ -416,6 +389,27 @@ static struct interface_data *find_interface(GSList *interfaces,
        return NULL;
 }
 
+static gboolean g_dbus_args_have_signature(const GDBusArgInfo *args,
+                                                       DBusMessage *message)
+{
+       const char *sig = dbus_message_get_signature(message);
+       const char *p = NULL;
+
+       for (; args && args->signature && *sig; args++) {
+               p = args->signature;
+
+               for (; *sig && *p; sig++, p++) {
+                       if (*p != *sig)
+                               return FALSE;
+               }
+       }
+
+       if (*sig || (p && *p) || (args && args->signature))
+               return FALSE;
+
+       return TRUE;
+}
+
 static DBusHandlerResult generic_message(DBusConnection *connection,
                                        DBusMessage *message, void *user_data)
 {
@@ -436,8 +430,8 @@ static DBusHandlerResult generic_message(DBusConnection *connection,
                                                        method->name) == FALSE)
                        continue;
 
-               if (dbus_message_has_signature(message,
-                                               method->signature) == FALSE)
+               if (g_dbus_args_have_signature(method->in_args,
+                                                       message) == FALSE)
                        continue;
 
                if (check_privilege(connection, message, method,
@@ -491,8 +485,9 @@ done:
        g_free(parent_path);
 }
 
-static GDBusMethodTable introspect_methods[] = {
-       { "Introspect", "",     "s", introspect },
+static const GDBusMethodTable introspect_methods[] = {
+       { GDBUS_METHOD("Introspect", NULL,
+                       GDBUS_ARGS({ "xml", "s" }), introspect) },
        { }
 };
 
@@ -593,7 +588,7 @@ static void object_path_unref(DBusConnection *connection, const char *path)
 
 static gboolean check_signal(DBusConnection *conn, const char *path,
                                const char *interface, const char *name,
-                               const char **args)
+                               const GDBusArgInfo **args)
 {
        struct generic_data *data = NULL;
        struct interface_data *iface;
@@ -616,17 +611,13 @@ static gboolean check_signal(DBusConnection *conn, const char *path,
 
        for (signal = iface->signals; signal && signal->name; signal++) {
                if (!strcmp(signal->name, name)) {
-                       *args = signal->signature;
-                       break;
+                       *args = signal->args;
+                       return TRUE;
                }
        }
 
-       if (*args == NULL) {
-               error("No signal named %s on interface %s", name, interface);
-               return FALSE;
-       }
-
-       return TRUE;
+       error("No signal named %s on interface %s", name, interface);
+       return FALSE;
 }
 
 static dbus_bool_t emit_signal_valist(DBusConnection *conn,
@@ -638,7 +629,7 @@ static dbus_bool_t emit_signal_valist(DBusConnection *conn,
 {
        DBusMessage *signal;
        dbus_bool_t ret;
-       const char *signature, *args;
+       const GDBusArgInfo *args;
 
        if (!check_signal(conn, path, interface, name, &args))
                return FALSE;
@@ -653,8 +644,7 @@ static dbus_bool_t emit_signal_valist(DBusConnection *conn,
        if (!ret)
                goto fail;
 
-       signature = dbus_message_get_signature(signal);
-       if (strcmp(args, signature) != 0) {
+       if (g_dbus_args_have_signature(args, signal) == FALSE) {
                error("%s.%s: expected signature'%s' but got '%s'",
                                interface, name, args, signature);
                ret = FALSE;
index 9a716b0..d749176 100644 (file)
@@ -376,15 +376,14 @@ static gboolean filter_data_remove_callback(struct filter_data *data,
 
        connection = dbus_connection_ref(data->connection);
        listeners = g_slist_remove(listeners, data);
-       filter_data_free(data);
 
        /* Remove filter if there are no listeners left for the connection */
-       data = filter_data_find(connection, NULL, NULL, NULL, NULL, NULL,
-                                       NULL);
-       if (data == NULL)
+       if (filter_data_find(connection, NULL, NULL, NULL, NULL, NULL,
+                                                               NULL) == NULL)
                dbus_connection_remove_filter(connection, message_filter,
                                                NULL);
 
+       filter_data_free(data);
        dbus_connection_unref(connection);
 
        return TRUE;
@@ -537,15 +536,15 @@ static DBusHandlerResult message_filter(DBusConnection *connection,
        remove_match(data);
 
        listeners = g_slist_remove(listeners, data);
-       filter_data_free(data);
 
-       /* Remove filter if there no listener left for the connection */
-       data = filter_data_find(connection, NULL, NULL, NULL, NULL, NULL,
-                                       NULL);
-       if (data == NULL)
+       /* Remove filter if there are no listeners left for the connection */
+       if (filter_data_find(connection, NULL, NULL, NULL, NULL, NULL,
+                                                               NULL) == NULL)
                dbus_connection_remove_filter(connection, message_filter,
                                                NULL);
 
+       filter_data_free(data);
+
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 }
 
index b9f8da6..ec1b2a2 100644 (file)
@@ -1126,7 +1126,6 @@ static int ipv4ll_recv_arp_packet(GDHCPClient *dhcp_client)
        int target_conflict;
 
        memset(&arp, 0, sizeof(arp));
-       bytes = 0;
        bytes = read(dhcp_client->listener_sockfd, &arp, sizeof(arp));
        if (bytes < 0)
                return bytes;
@@ -1853,7 +1852,7 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
                        re = dhcp_recv_l3_packet(&packet,
                                                dhcp_client->listener_sockfd);
        } else if (dhcp_client->listen_mode == L_ARP) {
-               re = ipv4ll_recv_arp_packet(dhcp_client);
+               ipv4ll_recv_arp_packet(dhcp_client);
                return TRUE;
        }
        else
@@ -1866,6 +1865,9 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
                return TRUE;
 
        if (dhcp_client->type == G_DHCP_IPV6) {
+               if (packet6 == NULL)
+                       return TRUE;
+
                count = 0;
                client_id = dhcpv6_get_option(packet6, pkt_len,
                                G_DHCPV6_CLIENTID, &option_len, &count);
@@ -1898,8 +1900,11 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
                } else
                        dhcp_client->status_code = 0;
 
-       } else
+       } else {
                message_type = dhcp_get_option(&packet, DHCP_MESSAGE_TYPE);
+               if (message_type == NULL)
+                       return TRUE;
+       }
 
        if (message_type == NULL && client_id == NULL)
                /* No message type / client id option, ignore package */
index a267335..1a10291 100644 (file)
@@ -182,9 +182,14 @@ struct g_supplicant_bss {
        dbus_int16_t signal;
        GSupplicantMode mode;
        GSupplicantSecurity security;
+       dbus_bool_t rsn_selected;
+       unsigned int wpa_keymgmt;
+       unsigned int wpa_pairwise;
+       unsigned int wpa_group;
+       unsigned int rsn_keymgmt;
+       unsigned int rsn_pairwise;
+       unsigned int rsn_group;
        unsigned int keymgmt;
-       unsigned int pairwise;
-       unsigned int group;
        dbus_bool_t privacy;
        dbus_bool_t psk;
        dbus_bool_t ieee8021x;
@@ -432,6 +437,21 @@ static void remove_interface(gpointer data)
        g_hash_table_destroy(interface->net_mapping);
        g_hash_table_destroy(interface->network_table);
 
+       if (interface->scan_callback != NULL) {
+               SUPPLICANT_DBG("call interface %p callback %p scanning %d",
+                               interface, interface->scan_callback,
+                               interface->scanning);
+
+               interface->scan_callback(-EIO, interface, interface->scan_data);
+                interface->scan_callback = NULL;
+                interface->scan_data = NULL;
+
+               if (interface->scanning == TRUE) {
+                       interface->scanning = FALSE;
+                       callback_scan_finished(interface);
+               }
+       }
+
        callback_interface_removed(interface);
 
        g_free(interface->wps_cred.key);
@@ -1138,13 +1158,6 @@ static void add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
        network->frequency = bss->frequency;
        network->best_bss = bss;
 
-       network->wps = FALSE;
-       if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0) {
-               network->wps = TRUE;
-
-               network->wps_capabilities |= bss->wps_capabilities;
-       }
-
        SUPPLICANT_DBG("New network %s created", network->name);
 
        network->bss_table = g_hash_table_new_full(g_str_hash, g_str_equal,
@@ -1159,6 +1172,12 @@ static void add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
        callback_network_added(network);
 
 done:
+       /* We update network's WPS properties if only bss provides WPS. */
+       if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0) {
+               network->wps = TRUE;
+               network->wps_capabilities |= bss->wps_capabilities;
+       }
+
        if (bss->signal > network->signal) {
                network->signal = bss->signal;
                network->best_bss = bss;
@@ -1186,7 +1205,7 @@ static void bss_rates(DBusMessageIter *iter, void *user_data)
 
 static void bss_keymgmt(DBusMessageIter *iter, void *user_data)
 {
-       struct g_supplicant_bss *bss = user_data;
+       unsigned int *keymgmt = user_data;
        const char *str = NULL;
        int i;
 
@@ -1196,14 +1215,15 @@ static void bss_keymgmt(DBusMessageIter *iter, void *user_data)
 
        for (i = 0; keymgmt_map[i].str != NULL; i++)
                if (strcmp(str, keymgmt_map[i].str) == 0) {
-                       bss->keymgmt |= keymgmt_map[i].val;
+                       SUPPLICANT_DBG("Keymgmt: %s", str);
+                       *keymgmt |= keymgmt_map[i].val;
                        break;
                }
 }
 
 static void bss_group(DBusMessageIter *iter, void *user_data)
 {
-       struct g_supplicant_bss *bss = user_data;
+       unsigned int *group = user_data;
        const char *str = NULL;
        int i;
 
@@ -1213,14 +1233,15 @@ static void bss_group(DBusMessageIter *iter, void *user_data)
 
        for (i = 0; group_map[i].str != NULL; i++)
                if (strcmp(str, group_map[i].str) == 0) {
-                       bss->group |= group_map[i].val;
+                       SUPPLICANT_DBG("Group: %s", str);
+                       *group |= group_map[i].val;
                        break;
                }
 }
 
 static void bss_pairwise(DBusMessageIter *iter, void *user_data)
 {
-       struct g_supplicant_bss *bss = user_data;
+       unsigned int *pairwise = user_data;
        const char *str = NULL;
        int i;
 
@@ -1230,7 +1251,8 @@ static void bss_pairwise(DBusMessageIter *iter, void *user_data)
 
        for (i = 0; pairwise_map[i].str != NULL; i++)
                if (strcmp(str, pairwise_map[i].str) == 0) {
-                       bss->pairwise |= pairwise_map[i].val;
+                       SUPPLICANT_DBG("Pairwise: %s", str);
+                       *pairwise |= pairwise_map[i].val;
                        break;
                }
 }
@@ -1238,13 +1260,33 @@ static void bss_pairwise(DBusMessageIter *iter, void *user_data)
 static void bss_wpa(const char *key, DBusMessageIter *iter,
                        void *user_data)
 {
-       if (g_strcmp0(key, "KeyMgmt") == 0)
-               supplicant_dbus_array_foreach(iter, bss_keymgmt, user_data);
-       else if (g_strcmp0(key, "Group") == 0)
-               supplicant_dbus_array_foreach(iter, bss_group, user_data);
-       else if (g_strcmp0(key, "Pairwise") == 0)
-               supplicant_dbus_array_foreach(iter, bss_pairwise, user_data);
+       struct g_supplicant_bss *bss = user_data;
+       unsigned int value = 0;
+
+       SUPPLICANT_DBG("Key: %s", key);
+
+       if (g_strcmp0(key, "KeyMgmt") == 0) {
+               supplicant_dbus_array_foreach(iter, bss_keymgmt, &value);
 
+               if (bss->rsn_selected == TRUE)
+                       bss->rsn_keymgmt = value;
+               else
+                       bss->wpa_keymgmt = value;
+       } else if (g_strcmp0(key, "Group") == 0) {
+               supplicant_dbus_array_foreach(iter, bss_group, &value);
+
+               if (bss->rsn_selected == TRUE)
+                       bss->rsn_group = value;
+               else
+                       bss->wpa_group = value;
+       } else if (g_strcmp0(key, "Pairwise") == 0) {
+               supplicant_dbus_array_foreach(iter, bss_pairwise, &value);
+
+               if (bss->rsn_selected == TRUE)
+                       bss->rsn_pairwise = value;
+               else
+                       bss->wpa_pairwise = value;
+       }
 }
 
 static unsigned int get_tlv(unsigned char *ie, unsigned int ie_size,
@@ -1315,6 +1357,9 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
        if (ie == NULL || ie_len < 2)
                return;
 
+       bss->wps_capabilities = 0;
+       bss->keymgmt = 0;
+
        for (ie_end = ie + ie_len; ie < ie_end && ie + ie[1] + 1 <= ie_end;
                                                        ie += ie[1] + 2) {
 
@@ -1356,6 +1401,26 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
 
 static void bss_compute_security(struct g_supplicant_bss *bss)
 {
+       /*
+        * Combining RSN and WPA keymgmt
+        * We combine it since parsing IEs might have set something for WPS. */
+       bss->keymgmt |= bss->rsn_keymgmt | bss->wpa_keymgmt;
+
+       bss->ieee8021x = FALSE;
+       bss->psk = FALSE;
+
+       if (bss->keymgmt &
+                       (G_SUPPLICANT_KEYMGMT_WPA_EAP |
+                               G_SUPPLICANT_KEYMGMT_WPA_FT_EAP |
+                               G_SUPPLICANT_KEYMGMT_WPA_EAP_256))
+               bss->ieee8021x = TRUE;
+
+       if (bss->keymgmt &
+                       (G_SUPPLICANT_KEYMGMT_WPA_PSK |
+                               G_SUPPLICANT_KEYMGMT_WPA_FT_PSK |
+                               G_SUPPLICANT_KEYMGMT_WPA_PSK_256))
+               bss->psk = TRUE;
+
        if (bss->ieee8021x == TRUE)
                bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
        else if (bss->psk == TRUE)
@@ -1450,21 +1515,14 @@ static void bss_property(const char *key, DBusMessageIter *iter,
 
                dbus_message_iter_get_basic(iter, &privacy);
                bss->privacy = privacy;
-       } else if ((g_strcmp0(key, "RSN") == 0) ||
-                       (g_strcmp0(key, "WPA") == 0)) {
-               supplicant_dbus_property_foreach(iter, bss_wpa, bss);
+       } else if (g_strcmp0(key, "RSN") == 0) {
+               bss->rsn_selected = TRUE;
 
-               if (bss->keymgmt &
-                       (G_SUPPLICANT_KEYMGMT_WPA_EAP |
-                               G_SUPPLICANT_KEYMGMT_WPA_FT_EAP |
-                               G_SUPPLICANT_KEYMGMT_WPA_EAP_256))
-                       bss->ieee8021x = TRUE;
+               supplicant_dbus_property_foreach(iter, bss_wpa, bss);
+       } else if (g_strcmp0(key, "WPA") == 0) {
+               bss->rsn_selected = FALSE;
 
-               if (bss->keymgmt &
-                       (G_SUPPLICANT_KEYMGMT_WPA_PSK |
-                               G_SUPPLICANT_KEYMGMT_WPA_FT_PSK |
-                               G_SUPPLICANT_KEYMGMT_WPA_PSK_256))
-                       bss->psk = TRUE;
+               supplicant_dbus_property_foreach(iter, bss_wpa, bss);
        } else if (g_strcmp0(key, "IEs") == 0)
                bss_process_ies(iter, bss);
        else
@@ -1698,23 +1756,6 @@ static void interface_property(const char *key, DBusMessageIter *iter,
        } else
                SUPPLICANT_DBG("key %s type %c",
                                key, dbus_message_iter_get_arg_type(iter));
-
-       if (key != NULL) {
-               debug_strvalmap("000 KeyMgmt capability", keymgmt_map,
-                                               interface->keymgmt_capa);
-               debug_strvalmap("000 AuthAlg capability", authalg_capa_map,
-                                               interface->authalg_capa);
-               debug_strvalmap("000 Protocol capability", proto_capa_map,
-                                               interface->proto_capa);
-               debug_strvalmap("000 Pairwise capability", pairwise_map,
-                                               interface->pairwise_capa);
-               debug_strvalmap("000 Group capability", group_map,
-                                               interface->group_capa);
-               debug_strvalmap("000 Scan capability", scan_capa_map,
-                                               interface->scan_capa);
-               debug_strvalmap("000 Mode capability", mode_capa_map,
-                                               interface->mode_capa);
-       }
 }
 
 static void scan_network_update(DBusMessageIter *iter, void *user_data)
@@ -2077,7 +2118,7 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter)
                /* Security change policy:
                 * - we first copy the current bss into a new one with
                 * its own pointer (path)
-                * - we remove the current bss related nework which will
+                * - we remove the current bss related network which will
                 * tell the plugin about such removal. This is done due
                 * to the fact that a security change means a group change
                 * so a complete network change.
@@ -2396,7 +2437,7 @@ static void interface_create_result(const char *error,
        SUPPLICANT_DBG("");
 
        if (error != NULL) {
-               g_critical("error %s", error);
+               g_warning("error %s", error);
                err = -EIO;
                goto done;
        }
@@ -2469,7 +2510,6 @@ static void interface_get_result(const char *error,
 
        if (error != NULL) {
                SUPPLICANT_DBG("Interface not created yet");
-               err = -EIO;
                goto create;
        }
 
@@ -2979,17 +3019,49 @@ static dbus_bool_t is_psk_raw_key(const char *psk)
        return TRUE;
 }
 
+static unsigned char hexchar2bin(char c)
+{
+       if ((c >= '0') && (c <= '9'))
+               return c - '0';
+       else if ((c >= 'A') && (c <= 'F'))
+               return c - 'A' + 10;
+       else if ((c >= 'a') && (c <= 'f'))
+               return c - 'a' + 10;
+       else
+               return c;
+}
+
+static void hexstring2bin(const char *string, unsigned char *data, size_t data_len)
+{
+       size_t i;
+
+       for (i = 0; i < data_len; i++)
+               data[i] = (hexchar2bin(string[i * 2 + 0]) << 4 |
+                          hexchar2bin(string[i * 2 + 1]) << 0);
+}
+
 static void add_network_security_psk(DBusMessageIter *dict,
                                        GSupplicantSSID *ssid)
 {
        if (ssid->passphrase && strlen(ssid->passphrase) > 0) {
-               if (is_psk_raw_key(ssid->passphrase) == TRUE)
+               const char *key = "psk";
+
+               if (is_psk_raw_key(ssid->passphrase) == TRUE) {
+                       unsigned char data[32];
+                       unsigned char *datap = data;
+
+                       /* The above pointer alias is required by D-Bus because
+                        * with D-Bus and GCC, non-heap-allocated arrays cannot
+                        * be passed directly by their base pointer. */
+
+                       hexstring2bin(ssid->passphrase, datap, sizeof(data));
+
                        supplicant_dbus_dict_append_fixed_array(dict,
-                                                       "psk", DBUS_TYPE_BYTE,
-                                                       &ssid->passphrase, 64);
-               else
-                       supplicant_dbus_dict_append_basic(dict, "psk",
-                                                       DBUS_TYPE_STRING,
+                                                       key, DBUS_TYPE_BYTE,
+                                                       &datap, sizeof(data));
+               else
+                       supplicant_dbus_dict_append_basic(dict,
+                                                       key, DBUS_TYPE_STRING,
                                                        &ssid->passphrase);
        }
 }
index f7f5faa..47ff8c4 100644 (file)
@@ -408,6 +408,11 @@ static ssize_t g_io_gnutls_pull_func(gnutls_transport_ptr_t transport_data,
        return result;
 }
 
+gboolean g_io_channel_supports_tls(void)
+{
+       return TRUE;
+}
+
 GIOChannel *g_io_channel_gnutls_new(int fd)
 {
        GIOGnuTLSChannel *gnutls_channel;
index 4131317..f16c75d 100644 (file)
@@ -21,4 +21,6 @@
 
 #include <glib.h>
 
+gboolean g_io_channel_supports_tls(void);
+
 GIOChannel *g_io_channel_gnutls_new(int fd);
index 75b20a3..88db3e4 100644 (file)
 
 #include "giognutls.h"
 
+gboolean g_io_channel_supports_tls(void)
+{
+       return FALSE;
+}
+
 GIOChannel *g_io_channel_gnutls_new(int fd)
 {
        return NULL;
index cd5a5bf..e93bf4f 100644 (file)
@@ -607,8 +607,10 @@ static void add_result(struct resolv_lookup *lookup, int family,
                                                        const void *data)
 {
        int n = lookup->nr_results++;
-       lookup->results = g_realloc(lookup->results,
+       lookup->results = g_try_realloc(lookup->results,
                                        sizeof(struct sort_result) * (n + 1));
+       if (lookup->results == NULL)
+               return;
 
        memset(&lookup->results[n], 0, sizeof(struct sort_result));
 
index 8071536..27ed634 100644 (file)
@@ -266,6 +266,11 @@ void g_web_unref(GWeb *web)
        g_free(web);
 }
 
+gboolean g_web_supports_tls(void)
+{
+       return g_io_channel_supports_tls();
+}
+
 void g_web_set_debug(GWeb *web, GWebDebugFunc func, gpointer user_data)
 {
        if (web == NULL)
index 06de0d4..104345e 100644 (file)
@@ -55,6 +55,8 @@ void g_web_unref(GWeb *web);
 
 void g_web_set_debug(GWeb *web, GWebDebugFunc func, gpointer user_data);
 
+gboolean g_web_supports_tls(void);
+
 gboolean g_web_set_proxy(GWeb *web, const char *proxy);
 
 gboolean g_web_set_address_family(GWeb *web, int family);
index abfa228..f787cf4 100644 (file)
@@ -82,6 +82,7 @@ int connman_device_set_powered(struct connman_device *device,
                                                connman_bool_t powered);
 int connman_device_set_scanning(struct connman_device *device,
                                                connman_bool_t scanning);
+connman_bool_t connman_device_get_scanning(struct connman_device *device);
 void connman_device_reset_scanning(struct connman_device *device);
 
 int connman_device_set_disconnected(struct connman_device *device,
@@ -119,7 +120,8 @@ struct connman_device_driver {
        int (*scan_fast) (struct connman_device *device);
        int (*scan_hidden)(struct connman_device *device,
                        const char *ssid, unsigned int ssid_len,
-                       const char *identity, const char* passphrase);
+                       const char *identity, const char* passphrase,
+                       void *user_data);
 };
 
 int connman_device_driver_register(struct connman_device_driver *driver);
index aa67573..8b9b390 100644 (file)
@@ -80,6 +80,7 @@ int connman_inet_setup_tunnel(char *tunnel, int mtu);
 int connman_inet_create_tunnel(char **iface);
 int connman_inet_get_dest_addr(int index, char **dest);
 int connman_inet_ipv6_get_dest_addr(int index, char **dest);
+int connman_inet_check_ipaddress(const char *host);
 connman_bool_t connman_inet_check_hostname(const char *ptr, size_t len);
 
 #ifdef __cplusplus
index 12b0621..3945a54 100644 (file)
@@ -102,8 +102,9 @@ connman_bool_t connman_network_get_connected(struct connman_network *network);
 
 connman_bool_t connman_network_get_associating(struct connman_network *network);
 
+void connman_network_clear_hidden(void *user_data);
 int connman_network_connect_hidden(struct connman_network *network,
-                               char *identity, char* passphrase);
+                       char *identity, char* passphrase, void *user_data);
 
 void connman_network_set_ipv4_method(struct connman_network *network,
                                        enum connman_ipconfig_method method);
index 6503388..e867a78 100644 (file)
@@ -32,6 +32,9 @@ connman_bool_t connman_setting_get_bool(const char *key);
 char **connman_setting_get_string_list(const char *key);
 unsigned int *connman_setting_get_uint_list(const char *key);
 
+unsigned int connman_timeout_input_request(void);
+unsigned int connman_timeout_browser_launch(void);
+
 #ifdef __cplusplus
 }
 #endif
index e7b9ed7..45a937d 100644 (file)
@@ -1,6 +1,6 @@
 Name:       connman
 Summary:    Connection Manager
-Version:    1.0
+Version:    1.3
 Release:    1
 Group:      System/Networking
 License:    GPLv2
index d132870..6f476e2 100644 (file)
@@ -885,9 +885,24 @@ static void bluetooth_disconnect(DBusConnection *connection, void *user_data)
 
 static int bluetooth_probe(struct connman_device *device)
 {
+       GHashTableIter iter;
+       gpointer key, value;
+
        DBG("device %p", device);
 
-       return 0;
+       if (bluetooth_devices == NULL)
+               return -ENOTSUP;
+
+       g_hash_table_iter_init(&iter, bluetooth_devices);
+
+       while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+               struct connman_device *device_pan = value;
+
+               if (device == device_pan)
+                       return 0;
+       }
+
+       return -ENOTSUP;
 }
 
 static void bluetooth_remove(struct connman_device *device)
@@ -1179,33 +1194,34 @@ static int bluetooth_init(void)
        watch = g_dbus_add_service_watch(connection, BLUEZ_SERVICE,
                        bluetooth_connect, bluetooth_disconnect, NULL, NULL);
 
-       added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+       added_watch = g_dbus_add_signal_watch(connection, BLUEZ_SERVICE, NULL,
                                                BLUEZ_MANAGER_INTERFACE,
                                                ADAPTER_ADDED, adapter_added,
                                                NULL, NULL);
 
-       removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+       removed_watch = g_dbus_add_signal_watch(connection, BLUEZ_SERVICE, NULL,
                                                BLUEZ_MANAGER_INTERFACE,
                                                ADAPTER_REMOVED, adapter_removed,
                                                NULL, NULL);
 
-       adapter_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
-                                               BLUEZ_ADAPTER_INTERFACE,
+       adapter_watch = g_dbus_add_signal_watch(connection, BLUEZ_SERVICE,
+                                               NULL, BLUEZ_ADAPTER_INTERFACE,
                                                PROPERTY_CHANGED, adapter_changed,
                                                NULL, NULL);
 
-       device_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+       device_removed_watch = g_dbus_add_signal_watch(connection,
+                                               BLUEZ_SERVICE, NULL,
                                                BLUEZ_ADAPTER_INTERFACE,
                                                DEVICE_REMOVED, device_removed,
                                                NULL, NULL);
 
-       device_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+       device_watch = g_dbus_add_signal_watch(connection, BLUEZ_SERVICE, NULL,
                                                BLUEZ_DEVICE_INTERFACE,
                                                PROPERTY_CHANGED, device_changed,
                                                NULL, NULL);
 
-       network_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
-                                               BLUEZ_NETWORK_INTERFACE,
+       network_watch = g_dbus_add_signal_watch(connection, BLUEZ_SERVICE,
+                                               NULL, BLUEZ_NETWORK_INTERFACE,
                                                PROPERTY_CHANGED, network_changed,
                                                NULL, NULL);
 
diff --git a/plugins/dundee.c b/plugins/dundee.c
new file mode 100644 (file)
index 0000000..d0ecdef
--- /dev/null
@@ -0,0 +1,852 @@
+/*
+ *
+ *  Connection Manager
+ *
+ *  Copyright (C) 2012  BMW Car IT GmbH. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <errno.h>
+
+#include <gdbus.h>
+
+#define CONNMAN_API_SUBJECT_TO_CHANGE
+#include <connman/plugin.h>
+#include <connman/device.h>
+#include <connman/network.h>
+#include <connman/inet.h>
+#include <connman/dbus.h>
+
+#define DUNDEE_SERVICE                 "org.ofono.dundee"
+#define DUNDEE_MANAGER_INTERFACE       DUNDEE_SERVICE ".Manager"
+#define DUNDEE_DEVICE_INTERFACE                DUNDEE_SERVICE ".Device"
+
+#define DEVICE_ADDED                   "DeviceAdded"
+#define DEVICE_REMOVED                 "DeviceRemoved"
+#define PROPERTY_CHANGED               "PropertyChanged"
+
+#define GET_PROPERTIES                 "GetProperties"
+#define SET_PROPERTY                   "SetProperty"
+#define GET_DEVICES                    "GetDevices"
+
+#define TIMEOUT 40000
+
+static DBusConnection *connection;
+
+static GHashTable *dundee_devices = NULL;
+
+struct dundee_data {
+       char *path;
+       char *name;
+
+       struct connman_device *device;
+       struct connman_network *network;
+
+       connman_bool_t active;
+
+       int index;
+
+       /* IPv4 Settings */
+       enum connman_ipconfig_method method;
+       struct connman_ipaddress *address;
+       char *nameservers;
+
+       DBusPendingCall *call;
+};
+
+static char *get_ident(const char *path)
+{
+       char *pos;
+
+       if (*path != '/')
+               return NULL;
+
+       pos = strrchr(path, '/');
+       if (pos == NULL)
+               return NULL;
+
+       return pos + 1;
+}
+
+static void create_device(struct dundee_data *info)
+{
+       struct connman_device *device;
+       char *ident;
+
+       DBG("%s", info->path);
+
+       ident = g_strdup(get_ident(info->path));
+       device = connman_device_create(ident, CONNMAN_DEVICE_TYPE_BLUETOOTH);
+       if (device == NULL)
+               goto out;
+
+       DBG("device %p", device);
+
+       connman_device_set_ident(device, ident);
+
+       connman_device_set_string(device, "Path", info->path);
+
+       connman_device_set_data(device, info);
+
+       if (connman_device_register(device) < 0) {
+               connman_error("Failed to register DUN device");
+               connman_device_unref(device);
+               goto out;
+       }
+
+       info->device = device;
+
+out:
+       g_free(ident);
+}
+
+static void destroy_device(struct dundee_data *info)
+{
+       connman_device_set_powered(info->device, FALSE);
+
+       if (info->call != NULL)
+               dbus_pending_call_cancel(info->call);
+
+       if (info->network != NULL) {
+               connman_device_remove_network(info->device, info->network);
+               connman_network_unref(info->network);
+               info->network = NULL;
+       }
+
+       connman_device_unregister(info->device);
+       connman_device_unref(info->device);
+
+       info->device = NULL;
+}
+
+static void device_destroy(gpointer data)
+{
+       struct dundee_data *info = data;
+
+       if (info->device != NULL)
+               destroy_device(info);
+
+       g_free(info->path);
+       g_free(info->name);
+
+       g_free(info);
+}
+
+static void create_network(struct dundee_data *info)
+{
+       struct connman_network *network;
+       const char *group;
+
+       DBG("%s", info->path);
+
+       network = connman_network_create(info->path,
+                               CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN);
+       if (network == NULL)
+               return;
+
+       DBG("network %p", network);
+
+       connman_network_set_data(network, info);
+
+       connman_network_set_string(network, "Path",
+                               info->path);
+
+       connman_network_set_name(network, info->name);
+
+       group = get_ident(info->path);
+       connman_network_set_group(network, group);
+
+       connman_network_set_available(network, TRUE);
+
+       if (connman_device_add_network(info->device, network) < 0) {
+               connman_network_unref(network);
+               return;
+       }
+
+       info->network = network;
+}
+
+static void set_connected(struct dundee_data *info)
+{
+       DBG("%s", info->path);
+
+       connman_inet_ifup(info->index);
+
+       connman_network_set_index(info->network, info->index);
+       connman_network_set_ipv4_method(info->network,
+                                       CONNMAN_IPCONFIG_METHOD_FIXED);
+       connman_network_set_ipaddress(info->network, info->address);
+       connman_network_set_nameservers(info->network, info->nameservers);
+
+       connman_network_set_connected(info->network, TRUE);
+}
+
+static void set_disconnected(struct dundee_data *info)
+{
+       DBG("%s", info->path);
+
+       connman_network_set_connected(info->network, FALSE);
+       connman_inet_ifdown(info->index);
+}
+
+static void set_property_reply(DBusPendingCall *call, void *user_data)
+{
+       struct dundee_data *info = user_data;
+       DBusMessage *reply;
+       DBusError error;
+
+       DBG("%s", info->path);
+
+       info->call = NULL;
+
+       dbus_error_init(&error);
+
+       reply = dbus_pending_call_steal_reply(call);
+
+       if (dbus_set_error_from_message(&error, reply)) {
+               connman_error("Failed to change property: %s %s %s",
+                               info->path, error.name, error.message);
+               dbus_error_free(&error);
+
+               connman_network_set_error(info->network,
+                                       CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
+       }
+
+       dbus_message_unref(reply);
+
+       dbus_pending_call_unref(call);
+}
+
+static int set_property(struct dundee_data *info,
+                       const char *property, int type, void *value)
+{
+       DBusMessage *message;
+       DBusMessageIter iter;
+
+       DBG("%s %s", info->path, property);
+
+       message = dbus_message_new_method_call(DUNDEE_SERVICE, info->path,
+                                       DUNDEE_DEVICE_INTERFACE, SET_PROPERTY);
+       if (message == NULL)
+               return -ENOMEM;
+
+       dbus_message_iter_init_append(message, &iter);
+       connman_dbus_property_append_basic(&iter, property, type, value);
+
+       if (dbus_connection_send_with_reply(connection, message,
+                       &info->call, TIMEOUT) == FALSE) {
+               connman_error("Failed to change property: %s %s",
+                               info->path, property);
+               dbus_message_unref(message);
+               return -EINVAL;
+       }
+
+       if (info->call == NULL) {
+               connman_error("D-Bus connection not available");
+               dbus_message_unref(message);
+               return -EINVAL;
+       }
+
+       dbus_pending_call_set_notify(info->call, set_property_reply,
+                                       info, NULL);
+
+       dbus_message_unref(message);
+
+       return -EINPROGRESS;
+}
+
+static int device_set_active(struct dundee_data *info)
+{
+       dbus_bool_t active = TRUE;
+
+       DBG("%s", info->path);
+
+       return set_property(info, "Active", DBUS_TYPE_BOOLEAN,
+                               &active);
+}
+
+static int device_set_inactive(struct dundee_data *info)
+{
+       dbus_bool_t active = FALSE;
+       int err;
+
+       DBG("%s", info->path);
+
+       err = set_property(info, "Active", DBUS_TYPE_BOOLEAN,
+                               &active);
+       if (err == -EINPROGRESS)
+               return 0;
+
+       return err;
+}
+
+static int network_probe(struct connman_network *network)
+{
+       DBG("network %p", network);
+
+       return 0;
+}
+
+static void network_remove(struct connman_network *network)
+{
+       DBG("network %p", network);
+}
+
+static int network_connect(struct connman_network *network)
+{
+       struct dundee_data *info = connman_network_get_data(network);
+
+       DBG("network %p", network);
+
+       return device_set_active(info);
+}
+
+static int network_disconnect(struct connman_network *network)
+{
+       struct dundee_data *info = connman_network_get_data(network);
+
+       DBG("network %p", network);
+
+       return device_set_inactive(info);
+}
+
+static struct connman_network_driver network_driver = {
+       .name           = "network",
+       .type           = CONNMAN_NETWORK_TYPE_BLUETOOTH_DUN,
+       .probe          = network_probe,
+       .remove         = network_remove,
+       .connect        = network_connect,
+       .disconnect     = network_disconnect,
+};
+
+static int dundee_probe(struct connman_device *device)
+{
+       GHashTableIter iter;
+       gpointer key, value;
+
+       DBG("device %p", device);
+
+       if (dundee_devices == NULL)
+               return -ENOTSUP;
+
+       g_hash_table_iter_init(&iter, dundee_devices);
+
+       while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+               struct dundee_data *info = value;
+
+               if (device == info->device)
+                       return 0;
+       }
+
+       return -ENOTSUP;
+}
+
+static void dundee_remove(struct connman_device *device)
+{
+       DBG("device %p", device);
+}
+
+static int dundee_enable(struct connman_device *device)
+{
+       DBG("device %p", device);
+
+       return 0;
+}
+
+static int dundee_disable(struct connman_device *device)
+{
+       DBG("device %p", device);
+
+       return 0;
+}
+
+static struct connman_device_driver dundee_driver = {
+       .name           = "dundee",
+       .type           = CONNMAN_DEVICE_TYPE_BLUETOOTH,
+       .probe          = dundee_probe,
+       .remove         = dundee_remove,
+       .enable         = dundee_enable,
+       .disable        = dundee_disable,
+};
+
+static char *extract_nameservers(DBusMessageIter *array)
+{
+       DBusMessageIter entry;
+       char *nameservers = NULL;
+       char *tmp;
+
+       dbus_message_iter_recurse(array, &entry);
+
+       while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
+               const char *nameserver;
+
+               dbus_message_iter_get_basic(&entry, &nameserver);
+
+               if (nameservers == NULL) {
+                       nameservers = g_strdup(nameserver);
+               } else {
+                       tmp = nameservers;
+                       nameservers = g_strdup_printf("%s %s", tmp, nameserver);
+                       g_free(tmp);
+               }
+
+               dbus_message_iter_next(&entry);
+       }
+
+       return nameservers;
+}
+
+static void extract_settings(DBusMessageIter *array,
+                               struct dundee_data *info)
+{
+       DBusMessageIter dict;
+       char *address = NULL, *gateway = NULL;
+       char *nameservers = NULL;
+       const char *interface = NULL;
+       int index = -1;
+
+       if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
+               return;
+
+       dbus_message_iter_recurse(array, &dict);
+
+       while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+               DBusMessageIter entry, value;
+               const char *key, *val;
+
+               dbus_message_iter_recurse(&dict, &entry);
+               dbus_message_iter_get_basic(&entry, &key);
+
+               dbus_message_iter_next(&entry);
+               dbus_message_iter_recurse(&entry, &value);
+
+               if (g_str_equal(key, "Interface") == TRUE) {
+                       dbus_message_iter_get_basic(&value, &interface);
+
+                       DBG("Interface %s", interface);
+
+                       index = connman_inet_ifindex(interface);
+
+                       DBG("index %d", index);
+
+                       if (index < 0)
+                               break;
+               } else if (g_str_equal(key, "Address") == TRUE) {
+                       dbus_message_iter_get_basic(&value, &val);
+
+                       address = g_strdup(val);
+
+                       DBG("Address %s", address);
+               } else if (g_str_equal(key, "DomainNameServers") == TRUE) {
+                       nameservers = extract_nameservers(&value);
+
+                       DBG("Nameservers %s", nameservers);
+               } else if (g_str_equal(key, "Gateway") == TRUE) {
+                       dbus_message_iter_get_basic(&value, &val);
+
+                       gateway = g_strdup(val);
+
+                       DBG("Gateway %s", gateway);
+               }
+
+               dbus_message_iter_next(&dict);
+       }
+
+       if (index < 0)
+               goto out;
+
+       info->address = connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4);
+       if (info->address == NULL)
+               goto out;
+
+       info->index = index;
+       connman_ipaddress_set_ipv4(info->address, address, NULL, gateway);
+
+       info->nameservers = nameservers;
+
+out:
+       if (info->nameservers != nameservers)
+               g_free(nameservers);
+
+       g_free(address);
+       g_free(gateway);
+}
+
+static gboolean device_changed(DBusConnection *connection,
+                               DBusMessage *message,
+                               void *user_data)
+{
+       const char *path = dbus_message_get_path(message);
+       struct dundee_data *info = NULL;
+       DBusMessageIter iter, value;
+       const char *key;
+       const char *signature = DBUS_TYPE_STRING_AS_STRING
+               DBUS_TYPE_VARIANT_AS_STRING;
+
+       if (dbus_message_has_signature(message, signature) == FALSE) {
+               connman_error("dundee signature does not match");
+               return TRUE;
+       }
+
+       info = g_hash_table_lookup(dundee_devices, path);
+       if (info == NULL)
+               return TRUE;
+
+       if (dbus_message_iter_init(message, &iter) == FALSE)
+               return TRUE;
+
+       dbus_message_iter_get_basic(&iter, &key);
+
+       dbus_message_iter_next(&iter);
+       dbus_message_iter_recurse(&iter, &value);
+
+       /*
+        * Dundee guarantees the ordering of Settings and
+        * Active. Settings will always be send before Active = True.
+        * That means we don't have to order here.
+        */
+       if (g_str_equal(key, "Active") == TRUE) {
+               dbus_message_iter_get_basic(&value, &info->active);
+
+               DBG("%s Active %d", info->path, info->active);
+
+               if (info->active == TRUE)
+                       set_connected(info);
+               else
+                       set_disconnected(info);
+       } else if (g_str_equal(key, "Settings") == TRUE) {
+               DBG("%s Settings", info->path);
+
+               extract_settings(&value, info);
+       } else if (g_str_equal(key, "Name") == TRUE) {
+               char *name;
+
+               dbus_message_iter_get_basic(&value, &name);
+
+               g_free(info->name);
+               info->name = g_strdup(name);
+
+               DBG("%s Name %s", info->path, info->name);
+
+               connman_network_set_name(info->network, info->name);
+               connman_network_update(info->network);
+       }
+
+       return TRUE;
+}
+
+static void add_device(const char *path, DBusMessageIter *properties)
+{
+       struct dundee_data *info;
+
+       info = g_hash_table_lookup(dundee_devices, path);
+       if (info != NULL)
+               return;
+
+       info = g_try_new0(struct dundee_data, 1);
+       if (info == NULL)
+               return;
+
+       info->path = g_strdup(path);
+
+       while (dbus_message_iter_get_arg_type(properties) ==
+                       DBUS_TYPE_DICT_ENTRY) {
+               DBusMessageIter entry, value;
+               const char *key;
+
+               dbus_message_iter_recurse(properties, &entry);
+               dbus_message_iter_get_basic(&entry, &key);
+
+               dbus_message_iter_next(&entry);
+               dbus_message_iter_recurse(&entry, &value);
+
+               if (g_str_equal(key, "Active") == TRUE) {
+                       dbus_message_iter_get_basic(&value, &info->active);
+
+                       DBG("%s Active %d", info->path, info->active);
+               } else if (g_str_equal(key, "Settings") == TRUE) {
+                       DBG("%s Settings", info->path);
+
+                       extract_settings(&value, info);
+               } else if (g_str_equal(key, "Name") == TRUE) {
+                       char *name;
+
+                       dbus_message_iter_get_basic(&value, &name);
+
+                       info->name = g_strdup(name);
+
+                       DBG("%s Name %s", info->path, info->name);
+               }
+
+               dbus_message_iter_next(properties);
+       }
+
+       g_hash_table_insert(dundee_devices, g_strdup(path), info);
+
+       create_device(info);
+       create_network(info);
+
+       if (info->active == TRUE)
+               set_connected(info);
+}
+
+static gboolean device_added(DBusConnection *connection, DBusMessage *message,
+                               void *user_data)
+{
+       DBusMessageIter iter, properties;
+       const char *path;
+       const char *signature = DBUS_TYPE_OBJECT_PATH_AS_STRING
+               DBUS_TYPE_ARRAY_AS_STRING
+               DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+               DBUS_TYPE_STRING_AS_STRING
+               DBUS_TYPE_VARIANT_AS_STRING
+               DBUS_DICT_ENTRY_END_CHAR_AS_STRING;
+
+       if (dbus_message_has_signature(message, signature) == FALSE) {
+               connman_error("dundee signature does not match");
+               return TRUE;
+       }
+
+       DBG("");
+
+       if (dbus_message_iter_init(message, &iter) == FALSE)
+               return TRUE;
+
+       dbus_message_iter_get_basic(&iter, &path);
+
+       dbus_message_iter_next(&iter);
+       dbus_message_iter_recurse(&iter, &properties);
+
+       add_device(path, &properties);
+
+       return TRUE;
+}
+
+static void remove_device(DBusConnection *connection, const char *path)
+{
+       DBG("path %s", path);
+
+       g_hash_table_remove(dundee_devices, path);
+}
+
+static gboolean device_removed(DBusConnection *connection, DBusMessage *message,
+                               void *user_data)
+{
+       const char *path;
+       const char *signature = DBUS_TYPE_OBJECT_PATH_AS_STRING;
+
+       if (dbus_message_has_signature(message, signature) == FALSE) {
+               connman_error("dundee signature does not match");
+               return TRUE;
+       }
+
+       dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+                               DBUS_TYPE_INVALID);
+       remove_device(connection, path);
+       return TRUE;
+}
+
+static void manager_get_devices_reply(DBusPendingCall *call, void *user_data)
+{
+       DBusMessage *reply;
+       DBusError error;
+       DBusMessageIter array, dict;
+       const char *signature = DBUS_TYPE_ARRAY_AS_STRING
+               DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+               DBUS_TYPE_OBJECT_PATH_AS_STRING
+               DBUS_TYPE_ARRAY_AS_STRING
+               DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+               DBUS_TYPE_STRING_AS_STRING
+               DBUS_TYPE_VARIANT_AS_STRING
+               DBUS_DICT_ENTRY_END_CHAR_AS_STRING
+               DBUS_STRUCT_END_CHAR_AS_STRING;
+
+       DBG("");
+
+       reply = dbus_pending_call_steal_reply(call);
+
+       if (dbus_message_has_signature(reply, signature) == FALSE) {
+               connman_error("dundee signature does not match");
+               goto done;
+       }
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, reply) == TRUE) {
+               connman_error("%s", error.message);
+               dbus_error_free(&error);
+               goto done;
+       }
+
+       if (dbus_message_iter_init(reply, &array) == FALSE)
+               goto done;
+
+       dbus_message_iter_recurse(&array, &dict);
+
+       while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_STRUCT) {
+               DBusMessageIter value, properties;
+               const char *path;
+
+               dbus_message_iter_recurse(&dict, &value);
+               dbus_message_iter_get_basic(&value, &path);
+
+               dbus_message_iter_next(&value);
+               dbus_message_iter_recurse(&value, &properties);
+
+               add_device(path, &properties);
+
+               dbus_message_iter_next(&dict);
+       }
+
+done:
+       dbus_message_unref(reply);
+
+       dbus_pending_call_unref(call);
+}
+
+static int manager_get_devices(void)
+{
+       DBusMessage *message;
+       DBusPendingCall *call;
+
+       DBG("");
+
+       message = dbus_message_new_method_call(DUNDEE_SERVICE, "/",
+                                       DUNDEE_MANAGER_INTERFACE, GET_DEVICES);
+       if (message == NULL)
+               return -ENOMEM;
+
+       if (dbus_connection_send_with_reply(connection, message,
+                                               &call, TIMEOUT) == FALSE) {
+               connman_error("Failed to call GetDevices()");
+               dbus_message_unref(message);
+               return -EINVAL;
+       }
+
+       if (call == NULL) {
+               connman_error("D-Bus connection not available");
+               dbus_message_unref(message);
+               return -EINVAL;
+       }
+
+       dbus_pending_call_set_notify(call, manager_get_devices_reply,
+                                       NULL, NULL);
+
+       dbus_message_unref(message);
+
+       return -EINPROGRESS;
+}
+
+static void dundee_connect(DBusConnection *connection, void *user_data)
+{
+       DBG("connection %p", connection);
+
+       dundee_devices = g_hash_table_new_full(g_str_hash, g_str_equal,
+                                       g_free, device_destroy);
+
+       manager_get_devices();
+}
+
+static void dundee_disconnect(DBusConnection *connection, void *user_data)
+{
+       DBG("connection %p", connection);
+
+       g_hash_table_destroy(dundee_devices);
+       dundee_devices = NULL;
+}
+
+static guint watch;
+static guint added_watch;
+static guint removed_watch;
+static guint device_watch;
+
+static int dundee_init(void)
+{
+       int err;
+
+       connection = connman_dbus_get_connection();
+       if (connection == NULL)
+               return -EIO;
+
+       watch = g_dbus_add_service_watch(connection, DUNDEE_SERVICE,
+                       dundee_connect, dundee_disconnect, NULL, NULL);
+
+       added_watch = g_dbus_add_signal_watch(connection, DUNDEE_SERVICE, NULL,
+                                               DUNDEE_MANAGER_INTERFACE,
+                                               DEVICE_ADDED, device_added,
+                                               NULL, NULL);
+
+       removed_watch = g_dbus_add_signal_watch(connection, DUNDEE_SERVICE,
+                                               NULL, DUNDEE_MANAGER_INTERFACE,
+                                               DEVICE_REMOVED, device_removed,
+                                               NULL, NULL);
+
+       device_watch = g_dbus_add_signal_watch(connection, DUNDEE_SERVICE,
+                                               NULL, DUNDEE_DEVICE_INTERFACE,
+                                               PROPERTY_CHANGED,
+                                               device_changed,
+                                               NULL, NULL);
+
+
+       if (watch == 0 || added_watch == 0 || removed_watch == 0 ||
+                       device_watch == 0) {
+               err = -EIO;
+               goto remove;
+       }
+
+       err = connman_network_driver_register(&network_driver);
+       if (err < 0)
+               goto remove;
+
+       err = connman_device_driver_register(&dundee_driver);
+       if (err < 0) {
+               connman_network_driver_unregister(&network_driver);
+               goto remove;
+       }
+
+       return 0;
+
+remove:
+       g_dbus_remove_watch(connection, watch);
+       g_dbus_remove_watch(connection, added_watch);
+       g_dbus_remove_watch(connection, removed_watch);
+       g_dbus_remove_watch(connection, device_watch);
+
+       dbus_connection_unref(connection);
+
+       return err;
+}
+
+static void dundee_exit(void)
+{
+       g_dbus_remove_watch(connection, watch);
+       g_dbus_remove_watch(connection, added_watch);
+       g_dbus_remove_watch(connection, removed_watch);
+       g_dbus_remove_watch(connection, device_watch);
+
+       connman_device_driver_unregister(&dundee_driver);
+       connman_network_driver_unregister(&network_driver);
+
+       dbus_connection_unref(connection);
+}
+
+CONNMAN_PLUGIN_DEFINE(dundee, "Dundee plugin", VERSION,
+               CONNMAN_PLUGIN_PRIORITY_DEFAULT, dundee_init, dundee_exit)
index 2244c84..400389b 100644 (file)
@@ -220,14 +220,18 @@ static DBusMessage *property_get(DBusConnection *conn,
                                                "Unsupported property");
 }
 
-static GDBusMethodTable methods[] = {
-       { "Get", "ss",  "v",   property_get     },
+static const GDBusMethodTable methods[] = {
+       { GDBUS_METHOD("Get",
+                       GDBUS_ARGS({ "interface", "s" }, { "key", "s" }),
+                       GDBUS_ARGS({ "property", "v" }), property_get) },
        { },
 };
 
-static GDBusSignalTable signals[] = {
-       { "PropertiesChanged",  "a{sv}" },
-       { "StateChanged",       "u"     },
+static const GDBusSignalTable signals[] = {
+       { GDBUS_SIGNAL("PropertiesChanged",
+                       GDBUS_ARGS({ "properties", "a{sv}" })) },
+       { GDBUS_SIGNAL("StateChanged",
+                       GDBUS_ARGS({ "state", "u" })) },
        { },
 };
 
index 0dfadb8..d9696d7 100644 (file)
@@ -43,8 +43,6 @@
 
 #include "mcc.h"
 
-#define uninitialized_var(x) x = x
-
 #define OFONO_SERVICE                  "org.ofono"
 
 #define OFONO_MANAGER_INTERFACE                OFONO_SERVICE ".Manager"
@@ -262,6 +260,12 @@ static void set_connected(struct modem_data *modem)
 
        DBG("%s", modem->path);
 
+       if (modem->context->index < 0 ||
+                       modem->context->ipv4_address == NULL) {
+               connman_error("Invalid index and/or address");
+               return;
+       }
+
        connman_network_set_index(modem->network, modem->context->index);
 
        switch (modem->context->ipv4_method) {
@@ -834,7 +838,7 @@ static void extract_ipv6_settings(DBusMessageIter *array,
 {
        DBusMessageIter dict;
        char *address = NULL, *gateway = NULL;
-       unsigned char prefix_length;
+       unsigned char prefix_length = 0;
        char *nameservers = NULL;
        const char *interface = NULL;
        int index = -1;
@@ -937,7 +941,7 @@ static connman_bool_t ready_to_create_device(struct modem_data *modem)
 static void create_device(struct modem_data *modem)
 {
        struct connman_device *device;
-       char *uninitialized_var(ident);
+       char *ident = NULL;
 
        DBG("%s", modem->path);
 
@@ -1062,7 +1066,7 @@ static void remove_network(struct modem_data *modem)
 static int add_cm_context(struct modem_data *modem, const char *context_path,
                                DBusMessageIter *dict)
 {
-       const char *context_type;
+       const char *context_type = NULL;
        struct network_context *context = NULL;
        connman_bool_t active = FALSE;
 
@@ -2549,68 +2553,71 @@ static int ofono_init(void)
                                        OFONO_SERVICE, ofono_connect,
                                        ofono_disconnect, NULL, NULL);
 
-       modem_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
-                                               OFONO_MANAGER_INTERFACE,
+       modem_added_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE,
+                                               NULL, OFONO_MANAGER_INTERFACE,
                                                MODEM_ADDED,
                                                modem_added,
                                                NULL, NULL);
 
-       modem_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+       modem_removed_watch = g_dbus_add_signal_watch(connection,
+                                               OFONO_SERVICE, NULL,
                                                OFONO_MANAGER_INTERFACE,
                                                MODEM_REMOVED,
                                                modem_removed,
                                                NULL, NULL);
 
-       modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+       modem_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE, NULL,
                                                OFONO_MODEM_INTERFACE,
                                                PROPERTY_CHANGED,
                                                modem_changed,
                                                NULL, NULL);
 
-       cm_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+       cm_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE, NULL,
                                                OFONO_CM_INTERFACE,
                                                PROPERTY_CHANGED,
                                                cm_changed,
                                                NULL, NULL);
 
-       sim_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+       sim_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE, NULL,
                                                OFONO_SIM_INTERFACE,
                                                PROPERTY_CHANGED,
                                                sim_changed,
                                                NULL, NULL);
 
-       context_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+       context_added_watch = g_dbus_add_signal_watch(connection,
+                                               OFONO_SERVICE, NULL,
                                                OFONO_CM_INTERFACE,
                                                CONTEXT_ADDED,
                                                cm_context_added,
                                                NULL, NULL);
 
-       context_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+       context_removed_watch = g_dbus_add_signal_watch(connection,
+                                               OFONO_SERVICE, NULL,
                                                OFONO_CM_INTERFACE,
                                                CONTEXT_REMOVED,
                                                cm_context_removed,
                                                NULL, NULL);
 
-       context_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
-                                               OFONO_CONTEXT_INTERFACE,
+       context_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE,
+                                               NULL, OFONO_CONTEXT_INTERFACE,
                                                PROPERTY_CHANGED,
                                                context_changed,
                                                NULL, NULL);
 
-       netreg_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+       netreg_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE, NULL,
                                                OFONO_NETREG_INTERFACE,
                                                PROPERTY_CHANGED,
                                                netreg_changed,
                                                NULL, NULL);
 
-       cdma_cm_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
-                                               OFONO_CDMA_CM_INTERFACE,
+       cdma_cm_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE,
+                                               NULL, OFONO_CDMA_CM_INTERFACE,
                                                PROPERTY_CHANGED,
                                                cdma_cm_changed,
                                                NULL, NULL);
 
-       cdma_netreg_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
-                                               OFONO_CDMA_NETREG_INTERFACE,
+       cdma_netreg_watch = g_dbus_add_signal_watch(connection, OFONO_SERVICE,
+                                               NULL, OFONO_CDMA_NETREG_INTERFACE,
                                                PROPERTY_CHANGED,
                                                cdma_netreg_changed,
                                                NULL, NULL);
index ada15aa..165c325 100644 (file)
@@ -162,10 +162,12 @@ vpn_exit:
                                                CONNMAN_PROVIDER_STATE_IDLE);
 
        connman_provider_set_index(provider, -1);
-       connman_provider_unref(data->provider);
 
-       g_free(data->if_name);
-       g_free(data);
+       if (data != NULL) {
+               connman_provider_unref(data->provider);
+               g_free(data->if_name);
+               g_free(data);
+       }
 
        connman_task_destroy(task);
 }
@@ -351,9 +353,12 @@ static int vpn_connect(struct connman_provider *provider)
 
        vpn_driver_data = g_hash_table_lookup(driver_hash, name);
 
-       if (vpn_driver_data != NULL && vpn_driver_data->vpn_driver != NULL &&
-               vpn_driver_data->vpn_driver->flags != VPN_FLAG_NO_TUN) {
+       if (vpn_driver_data == NULL || vpn_driver_data->vpn_driver == NULL) {
+               ret = -EINVAL;
+               goto exist_err;
+       }
 
+       if (vpn_driver_data->vpn_driver->flags != VPN_FLAG_NO_TUN) {
                ret = vpn_create_tun(provider);
                if (ret < 0)
                        goto exist_err;
index cace607..06604d5 100644 (file)
@@ -68,6 +68,7 @@ struct hidden_params {
        unsigned int ssid_len;
        char *identity;
        char *passphrase;
+       gpointer user_data;
 };
 
 /**
@@ -107,6 +108,8 @@ struct wifi_data {
 
 static GList *iface_list = NULL;
 
+static void start_autoscan(struct connman_device *device);
+
 static void handle_tethering(struct wifi_data *wifi)
 {
        if (wifi->tethering == FALSE)
@@ -131,6 +134,9 @@ static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
        struct connman_device *device = user_data;
        struct wifi_data *wifi = connman_device_get_data(device);
 
+       if (wifi == NULL)
+               return;
+
        DBG("index %d flags %d change %d", wifi->index, flags, change);
 
        if (!change)
@@ -202,7 +208,7 @@ static void remove_networks(struct connman_device *device,
        wifi->networks = NULL;
 }
 
-static void stop_autoscan(struct connman_device *device)
+static void reset_autoscan(struct connman_device *device)
 {
        struct wifi_data *wifi = connman_device_get_data(device);
        struct autoscan_params *autoscan;
@@ -225,6 +231,13 @@ static void stop_autoscan(struct connman_device *device)
        connman_device_unref(device);
 }
 
+static void stop_autoscan(struct connman_device *device)
+{
+       reset_autoscan(device);
+
+       connman_device_set_scanning(device, FALSE);
+}
+
 static void wifi_remove(struct connman_device *device)
 {
        struct wifi_data *wifi = connman_device_get_data(device);
@@ -234,8 +247,6 @@ static void wifi_remove(struct connman_device *device)
        if (wifi == NULL)
                return;
 
-       stop_autoscan(device);
-
        iface_list = g_list_remove(iface_list, wifi);
 
        remove_networks(device, wifi);
@@ -394,11 +405,17 @@ static int throw_wifi_scan(struct connman_device *device,
        struct wifi_data *wifi = connman_device_get_data(device);
        int ret;
 
+       if (wifi == NULL)
+               return -ENODEV;
+
        DBG("device %p %p", device, wifi->interface);
 
        if (wifi->tethering == TRUE)
                return 0;
 
+       if (connman_device_get_scanning(device) == TRUE)
+               return -EALREADY;
+
        connman_device_ref(device);
 
        ret = g_supplicant_interface_scan(wifi->interface, NULL,
@@ -411,25 +428,49 @@ static int throw_wifi_scan(struct connman_device *device,
        return ret;
 }
 
-static void hidden_scan_callback(int result,
-                       GSupplicantInterface *interface, void *user_data)
+static void hidden_free(struct hidden_params *hidden)
+{
+       if (hidden == NULL)
+               return;
+
+       g_free(hidden->identity);
+       g_free(hidden->passphrase);
+       g_free(hidden);
+}
+
+static void scan_callback(int result, GSupplicantInterface *interface,
+                                               void *user_data)
 {
        struct connman_device *device = user_data;
+       struct wifi_data *wifi = connman_device_get_data(device);
+
+       DBG("result %d wifi %p", result, wifi);
+
+       if (wifi != NULL && wifi->hidden != NULL) {
+               connman_network_clear_hidden(wifi->hidden->user_data);
+               hidden_free(wifi->hidden);
+               wifi->hidden = NULL;
+       }
 
-       DBG("result %d", result);
+       if (result < 0)
+               connman_device_reset_scanning(device);
 
        connman_device_set_scanning(device, FALSE);
+       start_autoscan(device);
        connman_device_unref(device);
 }
 
-static void autoscan_scan_callback(int result,
+static void scan_callback_hidden(int result,
                        GSupplicantInterface *interface, void *user_data)
 {
        struct connman_device *device = user_data;
        struct wifi_data *wifi = connman_device_get_data(device);
        int driver_max_ssids;
 
-       DBG("result %d", result);
+       DBG("result %d wifi %p", result, wifi);
+
+       if (wifi == NULL)
+               goto out;
 
        /*
         * Scan hidden networks so that we can autoconnect to them.
@@ -450,7 +491,7 @@ static void autoscan_scan_callback(int result,
                                                scan_params) > 0) {
                        ret = g_supplicant_interface_scan(wifi->interface,
                                                        scan_params,
-                                                       hidden_scan_callback,
+                                                       scan_callback,
                                                        device);
                        if (ret == 0)
                                return;
@@ -460,8 +501,7 @@ static void autoscan_scan_callback(int result,
        }
 
 out:
-       connman_device_set_scanning(device, FALSE);
-       connman_device_unref(device);
+       scan_callback(result, interface, user_data);
 }
 
 static gboolean autoscan_timeout(gpointer data)
@@ -471,6 +511,9 @@ static gboolean autoscan_timeout(gpointer data)
        struct autoscan_params *autoscan;
        int interval;
 
+       if (wifi == NULL)
+               return FALSE;
+
        autoscan = wifi->autoscan;
 
        if (autoscan->interval <= 0) {
@@ -482,7 +525,7 @@ static gboolean autoscan_timeout(gpointer data)
        if (autoscan->interval >= autoscan->limit)
                interval = autoscan->limit;
 
-       throw_wifi_scan(wifi->device, autoscan_scan_callback);
+       throw_wifi_scan(wifi->device, scan_callback_hidden);
 
 set_interval:
        DBG("interval %d", interval);
@@ -605,12 +648,12 @@ static int wifi_enable(struct connman_device *device)
 
        DBG("device %p %p", device, wifi);
 
+       if (wifi == NULL)
+               return -ENODEV;
+
        ret = g_supplicant_interface_create(interface, driver, NULL,
                                                interface_create_callback,
                                                        wifi);
-        // added by chengyi.zhao
-       //      DBG("%s does not AP mode", device->network->wifi.mode);
-       DBG("%p does not AP mode", device);
        if (ret < 0)
                return ret;
 
@@ -622,7 +665,10 @@ static int wifi_disable(struct connman_device *device)
        struct wifi_data *wifi = connman_device_get_data(device);
        int ret;
 
-       DBG("device %p", device);
+       DBG("device %p wifi %p", device, wifi);
+
+       if (wifi == NULL)
+               return -ENODEV;
 
        wifi->connected = FALSE;
        wifi->disconnecting = FALSE;
@@ -630,6 +676,14 @@ static int wifi_disable(struct connman_device *device)
        if (wifi->pending_network != NULL)
                wifi->pending_network = NULL;
 
+       stop_autoscan(device);
+
+       /* In case of a user scan, device is still referenced */
+       if (connman_device_get_scanning(device) == TRUE) {
+               connman_device_set_scanning(device, FALSE);
+               connman_device_unref(wifi->device);
+       }
+
        remove_networks(device, wifi);
 
        ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
@@ -639,38 +693,6 @@ static int wifi_disable(struct connman_device *device)
        return -EINPROGRESS;
 }
 
-static void hidden_free(struct hidden_params *hidden)
-{
-       if (hidden == NULL)
-               return;
-
-       g_free(hidden->identity);
-       g_free(hidden->passphrase);
-       g_free(hidden);
-}
-
-static void scan_callback(int result, GSupplicantInterface *interface,
-                                               void *user_data)
-{
-       struct connman_device *device = user_data;
-       struct wifi_data *wifi = connman_device_get_data(device);
-
-       DBG("result %d", result);
-
-       if (wifi != NULL && wifi->hidden != NULL) {
-               hidden_free(wifi->hidden);
-               wifi->hidden = NULL;
-       }
-
-       if (result < 0)
-               connman_device_reset_scanning(device);
-
-       connman_device_set_scanning(device, FALSE);
-       connman_device_unref(device);
-
-       start_autoscan(device);
-}
-
 struct last_connected {
        GTimeVal modified;
        gchar *ssid;
@@ -802,9 +824,9 @@ static int get_latest_connections(int max_ssids,
 
 static int wifi_scan(struct connman_device *device)
 {
-       stop_autoscan(device);
+       reset_autoscan(device);
 
-       return throw_wifi_scan(device, scan_callback);
+       return throw_wifi_scan(device, scan_callback_hidden);
 }
 
 static int wifi_scan_fast(struct connman_device *device)
@@ -814,11 +836,17 @@ static int wifi_scan_fast(struct connman_device *device)
        int ret;
        int driver_max_ssids = 0;
 
+       if (wifi == NULL)
+               return -ENODEV;
+
        DBG("device %p %p", device, wifi->interface);
 
        if (wifi->tethering == TRUE)
                return 0;
 
+       if (connman_device_get_scanning(device) == TRUE)
+               return -EALREADY;
+
        driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
                                                        wifi->interface);
        DBG("max ssids %d", driver_max_ssids);
@@ -835,9 +863,9 @@ static int wifi_scan_fast(struct connman_device *device)
                return wifi_scan(device);
        }
 
-       stop_autoscan(device);
-
        connman_device_ref(device);
+       reset_autoscan(device);
+
        ret = g_supplicant_interface_scan(wifi->interface, scan_params,
                                                scan_callback, device);
        if (ret == 0)
@@ -856,7 +884,8 @@ static int wifi_scan_fast(struct connman_device *device)
  */
 static int wifi_scan_hidden(struct connman_device *device,
                const char *ssid, unsigned int ssid_len,
-               const char *identity, const char* passphrase)
+               const char *identity, const char* passphrase,
+               gpointer user_data)
 {
        struct wifi_data *wifi = connman_device_get_data(device);
        GSupplicantScanParams *scan_params = NULL;
@@ -864,6 +893,9 @@ static int wifi_scan_hidden(struct connman_device *device,
        struct hidden_params *hidden;
        int ret;
 
+       if (wifi == NULL)
+               return -ENODEV;
+
        DBG("hidden SSID %s", ssid);
 
        if (wifi->tethering == TRUE || wifi->hidden != NULL)
@@ -872,6 +904,9 @@ static int wifi_scan_hidden(struct connman_device *device,
        if (ssid == NULL || ssid_len == 0 || ssid_len > 32)
                return -EINVAL;
 
+       if (connman_device_get_scanning(device) == TRUE)
+               return -EALREADY;
+
        scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
        if (scan_params == NULL)
                return -ENOMEM;
@@ -897,11 +932,13 @@ static int wifi_scan_hidden(struct connman_device *device,
        hidden->ssid_len = ssid_len;
        hidden->identity = g_strdup(identity);
        hidden->passphrase = g_strdup(passphrase);
+       hidden->user_data = user_data;
        wifi->hidden = hidden;
 
-       stop_autoscan(device);
-
        connman_device_ref(device);
+
+       reset_autoscan(device);
+
        ret = g_supplicant_interface_scan(wifi->interface, scan_params,
                        scan_callback, device);
        if (ret == 0)
@@ -1447,7 +1484,7 @@ static void interface_removed(GSupplicantInterface *interface)
                return;
 
        if (wifi == NULL || wifi->device == NULL) {
-               connman_error("Wrong wifi pointer");
+               DBG("wifi interface already removed");
                return;
        }
 
@@ -1554,13 +1591,15 @@ static void network_added(GSupplicantNetwork *supplicant_network)
        if (ssid != NULL)
                connman_network_set_group(network, group);
 
-       if (wifi->hidden != NULL) {
+       if (wifi->hidden != NULL && ssid != NULL) {
                if (wifi->hidden->ssid_len == ssid_len &&
                                memcmp(wifi->hidden->ssid, ssid,
                                                ssid_len) == 0) {
                        connman_network_connect_hidden(network,
                                        wifi->hidden->identity,
-                                       wifi->hidden->passphrase);
+                                       wifi->hidden->passphrase,
+                                       wifi->hidden->user_data);
+                       wifi->hidden->user_data = NULL;
                        hidden_free(wifi->hidden);
                        wifi->hidden = NULL;
                }
index feeb48e..7aaf304 100644 (file)
@@ -85,6 +85,26 @@ int __connman_agent_unregister(const char *sender, const char *path)
        return 0;
 }
 
+static connman_bool_t check_reply_has_dict(DBusMessage *reply)
+{
+       const char *signature = DBUS_TYPE_ARRAY_AS_STRING
+               DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+               DBUS_TYPE_STRING_AS_STRING
+               DBUS_TYPE_VARIANT_AS_STRING
+               DBUS_DICT_ENTRY_END_CHAR_AS_STRING;
+
+       if (dbus_message_has_signature(reply, signature) == TRUE)
+               return TRUE;
+
+       connman_warn("Reply %s to %s from %s has wrong signature %s",
+                       signature,
+                       dbus_message_get_interface(reply),
+                       dbus_message_get_sender(reply),
+                       dbus_message_get_signature(reply));
+
+       return FALSE;
+}
+
 struct request_input_reply {
        struct connman_service *service;
        authentication_cb_t callback;
@@ -111,6 +131,9 @@ static void request_input_passphrase_reply(DBusPendingCall *call, void *user_dat
                goto done;
        }
 
+       if (check_reply_has_dict(reply) == FALSE)
+               goto done;
+
        values_received = TRUE;
 
        dbus_message_iter_init(reply, &iter);
@@ -311,10 +334,46 @@ static void request_input_append_password(DBusMessageIter *iter,
                                DBUS_TYPE_STRING, &str);
 }
 
+static void request_input_append_previouspassphrase(DBusMessageIter *iter,
+                                                       void *user_data)
+{
+       struct connman_service *service = user_data;
+       enum connman_service_security security;
+       const char *passphrase, *str = NULL;
+
+       passphrase = __connman_service_get_passphrase(service);
+
+       security = __connman_service_get_security(service);
+       switch (security) {
+       case CONNMAN_SERVICE_SECURITY_WEP:
+               str = "wep";
+               break;
+       case CONNMAN_SERVICE_SECURITY_PSK:
+               str  = "psk";
+               break;
+       /*
+        * This should never happen: no passphrase is set if security is not
+        * one of the above.*/
+       default:
+               break;
+       }
+
+       connman_dbus_dict_append_basic(iter, "Type",
+                               DBUS_TYPE_STRING, &str);
+
+       str = "informational";
+       connman_dbus_dict_append_basic(iter, "Requirement",
+                               DBUS_TYPE_STRING, &str);
+
+       connman_dbus_dict_append_basic(iter, "Value",
+                               DBUS_TYPE_STRING, &passphrase);
+}
+
 static void request_input_login_reply(DBusPendingCall *call, void *user_data)
 {
        struct request_input_reply *username_password_reply = user_data;
        const char *error = NULL;
+       connman_bool_t values_received = FALSE;
        char *username = NULL;
        char *password = NULL;
        char *key;
@@ -326,6 +385,11 @@ static void request_input_login_reply(DBusPendingCall *call, void *user_data)
                goto done;
        }
 
+       if (check_reply_has_dict(reply) == FALSE)
+               goto done;
+
+       values_received = TRUE;
+
        dbus_message_iter_init(reply, &iter);
        dbus_message_iter_recurse(&iter, &dict);
        while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
@@ -359,7 +423,7 @@ static void request_input_login_reply(DBusPendingCall *call, void *user_data)
 
 done:
        username_password_reply->callback(username_password_reply->service,
-                                       TRUE, NULL, 0,
+                                       values_received, NULL, 0,
                                        username, password,
                                        FALSE, NULL, error,
                                        username_password_reply->user_data);
@@ -412,6 +476,11 @@ int __connman_agent_request_passphrase_input(struct connman_service *service,
                        CONNMAN_SERVICE_SECURITY_NONE) {
                connman_dbus_dict_append_dict(&dict, "Passphrase",
                                        request_input_append_passphrase, service);
+
+               if (__connman_service_get_passphrase(service) != NULL)
+                       connman_dbus_dict_append_dict(&dict, "PreviousPassphrase",
+                                       request_input_append_previouspassphrase,
+                                       service);
        }
 
        if (__connman_service_wps_enabled(service) == TRUE) {
@@ -427,8 +496,9 @@ int __connman_agent_request_passphrase_input(struct connman_service *service,
                return -ENOMEM;
        }
 
-       if (dbus_connection_send_with_reply(connection, message,
-                                               &call, -1) == FALSE) {
+       if (dbus_connection_send_with_reply(connection, message, &call,
+                                       connman_timeout_input_request())
+                       == FALSE) {
                dbus_message_unref(message);
                g_free(passphrase_reply);
                return -ESRCH;
@@ -449,7 +519,7 @@ int __connman_agent_request_passphrase_input(struct connman_service *service,
 
        dbus_message_unref(message);
 
-       return -EIO;
+       return -EINPROGRESS;
 }
 
 int __connman_agent_request_login_input(struct connman_service *service,
@@ -493,8 +563,9 @@ int __connman_agent_request_login_input(struct connman_service *service,
                return -ENOMEM;
        }
 
-       if (dbus_connection_send_with_reply(connection, message,
-                                                       &call, -1) == FALSE) {
+       if (dbus_connection_send_with_reply(connection, message, &call,
+                                       connman_timeout_input_request())
+                       == FALSE) {
                dbus_message_unref(message);
                g_free(username_password_reply);
                return -ESRCH;
@@ -515,7 +586,7 @@ int __connman_agent_request_login_input(struct connman_service *service,
 
        dbus_message_unref(message);
 
-       return -EIO;
+       return -EINPROGRESS;
 }
 
 struct request_browser_reply_data {
@@ -581,8 +652,9 @@ int __connman_agent_request_browser(struct connman_service *service,
                return -ENOMEM;
        }
 
-       if (dbus_connection_send_with_reply(connection, message,
-                                                       &call, -1) == FALSE) {
+       if (dbus_connection_send_with_reply(connection, message, &call,
+                                       connman_timeout_browser_launch())
+                       == FALSE) {
                dbus_message_unref(message);
                g_free(browser_reply_data);
                return -ESRCH;
@@ -603,7 +675,7 @@ int __connman_agent_request_browser(struct connman_service *service,
 
        dbus_message_unref(message);
 
-       return -EIO;
+       return -EINPROGRESS;
 }
 
 struct report_error_data {
@@ -669,8 +741,9 @@ int __connman_agent_report_error(struct connman_service *service,
                return -ENOMEM;
        }
 
-       if (dbus_connection_send_with_reply(connection, message,
-                                               &call, -1) == FALSE) {
+       if (dbus_connection_send_with_reply(connection, message, &call,
+                                       connman_timeout_input_request())
+                       == FALSE) {
                dbus_message_unref(message);
                g_free(report_error);
                return -ESRCH;
@@ -689,7 +762,7 @@ int __connman_agent_report_error(struct connman_service *service,
                                report_error, NULL);
        dbus_message_unref(message);
 
-       return -EIO;
+       return -EINPROGRESS;
 }
 
 int __connman_agent_init(void)
index a742557..e2cc19f 100644 (file)
@@ -308,14 +308,19 @@ static DBusMessage *set_property(DBusConnection *conn,
        return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
 
-static GDBusMethodTable clock_methods[] = {
-       { "GetProperties", "",   "a{sv}", get_properties },
-       { "SetProperty",   "sv", "",      set_property   },
+static const GDBusMethodTable clock_methods[] = {
+       { GDBUS_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       get_properties) },
+       { GDBUS_METHOD("SetProperty",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" }), NULL,
+                       set_property)   },
        { },
 };
 
-static GDBusSignalTable clock_signals[] = {
-       { "PropertyChanged", "sv" },
+static const GDBusSignalTable clock_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
        { },
 };
 
index 781427d..5363dc3 100644 (file)
@@ -48,6 +48,9 @@ struct connman_config_service {
        char *private_key_passphrase_type;
        char *phase2;
        char *passphrase;
+       GSList *service_identifiers;
+       char *config_ident; /* file prefix */
+       char *config_entry; /* entry name */
 };
 
 struct connman_config {
@@ -65,6 +68,7 @@ static int inotify_wd = -1;
 
 static GIOChannel *inotify_channel = NULL;
 static uint inotify_watch = 0;
+static connman_bool_t cleanup = FALSE;
 
 #define INTERNAL_CONFIG_PREFIX           "__internal"
 
@@ -125,26 +129,53 @@ static void unregister_config(gpointer data)
 
 static void unregister_service(gpointer data)
 {
-       struct connman_config_service *service = data;
-
-       connman_info("Removing service configuration %s", service->ident);
-
-       protected_services = g_slist_remove(protected_services, service);
-
-       g_free(service->ident);
-       g_free(service->type);
-       g_free(service->name);
-       g_free(service->ssid);
-       g_free(service->eap);
-       g_free(service->identity);
-       g_free(service->ca_cert_file);
-       g_free(service->client_cert_file);
-       g_free(service->private_key_file);
-       g_free(service->private_key_passphrase);
-       g_free(service->private_key_passphrase_type);
-       g_free(service->phase2);
-       g_free(service->passphrase);
-       g_free(service);
+       struct connman_config_service *config_service = data;
+       struct connman_service *service;
+       char *service_id;
+       GSList *list;
+
+       if (cleanup == TRUE)
+               goto free_only;
+
+       connman_info("Removing service configuration %s",
+                                               config_service->ident);
+
+       protected_services = g_slist_remove(protected_services,
+                                               config_service);
+
+       for (list = config_service->service_identifiers; list != NULL;
+                                                       list = list->next) {
+               service_id = list->data;
+
+               service = __connman_service_lookup_from_ident(service_id);
+               if (service != NULL) {
+                       __connman_service_set_immutable(service, FALSE);
+                       __connman_service_remove(service);
+               }
+
+               if (__connman_storage_remove_service(service_id) == FALSE)
+                       DBG("Could not remove all files for service %s",
+                                                               service_id);
+       }
+
+free_only:
+       g_free(config_service->ident);
+       g_free(config_service->type);
+       g_free(config_service->name);
+       g_free(config_service->ssid);
+       g_free(config_service->eap);
+       g_free(config_service->identity);
+       g_free(config_service->ca_cert_file);
+       g_free(config_service->client_cert_file);
+       g_free(config_service->private_key_file);
+       g_free(config_service->private_key_passphrase);
+       g_free(config_service->private_key_passphrase_type);
+       g_free(config_service->phase2);
+       g_free(config_service->passphrase);
+       g_slist_free_full(config_service->service_identifiers, g_free);
+       g_free(config_service->config_ident);
+       g_free(config_service->config_entry);
+       g_free(config_service);
 }
 
 static void check_keys(GKeyFile *keyfile, const char *group,
@@ -258,7 +289,13 @@ static int load_service(GKeyFile *keyfile, const char *group,
                }
 
                for (i = 0; i < hex_ssid_len; i += 2) {
-                       sscanf(hex_ssid + i, "%02x", &hex);
+                       if (sscanf(hex_ssid + i, "%02x", &hex) <= 0) {
+                               connman_warn("Invalid SSID %s", hex_ssid);
+                               g_free(ssid);
+                               g_free(hex_ssid);
+                               err = -EILSEQ;
+                               goto err;
+                       }
                        ssid[j++] = hex;
                }
 
@@ -347,6 +384,9 @@ static int load_service(GKeyFile *keyfile, const char *group,
                service->passphrase = str;
        }
 
+       service->config_ident = g_strdup(config->ident);
+       service->config_entry = g_strdup_printf("service_%s", service->ident);
+
        if (service_created)
                g_hash_table_insert(config->service_table, service->ident,
                                        service);
@@ -455,62 +495,6 @@ static struct connman_config *create_config(const char *ident)
        return config;
 }
 
-int __connman_config_load_service(GKeyFile *keyfile, const char *group,
-                                       connman_bool_t persistent)
-{
-       struct connman_config *config;
-       const char *service_name;
-       char *ident, *content = NULL;
-       gsize content_length;
-       int err;
-
-       service_name = group + strlen("service_");
-       ident = g_strdup_printf("%s_%s", INTERNAL_CONFIG_PREFIX, service_name);
-       if (ident == NULL)
-               return -ENOMEM;
-
-       DBG("ident %s", ident);
-
-       config = g_hash_table_lookup(config_table, ident);
-       if (config == NULL) {
-               config = create_config(ident);
-               if (config == NULL) {
-                       err = -ENOMEM;
-                       goto out;
-               }
-
-               config->protected = FALSE;
-       }
-
-       err = load_service(keyfile, group, config);
-       if (persistent == FALSE || err < 0)
-               goto out;
-
-       g_key_file_set_string(keyfile, "global", CONFIG_KEY_NAME,
-                                                       service_name);
-       g_key_file_set_string(keyfile, "global", CONFIG_KEY_DESC,
-                                               "Internal Config File");
-       g_key_file_set_boolean(keyfile, "global", CONFIG_KEY_PROT, FALSE);
-
-       content = g_key_file_to_data(keyfile, &content_length, NULL);
-       if (content == NULL) {
-               err = -EIO;
-               goto out;
-       }
-
-       DBG("Saving %zu bytes to %s", content_length, service_name);
-
-       __connman_storage_save_config(keyfile, ident);
-
-       return 0;
-
-out:
-       g_free(ident);
-       g_free(content);
-
-       return err;
-}
-
 static connman_bool_t validate_ident(const char *ident)
 {
        unsigned int i;
@@ -645,9 +629,20 @@ static gboolean inotify_data(GIOChannel *channel, GIOCondition cond,
 
                        config = g_hash_table_lookup(config_table, ident);
                        if (config != NULL) {
+                               int ret;
+
                                g_hash_table_remove_all(config->service_table);
                                load_config(config);
-                               __connman_service_provision_changed(ident);
+                               ret = __connman_service_provision_changed(ident);
+                               if (ret > 0) {
+                                       /*
+                                        * Re-scan the config file for any
+                                        * changes
+                                        */
+                                       g_hash_table_remove_all(config->service_table);
+                                       load_config(config);
+                                       __connman_service_provision_changed(ident);
+                               }
                        }
                }
 
@@ -733,10 +728,14 @@ void __connman_config_cleanup(void)
 {
        DBG("");
 
+       cleanup = TRUE;
+
        remove_watch();
 
        g_hash_table_destroy(config_table);
        config_table = NULL;
+
+       cleanup = FALSE;
 }
 
 static char *config_pem_fsid(const char *pem_file)
@@ -764,7 +763,7 @@ static void provision_service(gpointer key, gpointer value, gpointer user_data)
        struct connman_service *service = user_data;
        struct connman_config_service *config = value;
        struct connman_network *network;
-       const void *ssid;
+       const void *ssid, *service_id;
        unsigned int ssid_len;
 
        /* For now only WiFi service entries are supported */
@@ -789,9 +788,17 @@ static void provision_service(gpointer key, gpointer value, gpointer user_data)
        if (memcmp(config->ssid, ssid, ssid_len) != 0)
                return;
 
+       service_id = __connman_service_get_ident(service);
+       config->service_identifiers =
+               g_slist_prepend(config->service_identifiers,
+                               g_strdup(service_id));
+
        __connman_service_set_immutable(service, TRUE);
 
-       __connman_service_set_favorite(service, TRUE);
+       __connman_service_set_favorite_delayed(service, TRUE, TRUE);
+
+       __connman_service_set_config(service, config->config_ident,
+                                               config->config_entry);
 
        if (config->eap != NULL)
                __connman_service_set_string(service, "EAP", config->eap);
@@ -841,6 +848,10 @@ static void provision_service(gpointer key, gpointer value, gpointer user_data)
 
        if (config->passphrase != NULL)
                __connman_service_set_string(service, "Passphrase", config->passphrase);
+
+       __connman_service_mark_dirty();
+
+       __connman_service_save(service);
 }
 
 int __connman_config_provision_service(struct connman_service *service)
@@ -869,10 +880,11 @@ int __connman_config_provision_service(struct connman_service *service)
 }
 
 int __connman_config_provision_service_ident(struct connman_service *service,
-                                                       const char *ident)
+                       const char *ident, const char *file, const char *entry)
 {
        enum connman_service_type type;
        struct connman_config *config;
+       int ret = 0;
 
        DBG("service %p", service);
 
@@ -882,9 +894,47 @@ int __connman_config_provision_service_ident(struct connman_service *service,
                return -ENOSYS;
 
        config = g_hash_table_lookup(config_table, ident);
-       if(config != NULL)
+       if(config != NULL) {
+               GHashTableIter iter;
+               gpointer value, key;
+               gboolean found = FALSE;
+
+               g_hash_table_iter_init(&iter, config->service_table);
+
+               /*
+                * Check if we need to remove individual service if it
+                * is missing from config file.
+                */
+               if (file != NULL && entry != NULL) {
+                       while (g_hash_table_iter_next(&iter, &key,
+                                                       &value) == TRUE) {
+                               struct connman_config_service *config = value;
+
+                               if (g_strcmp0(config->config_ident,
+                                                               file) == 0 &&
+                                               g_strcmp0(config->config_entry,
+                                                               entry) == 0) {
+                                       found = TRUE;
+                                       break;
+                               }
+                       }
+
+                       DBG("found %d ident %s file %s entry %s", found, ident,
+                                                               file, entry);
+
+                       if (found == FALSE) {
+                               /*
+                                * The entry+8 will skip "service_" prefix
+                                */
+                               g_hash_table_remove(config->service_table,
+                                               entry + 8);
+                               ret = 1;
+                       }
+               }
+
                g_hash_table_foreach(config->service_table,
                                                provision_service, service);
+       }
 
-       return 0;
+       return ret;
 }
index f86f0ec..d40f428 100644 (file)
@@ -136,58 +136,103 @@ static struct gateway_data *find_phy_gateway(int index, const char *gateway)
        return NULL;
 }
 
-static void set_vpn_routes(struct gateway_config *config,
+static void set_vpn_routes(struct gateway_data *new_gateway,
                        struct connman_service *service,
                        const char *gateway,
                        enum connman_ipconfig_type type,
-                       const char *peer)
+                       const char *peer,
+                       struct gateway_data *active_gateway)
 {
+       struct gateway_config *config;
        struct gateway_data *data;
        struct connman_ipconfig *ipconfig;
+       char *dest;
        int index;
 
+       if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
+               ipconfig = __connman_service_get_ip4config(service);
+               config = new_gateway->ipv4_gateway;
+       } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
+               ipconfig = __connman_service_get_ip6config(service);
+               config = new_gateway->ipv6_gateway;
+       } else
+               return;
+
+       if (config == NULL)
+               goto done;
+
        config->vpn = TRUE;
        if (peer != NULL)
                config->vpn_ip = g_strdup(peer);
        else if (gateway != NULL)
                config->vpn_ip = g_strdup(gateway);
 
+       index = __connman_ipconfig_get_index(ipconfig);
+       data = find_phy_gateway(index, gateway);
+
+       if (data == NULL)
+               goto done;
+
+       /*
+        * data->service points now to original
+        * service that is serving the VPN link
+        */
        if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
-               ipconfig = __connman_service_get_ip4config(service);
+               ipconfig = __connman_service_get_ip4config(data->service);
        else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
-               ipconfig = __connman_service_get_ip6config(service);
+               ipconfig = __connman_service_get_ip6config(data->service);
        else
                return;
 
-       index = __connman_ipconfig_get_index(ipconfig);
-       data = find_phy_gateway(index, gateway);
+       if (ipconfig != NULL) {
+               const char *address;
+
+               address = __connman_ipconfig_get_local(ipconfig);
+               config->vpn_phy_ip = g_strdup(address);
+       }
+
+       config->vpn_phy_index = data->index;
+
+       DBG("vpn %s phy %s index %d", config->vpn_ip,
+               config->vpn_phy_ip, config->vpn_phy_index);
 
-       if (data != NULL) {
+done:
+       if (active_gateway == NULL)
+               return;
+
+       if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
                /*
-                * data->service points now to original
-                * service that is serving the VPN link
+                * Special route to VPN server via gateway. This
+                * is needed so that we can access hosts behind
+                * the VPN. The route might already exist depending
+                * on network topology.
                 */
-               if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
-                       ipconfig =
-                               __connman_service_get_ip4config(data->service);
-               else if (type == CONNMAN_IPCONFIG_TYPE_IPV6)
-                       ipconfig =
-                               __connman_service_get_ip6config(data->service);
-               else
+               if (active_gateway->ipv4_gateway == NULL)
                        return;
 
-               if (ipconfig != NULL) {
-                       const char *address;
+               if (g_strcmp0(active_gateway->ipv4_gateway->gateway,
+                                                       "0.0.0.0") != 0)
+                       dest = active_gateway->ipv4_gateway->gateway;
+               else
+                       dest = NULL;
 
-                       address = __connman_ipconfig_get_local(ipconfig);
-                       config->vpn_phy_ip = g_strdup(address);
-               }
+               connman_inet_add_host_route(active_gateway->index, gateway,
+                                                                       dest);
 
-               config->vpn_phy_index = data->index;
-       }
+       } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
 
-       DBG("vpn %s phy %s index %d", config->vpn_ip,
-               config->vpn_phy_ip, config->vpn_phy_index);
+               if (active_gateway->ipv6_gateway == NULL)
+                       return;
+
+               if (g_strcmp0(active_gateway->ipv6_gateway->gateway,
+                                                               "::") != 0)
+                       dest = active_gateway->ipv6_gateway->gateway;
+               else
+                       dest = NULL;
+
+               connman_inet_add_ipv6_host_route(active_gateway->index,
+                                                               gateway, dest);
+       }
 }
 
 static int del_routes(struct gateway_data *data,
@@ -832,46 +877,9 @@ int __connman_connection_gateway_add(struct connman_service *service,
        }
 
        if (service_type == CONNMAN_SERVICE_TYPE_VPN) {
-               char *dest;
 
-               if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
-                       if (new_gateway->ipv4_gateway != NULL)
-                               set_vpn_routes(new_gateway->ipv4_gateway,
-                                       service, gateway, type, peer);
-
-                       /*
-                        * Special route to VPN server via gateway. This
-                        * is needed so that we can access hosts behind
-                        * the VPN. The route might already exist depending
-                        * on network topology.
-                        */
-                       if (active_gateway != NULL) {
-                               if (g_strcmp0(active_gateway->ipv4_gateway->gateway, "0.0.0.0") != 0)
-                                       dest = active_gateway->ipv4_gateway->gateway;
-                               else
-                                       dest = NULL;
-
-                               connman_inet_add_host_route(active_gateway->index,
-                                               gateway,
-                                               dest);
-                       }
-
-               } else if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
-                       if (new_gateway->ipv6_gateway != NULL)
-                               set_vpn_routes(new_gateway->ipv6_gateway,
-                                       service, gateway, type, peer);
-
-                       if (active_gateway != NULL) {
-                               if (g_strcmp0(active_gateway->ipv6_gateway->gateway, "::") != 0)
-                                       dest = active_gateway->ipv6_gateway->gateway;
-                               else
-                                       dest = NULL;
-
-                               connman_inet_add_ipv6_host_route(active_gateway->index,
-                                               gateway,
-                                               dest);
-                       }
-               }
+               set_vpn_routes(new_gateway, service, gateway, type, peer,
+                                                       active_gateway);
 
        } else {
                if (type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
index 734213d..0418a7e 100644 (file)
@@ -147,6 +147,9 @@ typedef void (*__connman_inet_rs_cb_t) (struct nd_router_advert *reply,
 
 int __connman_inet_ipv6_send_rs(int index, int timeout,
                        __connman_inet_rs_cb_t callback, void *user_data);
+
+int __connman_refresh_rs_ipv6(struct connman_network *network, int index);
+
 GSList *__connman_inet_ipv6_get_prefixes(struct nd_router_advert *hdr,
                                        unsigned int length);
 
@@ -201,18 +204,17 @@ int __connman_resolver_redo_servers(const char *interface);
 void __connman_storage_migrate(void);
 GKeyFile *__connman_storage_open_global();
 GKeyFile *__connman_storage_load_global();
-void __connman_storage_save_global(GKeyFile *keyfile);
+int __connman_storage_save_global(GKeyFile *keyfile);
 void __connman_storage_delete_global();
 
 GKeyFile *__connman_storage_load_config(const char *ident);
-void __connman_storage_save_config(GKeyFile *keyfile, const char *ident);
-void __connman_storage_delete_config(const char *ident);
 
 GKeyFile *__connman_storage_open_service(const char *ident);
-void __connman_storage_save_service(GKeyFile *keyfile, const char *ident);
+int __connman_storage_save_service(GKeyFile *keyfile, const char *ident);
 GKeyFile *__connman_storage_load_provider(const char *identifier);
 void __connman_storage_save_provider(GKeyFile *keyfile, const char *identifier);
 char **__connman_storage_get_providers(void);
+gboolean __connman_storage_remove_service(const char *service_id);
 
 int __connman_detect_init(void);
 void __connman_detect_cleanup(void);
@@ -468,7 +470,8 @@ struct connman_device *__connman_device_find_device(enum connman_service_type ty
 int __connman_device_request_scan(enum connman_service_type type);
 int __connman_device_request_hidden_scan(struct connman_device *device,
                                const char *ssid, unsigned int ssid_len,
-                               const char *identity, const char *passphrase);
+                               const char *identity, const char *passphrase,
+                               gpointer user_data);
 
 connman_bool_t __connman_device_isfiltered(const char *devname);
 
@@ -484,8 +487,6 @@ int __connman_device_enable(struct connman_device *device);
 int __connman_device_disable(struct connman_device *device);
 int __connman_device_disconnect(struct connman_device *device);
 
-connman_bool_t __connman_device_scanning(struct connman_device *device);
-
 connman_bool_t __connman_device_has_driver(struct connman_device *device);
 
 void __connman_device_set_reconnect(struct connman_device *device,
@@ -525,7 +526,7 @@ void __connman_config_cleanup(void);
 int __connman_config_load_service(GKeyFile *keyfile, const char *group, connman_bool_t persistent);
 int __connman_config_provision_service(struct connman_service *service);
 int __connman_config_provision_service_ident(struct connman_service *service,
-                                                       const char *ident);
+               const char *ident, const char *file, const char *entry);
 
 int __connman_tethering_init(void);
 void __connman_tethering_cleanup(void);
@@ -565,6 +566,7 @@ void __connman_service_list_struct(DBusMessageIter *iter);
 
 struct connman_service *__connman_service_lookup_from_network(struct connman_network *network);
 struct connman_service *__connman_service_lookup_from_index(int index);
+struct connman_service *__connman_service_lookup_from_ident(const char *identifier);
 struct connman_service *__connman_service_create_from_network(struct connman_network *network);
 struct connman_service *__connman_service_create_from_provider(struct connman_provider *provider);
 struct connman_service *__connman_service_get_default(void);
@@ -594,6 +596,9 @@ const char *__connman_service_get_phase2(struct connman_service *service);
 connman_bool_t __connman_service_wps_enabled(struct connman_service *service);
 int __connman_service_set_favorite(struct connman_service *service,
                                                connman_bool_t favorite);
+int __connman_service_set_favorite_delayed(struct connman_service *service,
+                                       connman_bool_t favorite,
+                                       gboolean delay_ordering);
 int __connman_service_set_immutable(struct connman_service *service,
                                                connman_bool_t immutable);
 void __connman_service_set_userconnect(struct connman_service *service,
@@ -619,8 +624,16 @@ int __connman_service_connect(struct connman_service *service);
 int __connman_service_disconnect(struct connman_service *service);
 int __connman_service_disconnect_all(void);
 void __connman_service_auto_connect(void);
+gboolean __connman_service_remove(struct connman_service *service);
+void __connman_service_set_hidden_data(struct connman_service *service,
+                               gpointer user_data);
+void __connman_service_return_error(struct connman_service *service,
+                               int error, gpointer user_data);
+void __connman_service_reply_dbus_pending(DBusMessage *pending, int error);
 
-void __connman_service_provision_changed(const char *ident);
+int __connman_service_provision_changed(const char *ident);
+void __connman_service_set_config(struct connman_service *service,
+                               const char *file_id, const char *section);
 
 const char *__connman_service_type2string(enum connman_service_type type);
 enum connman_service_type __connman_service_string2type(const char *str);
@@ -659,6 +672,7 @@ void __connman_service_set_agent_identity(struct connman_service *service,
                                                const char *agent_identity);
 int __connman_service_set_passphrase(struct connman_service *service,
                                        const char *passphrase);
+const char *__connman_service_get_passphrase(struct connman_service *service);
 void __connman_service_set_agent_passphrase(struct connman_service *service,
                                                const char *agent_passphrase);
 
@@ -687,6 +701,8 @@ GSequence *__connman_service_get_list(struct connman_session *session,
 
 void __connman_service_session_inc(struct connman_service *service);
 connman_bool_t __connman_service_session_dec(struct connman_service *service);
+void __connman_service_mark_dirty();
+void __connman_service_save(struct connman_service *service);
 
 #include <connman/notifier.h>
 
index c20b82c..f2f3ce5 100644 (file)
@@ -247,12 +247,7 @@ int __connman_device_disable(struct connman_device *device)
        }
 
        err = device->driver->disable(device);
-       if (err == 0) {
-               connman_device_set_powered(device, FALSE);
-               goto done;
-       }
-
-       if (err == -EALREADY) {
+       if (err == 0 || err == -EALREADY) {
                connman_device_set_powered(device, FALSE);
                goto done;
        }
@@ -598,13 +593,12 @@ int connman_device_set_powered(struct connman_device *device,
 
        type = __connman_device_get_service_type(device);
 
-       if (device->powered == TRUE)
-               __connman_technology_enabled(type);
-       else
+       if (device->powered == FALSE) {
                __connman_technology_disabled(type);
-
-       if (powered == FALSE)
                return 0;
+       }
+
+       __connman_technology_enabled(type);
 
        connman_device_set_disconnected(device, FALSE);
        device->scanning = FALSE;
@@ -703,15 +697,13 @@ void __connman_device_cleanup_networks(struct connman_device *device)
                                        remove_unavailable_network, NULL);
 }
 
-connman_bool_t __connman_device_scanning(struct connman_device *device)
+connman_bool_t connman_device_get_scanning(struct connman_device *device)
 {
        return device->scanning;
 }
 
 void connman_device_reset_scanning(struct connman_device *device)
 {
-       device->scanning = FALSE;
-
        g_hash_table_foreach(device->networks,
                                mark_network_available, NULL);
 }
@@ -1102,7 +1094,8 @@ int __connman_device_request_scan(enum connman_service_type type)
 
 int __connman_device_request_hidden_scan(struct connman_device *device,
                                const char *ssid, unsigned int ssid_len,
-                               const char *identity, const char *passphrase)
+                               const char *identity, const char *passphrase,
+                               void *user_data)
 {
        DBG("device %p", device);
 
@@ -1114,12 +1107,13 @@ int __connman_device_request_hidden_scan(struct connman_device *device,
                return -EALREADY;
 
        return device->driver->scan_hidden(device, ssid, ssid_len,
-                                       identity, passphrase);
+                                       identity, passphrase, user_data);
 }
 
 connman_bool_t __connman_device_isfiltered(const char *devname)
 {
        char **pattern;
+       char **blacklisted_interfaces;
 
        if (device_filter == NULL)
                goto nodevice;
@@ -1138,7 +1132,7 @@ nodevice:
        }
 
        if (nodevice_filter == NULL)
-               return FALSE;
+               goto list;
 
        for (pattern = nodevice_filter; *pattern; pattern++) {
                if (g_pattern_match_simple(*pattern, devname) == TRUE) {
@@ -1147,6 +1141,19 @@ nodevice:
                }
        }
 
+list:
+       blacklisted_interfaces =
+               connman_setting_get_string_list("NetworkInterfaceBlacklist");
+       if (blacklisted_interfaces == NULL)
+               return FALSE;
+
+       for (pattern = blacklisted_interfaces; *pattern; pattern++) {
+               if (g_str_has_prefix(devname, *pattern) == TRUE) {
+                       DBG("ignoring device %s (blacklist)", devname);
+                       return TRUE;
+               }
+       }
+
        return FALSE;
 }
 
index b267074..f4de736 100644 (file)
@@ -244,8 +244,7 @@ static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data)
                ip_change = FALSE;
 
        option = g_dhcp_client_get_option(dhcp_client, G_DHCP_DNS_SERVER);
-       for (ns_entries = 0, list = option; list; list = list->next)
-               ns_entries += 1;
+       ns_entries = g_list_length(option);
        nameservers = g_try_new0(char *, ns_entries + 1);
        if (nameservers != NULL) {
                for (i = 0, list = option; list; list = list->next, i++)
@@ -262,8 +261,7 @@ static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data)
                hostname = g_strdup(option->data);
 
        option = g_dhcp_client_get_option(dhcp_client, G_DHCP_NTP_SERVER);
-       for (ns_entries = 0, list = option; list; list = list->next)
-               ns_entries += 1;
+       ns_entries = g_list_length(option);
        timeservers = g_try_new0(char *, ns_entries + 1);
        if (timeservers != NULL) {
                for (i = 0, list = option; list; list = list->next, i++)
@@ -294,7 +292,8 @@ static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data)
 
                dhcp->nameservers = nameservers;
 
-               for (i = 0; dhcp->nameservers[i] != NULL; i++) {
+               for (i = 0; dhcp->nameservers != NULL &&
+                                       dhcp->nameservers[i] != NULL; i++) {
                        __connman_service_nameserver_append(service,
                                                dhcp->nameservers[i], FALSE);
                }
@@ -313,7 +312,8 @@ static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data)
 
                dhcp->timeservers = timeservers;
 
-               for (i = 0; dhcp->timeservers[i] != NULL; i++) {
+               for (i = 0; dhcp->timeservers != NULL &&
+                                        dhcp->timeservers[i] != NULL; i++) {
                        __connman_service_timeserver_append(service,
                                                        dhcp->timeservers[i]);
                }
index bf764c8..574b19e 100644 (file)
@@ -291,7 +291,8 @@ static void info_req_cb(GDHCPClient *dhcp_client, gpointer user_data)
 
                dhcp->nameservers = nameservers;
 
-               for (i = 0; dhcp->nameservers[i] != NULL; i++)
+               for (i = 0; dhcp->nameservers != NULL &&
+                                       dhcp->nameservers[i] != NULL; i++)
                        __connman_service_nameserver_append(service,
                                                dhcp->nameservers[i],
                                                FALSE);
@@ -318,7 +319,8 @@ static void info_req_cb(GDHCPClient *dhcp_client, gpointer user_data)
 
                dhcp->timeservers = timeservers;
 
-               for (i = 0; dhcp->timeservers[i] != NULL; i++)
+               for (i = 0; dhcp->timeservers != NULL &&
+                                       dhcp->timeservers[i] != NULL; i++)
                        __connman_service_timeserver_append(service,
                                                        dhcp->timeservers[i]);
        } else
@@ -469,7 +471,8 @@ static int set_addresses(GDHCPClient *dhcp_client,
 
                dhcp->nameservers = nameservers;
 
-               for (i = 0; dhcp->nameservers[i] != NULL; i++)
+               for (i = 0; dhcp->nameservers != NULL &&
+                                       dhcp->nameservers[i] != NULL; i++)
                        __connman_service_nameserver_append(service,
                                                        dhcp->nameservers[i],
                                                        FALSE);
@@ -496,7 +499,8 @@ static int set_addresses(GDHCPClient *dhcp_client,
 
                dhcp->timeservers = timeservers;
 
-               for (i = 0; dhcp->timeservers[i] != NULL; i++)
+               for (i = 0; dhcp->timeservers != NULL &&
+                                       dhcp->timeservers[i] != NULL; i++)
                        __connman_service_timeserver_append(service,
                                                        dhcp->timeservers[i]);
        } else
index 5404348..82c5c1f 100644 (file)
@@ -24,6 +24,7 @@
 #endif
 
 #include <errno.h>
+#include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 #include <stdint.h>
@@ -182,11 +183,14 @@ static GHashTable *cache;
 static int cache_refcount;
 static GSList *server_list = NULL;
 static GSList *request_list = NULL;
-static GSList *request_pending_list = NULL;
-static guint16 request_id = 0x0000;
 static GHashTable *listener_table = NULL;
 static time_t next_refresh;
 
+static guint16 get_id()
+{
+       return random();
+}
+
 static int protocol_offset(int protocol)
 {
        switch (protocol) {
@@ -372,15 +376,32 @@ static void send_cached_response(int sk, unsigned char *buf, int len,
                                int protocol, int id, uint16_t answers, int ttl)
 {
        struct domain_hdr *hdr;
-       int err, offset = protocol_offset(protocol);
+       unsigned char *ptr = buf;
+       int err, offset, dns_len, adj_len = len - 2;
 
-       if (offset < 0)
+       /*
+        * The cached packet contains always the TCP offset (two bytes)
+        * so skip them for UDP.
+        */
+       switch (protocol) {
+       case IPPROTO_UDP:
+               ptr += 2;
+               len -= 2;
+               dns_len = len;
+               offset = 0;
+               break;
+       case IPPROTO_TCP:
+               offset = 2;
+               dns_len = ptr[0] * 256 + ptr[1];
+               break;
+       default:
                return;
+       }
 
        if (len < 12)
                return;
 
-       hdr = (void *) (buf + offset);
+       hdr = (void *) (ptr + offset);
 
        hdr->id = id;
        hdr->qr = 1;
@@ -393,16 +414,22 @@ static void send_cached_response(int sk, unsigned char *buf, int len,
        if (answers == 0)
                hdr->aa = 1;
        else
-               update_cached_ttl(buf, len, ttl);
+               update_cached_ttl((unsigned char *)hdr, adj_len, ttl);
 
-       DBG("id 0x%04x answers %d", hdr->id, answers);
+       DBG("sk %d id 0x%04x answers %d ptr %p length %d dns %d",
+               sk, hdr->id, answers, ptr, len, dns_len);
 
-       err = sendto(sk, buf, len, 0, to, tolen);
+       err = sendto(sk, ptr, len, MSG_NOSIGNAL, to, tolen);
        if (err < 0) {
                connman_error("Cannot send cached DNS response: %s",
                                strerror(errno));
                return;
        }
+
+       if (err != len || (dns_len != (len - 2) && protocol == IPPROTO_TCP) ||
+                               (dns_len != len && protocol == IPPROTO_UDP))
+               DBG("Packet length mismatch, sent %d wanted %d dns %d",
+                       err, len, dns_len);
 }
 
 static void send_response(int sk, unsigned char *buf, int len,
@@ -412,7 +439,7 @@ static void send_response(int sk, unsigned char *buf, int len,
        struct domain_hdr *hdr;
        int err, offset = protocol_offset(protocol);
 
-       DBG("");
+       DBG("sk %d", sk);
 
        if (offset < 0)
                return;
@@ -431,10 +458,10 @@ static void send_response(int sk, unsigned char *buf, int len,
        hdr->nscount = 0;
        hdr->arcount = 0;
 
-       err = sendto(sk, buf, len, 0, to, tolen);
+       err = sendto(sk, buf, len, MSG_NOSIGNAL, to, tolen);
        if (err < 0) {
-               connman_error("Failed to send DNS response: %s",
-                               strerror(errno));
+               connman_error("Failed to send DNS response to %d: %s",
+                               sk, strerror(errno));
                return;
        }
 }
@@ -459,7 +486,7 @@ static gboolean request_timeout(gpointer user_data)
 
                sk = g_io_channel_unix_get_fd(ifdata->udp_listener_channel);
 
-               err = sendto(sk, req->resp, req->resplen, 0,
+               err = sendto(sk, req->resp, req->resplen, MSG_NOSIGNAL,
                                                &req->sa, req->sa_len);
                if (err < 0)
                        return FALSE;
@@ -494,53 +521,50 @@ static int append_query(unsigned char *buf, unsigned int size,
                                const char *query, const char *domain)
 {
        unsigned char *ptr = buf;
-       char *offset;
        int len;
 
        DBG("query %s domain %s", query, domain);
 
-       offset = (char *) query;
-       while (offset != NULL) {
-               char *tmp;
+       while (query != NULL) {
+               const char *tmp;
 
-               tmp = strchr(offset, '.');
+               tmp = strchr(query, '.');
                if (tmp == NULL) {
-                       len = strlen(offset);
+                       len = strlen(query);
                        if (len == 0)
                                break;
                        *ptr = len;
-                       memcpy(ptr + 1, offset, len);
+                       memcpy(ptr + 1, query, len);
                        ptr += len + 1;
                        break;
                }
 
-               *ptr = tmp - offset;
-               memcpy(ptr + 1, offset, tmp - offset);
-               ptr += tmp - offset + 1;
+               *ptr = tmp - query;
+               memcpy(ptr + 1, query, tmp - query);
+               ptr += tmp - query + 1;
 
-               offset = tmp + 1;
+               query = tmp + 1;
        }
 
-       offset = (char *) domain;
-       while (offset != NULL) {
-               char *tmp;
+       while (domain != NULL) {
+               const char *tmp;
 
-               tmp = strchr(offset, '.');
+               tmp = strchr(domain, '.');
                if (tmp == NULL) {
-                       len = strlen(offset);
+                       len = strlen(domain);
                        if (len == 0)
                                break;
                        *ptr = len;
-                       memcpy(ptr + 1, offset, len);
+                       memcpy(ptr + 1, domain, len);
                        ptr += len + 1;
                        break;
                }
 
-               *ptr = tmp - offset;
-               memcpy(ptr + 1, offset, tmp - offset);
-               ptr += tmp - offset + 1;
+               *ptr = tmp - domain;
+               memcpy(ptr + 1, domain, tmp - domain);
+               ptr += tmp - domain + 1;
 
-               offset = tmp + 1;
+               domain = tmp + 1;
        }
 
        *ptr++ = 0x00;
@@ -641,13 +665,22 @@ static uint16_t cache_check_validity(char *question, uint16_t type,
        return type;
 }
 
-static struct cache_entry *cache_check(gpointer request, int *qtype)
+static struct cache_entry *cache_check(gpointer request, int *qtype, int proto)
 {
-       char *question = request + 12;
+       char *question;
        struct cache_entry *entry;
        struct domain_question *q;
        uint16_t type;
-       int offset;
+       int offset, proto_offset;
+
+       if (request == NULL)
+               return NULL;
+
+       proto_offset = protocol_offset(proto);
+       if (proto_offset < 0)
+               return NULL;
+
+       question = request + proto_offset + 12;
 
        offset = strlen(question) + 1;
        q = (void *) (question + offset);
@@ -1201,7 +1234,6 @@ static int reply_query_type(unsigned char *msg, int len)
        /* now the query, which is a name and 2 16 bit words */
        l = dns_name_length(c) + 1;
        c += l;
-       len -= l;
        w = (uint16_t *) c;
        type = ntohs(*w);
 
@@ -1214,6 +1246,7 @@ static int cache_update(struct server_data *srv, unsigned char *msg,
        int offset = protocol_offset(srv->protocol);
        int err, qlen, ttl = 0;
        uint16_t answers = 0, type = 0, class = 0;
+       struct domain_hdr *hdr = (void *)(msg + offset);
        struct domain_question *q;
        struct cache_entry *entry;
        struct cache_data *data;
@@ -1238,12 +1271,13 @@ static int cache_update(struct server_data *srv, unsigned char *msg,
                next_refresh = current_time + 30;
        }
 
-
-       /* Continue only if response code is 0 (=ok) */
-       if (msg[3] & 0x0f)
+       if (offset < 0)
                return 0;
 
-       if (offset < 0)
+       DBG("offset %d hdr %p msg %p rcode %d", offset, hdr, msg, hdr->rcode);
+
+       /* Continue only if response code is 0 (=ok) */
+       if (hdr->rcode != 0)
                return 0;
 
        rsplen = sizeof(response) - 1;
@@ -1260,21 +1294,30 @@ static int cache_update(struct server_data *srv, unsigned char *msg,
         * to cache the negative response.
         */
        if ((err == -ENOMSG || err == -ENOBUFS) &&
-                       reply_query_type(msg, msg_len) == 28) {
+                       reply_query_type(msg + offset,
+                                       msg_len - offset) == 28) {
                entry = g_hash_table_lookup(cache, question);
                if (entry && entry->ipv4 && entry->ipv6 == NULL) {
+                       int cache_offset = 0;
+
                        data = g_try_new(struct cache_data, 1);
                        if (data == NULL)
                                return -ENOMEM;
                        data->inserted = entry->ipv4->inserted;
                        data->type = type;
-                       data->answers = msg[5];
+                       data->answers = hdr->ancount;
                        data->timeout = entry->ipv4->timeout;
-                       data->data_len = msg_len;
-                       data->data = ptr = g_malloc(msg_len);
+                       if (srv->protocol == IPPROTO_UDP)
+                               cache_offset = 2;
+                       data->data_len = msg_len + cache_offset;
+                       data->data = ptr = g_malloc(data->data_len);
+                       ptr[0] = (data->data_len - 2) / 256;
+                       ptr[1] = (data->data_len - 2) - ptr[0] * 256;
+                       if (srv->protocol == IPPROTO_UDP)
+                               ptr += 2;
                        data->valid_until = entry->ipv4->valid_until;
                        data->cache_until = entry->ipv4->cache_until;
-                       memcpy(data->data, msg, msg_len);
+                       memcpy(ptr, msg, msg_len);
                        entry->ipv6 = data;
                        /*
                         * we will get a "hit" when we serve the response
@@ -1354,7 +1397,12 @@ static int cache_update(struct server_data *srv, unsigned char *msg,
        data->type = type;
        data->answers = answers;
        data->timeout = ttl;
-       data->data_len = 12 + qlen + 1 + 2 + 2 + rsplen;
+       /*
+        * The "2" in start of the length is the TCP offset. We allocate it
+        * here even for UDP packet because it simplifies the sending
+        * of cached packet.
+        */
+       data->data_len = 2 + 12 + qlen + 1 + 2 + 2 + rsplen;
        data->data = ptr = g_malloc(data->data_len);
        data->valid_until = current_time + ttl;
 
@@ -1374,13 +1422,24 @@ static int cache_update(struct server_data *srv, unsigned char *msg,
                return -ENOMEM;
        }
 
-       memcpy(ptr, msg, 12);
-       memcpy(ptr + 12, question, qlen + 1); /* copy also the \0 */
+       /*
+        * We cache the two extra bytes at the start of the message
+        * in a TCP packet. When sending UDP packet, we skip the first
+        * two bytes. This way we do not need to know the format
+        * (UDP/TCP) of the cached message.
+        */
+       ptr[0] = (data->data_len - 2) / 256;
+       ptr[1] = (data->data_len - 2) - ptr[0] * 256;
+       if (srv->protocol == IPPROTO_UDP)
+               ptr += 2;
+
+       memcpy(ptr, msg, offset + 12);
+       memcpy(ptr + offset + 12, question, qlen + 1); /* copy also the \0 */
 
-       q = (void *) (ptr + 12 + qlen + 1);
+       q = (void *) (ptr + offset + 12 + qlen + 1);
        q->type = htons(type);
        q->class = htons(class);
-       memcpy(ptr + 12 + qlen + 1 + sizeof(struct domain_question),
+       memcpy(ptr + offset + 12 + qlen + 1 + sizeof(struct domain_question),
                response, rsplen);
 
        if (new_entry == TRUE) {
@@ -1388,10 +1447,15 @@ static int cache_update(struct server_data *srv, unsigned char *msg,
                cache_size++;
        }
 
-       DBG("cache %d %squestion \"%s\" type %d ttl %d size %zd",
+       DBG("cache %d %squestion \"%s\" type %d ttl %d size %zd packet %u "
+                                                               "dns len %u",
                cache_size, new_entry ? "new " : "old ",
                question, type, ttl,
-               sizeof(*entry) + sizeof(*data) + data->data_len + qlen);
+               sizeof(*entry) + sizeof(*data) + data->data_len + qlen,
+               data->data_len,
+               srv->protocol == IPPROTO_TCP ?
+                       (unsigned int)(data->data[0] * 256 + data->data[1]) :
+                       data->data_len);
 
        return 0;
 }
@@ -1404,7 +1468,7 @@ static int ns_resolv(struct server_data *server, struct request_data *req,
        char *dot, *lookup = (char *) name;
        struct cache_entry *entry;
 
-       entry = cache_check(request, &type);
+       entry = cache_check(request, &type, req->protocol);
        if (entry != NULL) {
                int ttl_left = 0;
                struct cache_data *data;
@@ -1442,7 +1506,9 @@ static int ns_resolv(struct server_data *server, struct request_data *req,
 
        sk = g_io_channel_unix_get_fd(server->channel);
 
-       err = send(sk, request, req->request_len, 0);
+       err = send(sk, request, req->request_len, MSG_NOSIGNAL);
+       if (err < 0)
+               return -EIO;
 
        req->numserv++;
 
@@ -1497,7 +1563,7 @@ static int ns_resolv(struct server_data *server, struct request_data *req,
                        alt[1] = req_len & 0xff;
                }
 
-               err = send(sk, alt, req->request_len + domlen, 0);
+               err = send(sk, alt, req->request_len + domlen, MSG_NOSIGNAL);
                if (err < 0)
                        return -EIO;
 
@@ -1507,6 +1573,17 @@ static int ns_resolv(struct server_data *server, struct request_data *req,
        return 0;
 }
 
+static void destroy_request_data(struct request_data *req)
+{
+       if (req->timeout > 0)
+               g_source_remove(req->timeout);
+
+       g_free(req->resp);
+       g_free(req->request);
+       g_free(req->name);
+       g_free(req);
+}
+
 static int forward_dns_reply(unsigned char *reply, int reply_len, int protocol,
                                struct server_data *data)
 {
@@ -1553,17 +1630,30 @@ static int forward_dns_reply(unsigned char *reply, int reply_len, int protocol,
                         */
                        ptr = reply + offset + sizeof(struct domain_hdr);
                        host_len = *ptr;
-                       domain_len = strlen((const char *)ptr) - host_len - 1;
+                       domain_len = strlen((const char *)ptr + host_len + 1);
 
                        /*
-                        * remove the domain name and replaced it by the end
-                        * of reply.
+                        * Remove the domain name and replace it by the end
+                        * of reply. Check if the domain is really there
+                        * before trying to copy the data. The domain_len can
+                        * be 0 because if the original query did not contain
+                        * a domain name, then we are sending two packets,
+                        * first without the domain name and the second packet
+                        * with domain name. The append_domain is set to true
+                        * even if we sent the first packet without domain
+                        * name. In this case we end up in this branch.
                         */
-                       memmove(ptr + host_len + 1,
-                               ptr + host_len + domain_len + 1,
-                               reply_len - (ptr - reply + domain_len));
+                       if (domain_len > 0) {
+                               /*
+                                * Note that we must use memmove() here,
+                                * because the memory areas can overlap.
+                                */
+                               memmove(ptr + host_len + 1,
+                                       ptr + host_len + domain_len + 1,
+                                       reply_len - (ptr - reply + domain_len));
 
-                       reply_len = reply_len - domain_len;
+                               reply_len = reply_len - domain_len;
+                       }
                }
 
                g_free(req->resp);
@@ -1582,9 +1672,6 @@ static int forward_dns_reply(unsigned char *reply, int reply_len, int protocol,
        if (hdr->rcode > 0 && req->numresp < req->numserv)
                return -EINVAL;
 
-       if (req->timeout > 0)
-               g_source_remove(req->timeout);
-
        request_list = g_slist_remove(request_list, req);
 
        if (protocol == IPPROTO_UDP) {
@@ -1593,12 +1680,17 @@ static int forward_dns_reply(unsigned char *reply, int reply_len, int protocol,
                             &req->sa, req->sa_len);
        } else {
                sk = req->client_sk;
-               err = send(sk, req->resp, req->resplen, 0);
+               err = send(sk, req->resp, req->resplen, MSG_NOSIGNAL);
                close(sk);
        }
 
-       g_free(req->resp);
-       g_free(req);
+       if (err < 0)
+               DBG("Cannot send msg, sk %d proto %d errno %d/%s", sk,
+                       protocol, errno, strerror(errno));
+       else
+               DBG("proto %d sent %d bytes to %d", protocol, err, sk);
+
+       destroy_request_data(req);
 
        return err;
 }
@@ -1643,7 +1735,8 @@ static void destroy_server(struct server_data *server)
 {
        GList *list;
 
-       DBG("interface %s server %s", server->interface, server->server);
+       DBG("interface %s server %s sock %d", server->interface, server->server,
+               g_io_channel_unix_get_fd(server->channel));
 
        server_list = g_slist_remove(server_list, server);
 
@@ -1656,7 +1749,7 @@ static void destroy_server(struct server_data *server)
        g_io_channel_unref(server->channel);
 
        if (server->protocol == IPPROTO_UDP)
-               connman_info("Removing DNS server %s", server->server);
+               DBG("Removing DNS server %s", server->server);
 
        g_free(server->incoming_reply);
        g_free(server->server);
@@ -1721,7 +1814,7 @@ static gboolean tcp_server_event(GIOChannel *channel, GIOCondition condition,
        if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
                GSList *list;
 hangup:
-               DBG("TCP server channel closed");
+               DBG("TCP server channel closed, sk %d", sk);
 
                /*
                 * Discard any partial response which is buffered; better
@@ -1764,6 +1857,7 @@ hangup:
        if ((condition & G_IO_OUT) && !server->connected) {
                GSList *list;
                GList *domains;
+               int no_request_sent = TRUE;
                struct server_data *udp_server;
 
                udp_server = find_server(server->interface, server->server,
@@ -1789,29 +1883,48 @@ hangup:
                        server->timeout = 0;
                }
 
-               for (list = request_list; list; list = list->next) {
+               for (list = request_list; list; ) {
                        struct request_data *req = list->data;
+                       int status;
 
-                       if (req->protocol == IPPROTO_UDP)
+                       if (req->protocol == IPPROTO_UDP) {
+                               list = list->next;
                                continue;
+                       }
 
                        DBG("Sending req %s over TCP", (char *)req->name);
 
+                       status = ns_resolv(server, req,
+                                               req->request, req->name);
+                       if (status > 0) {
+                               /*
+                                * A cached result was sent,
+                                * so the request can be released
+                                */
+                               list = list->next;
+                               request_list = g_slist_remove(request_list, req);
+                               destroy_request_data(req);
+                               continue;
+                       }
+
+                       if (status < 0) {
+                               list = list->next;
+                               continue;
+                       }
+
+                       no_request_sent = FALSE;
+
                        if (req->timeout > 0)
                                g_source_remove(req->timeout);
 
                        req->timeout = g_timeout_add_seconds(30,
                                                request_timeout, req);
-                       if (ns_resolv(server, req, req->request,
-                                       req->name) > 0) {
-                               /* We sent cached result so no need for timeout
-                                * handler.
-                                */
-                               if (req->timeout > 0) {
-                                       g_source_remove(req->timeout);
-                                       req->timeout = 0;
-                               }
-                       }
+                       list = list->next;
+               }
+
+               if (no_request_sent == TRUE) {
+                       destroy_server(server);
+                       return FALSE;
                }
 
        } else if (condition & G_IO_IN) {
@@ -1838,7 +1951,7 @@ hangup:
                        reply_len = reply_len_buf[1] | reply_len_buf[0] << 8;
                        reply_len += 2;
 
-                       DBG("TCP reply %d bytes", reply_len);
+                       DBG("TCP reply %d bytes from %d", reply_len, sk);
 
                        reply = g_try_malloc(sizeof(*reply) + reply_len + 2);
                        if (!reply)
@@ -1939,6 +2052,8 @@ static struct server_data *create_server(const char *interface,
                return NULL;
        }
 
+       DBG("sk %d", sk);
+
        if (interface != NULL) {
                if (setsockopt(sk, SOL_SOCKET, SO_BINDTODEVICE,
                                interface, strlen(interface) + 1) < 0) {
@@ -2027,21 +2142,18 @@ static struct server_data *create_server(const char *interface,
        if (protocol == IPPROTO_UDP) {
                /* Enable new servers by default */
                data->enabled = TRUE;
-               connman_info("Adding DNS server %s", data->server);
+               DBG("Adding DNS server %s", data->server);
 
                server_list = g_slist_append(server_list, data);
-
-               return data;
        }
 
-       return NULL;
+       return data;
 }
 
 static gboolean resolv(struct request_data *req,
                                gpointer request, gpointer name)
 {
        GSList *list;
-       int status;
 
        for (list = server_list; list; list = list->next) {
                struct server_data *data = list->data;
@@ -2056,19 +2168,11 @@ static gboolean resolv(struct request_data *req,
                                G_IO_IN | G_IO_NVAL | G_IO_ERR | G_IO_HUP,
                                                udp_server_event, data);
 
-               status = ns_resolv(data, req, request, name);
-               if (status < 0)
-                       continue;
-
-               if (status > 0) {
-                       if (req->timeout > 0) {
-                               g_source_remove(req->timeout);
-                               req->timeout = 0;
-                       }
-               }
+               if (ns_resolv(data, req, request, name) > 0)
+                       return TRUE;
        }
 
-       return TRUE;
+       return FALSE;
 }
 
 static void append_domain(const char *interface, const char *domain)
@@ -2174,17 +2278,26 @@ void __connman_dnsproxy_flush(void)
 {
        GSList *list;
 
-       list = request_pending_list;
+       list = request_list;
        while (list) {
                struct request_data *req = list->data;
 
                list = list->next;
 
-               request_pending_list =
-                               g_slist_remove(request_pending_list, req);
-               resolv(req, req->request, req->name);
-               g_free(req->request);
-               g_free(req->name);
+               if (resolv(req, req->request, req->name) == TRUE) {
+                       /*
+                        * A cached result was sent,
+                        * so the request can be released
+                        */
+                       request_list =
+                               g_slist_remove(request_list, req);
+                       destroy_request_data(req);
+                       continue;
+               }
+
+               if (req->timeout > 0)
+                       g_source_remove(req->timeout);
+               req->timeout = g_timeout_add_seconds(5, request_timeout, req);
        }
 }
 
@@ -2198,12 +2311,12 @@ static void dnsproxy_offline_mode(connman_bool_t enabled)
                struct server_data *data = list->data;
 
                if (enabled == FALSE) {
-                       connman_info("Enabling DNS server %s", data->server);
+                       DBG("Enabling DNS server %s", data->server);
                        data->enabled = TRUE;
                        cache_invalidate();
                        cache_refresh();
                } else {
-                       connman_info("Disabling DNS server %s", data->server);
+                       DBG("Disabling DNS server %s", data->server);
                        data->enabled = FALSE;
                        cache_invalidate();
                }
@@ -2234,10 +2347,10 @@ static void dnsproxy_default_changed(struct connman_service *service)
                struct server_data *data = list->data;
 
                if (g_strcmp0(data->interface, interface) == 0) {
-                       connman_info("Enabling DNS server %s", data->server);
+                       DBG("Enabling DNS server %s", data->server);
                        data->enabled = TRUE;
                } else {
-                       connman_info("Disabling DNS server %s", data->server);
+                       DBG("Disabling DNS server %s", data->server);
                        data->enabled = FALSE;
                }
        }
@@ -2274,7 +2387,7 @@ static int parse_request(unsigned char *buf, int len,
        if (hdr->qr != 0 || qdcount != 1)
                return -EINVAL;
 
-       memset(name, 0, size);
+       name[0] = '\0';
 
        ptr = buf + sizeof(struct domain_hdr);
        remain = len - sizeof(struct domain_hdr);
@@ -2332,12 +2445,13 @@ static gboolean tcp_listener_event(GIOChannel *channel, GIOCondition condition,
        unsigned char buf[768];
        char query[512];
        struct request_data *req;
-       struct server_data *server;
        int sk, client_sk, len, err;
        struct sockaddr_in6 client_addr;
        socklen_t client_addr_len = sizeof(client_addr);
        GSList *list;
        struct listener_data *ifdata = user_data;
+       int waiting_for_connect = FALSE, qtype = 0;
+       struct cache_entry *entry;
 
        DBG("condition 0x%x", condition);
 
@@ -2364,7 +2478,8 @@ static gboolean tcp_listener_event(GIOChannel *channel, GIOCondition condition,
        if (len < 2)
                return TRUE;
 
-       DBG("Received %d bytes (id 0x%04x)", len, buf[2] | buf[3] << 8);
+       DBG("Received %d bytes (id 0x%04x) from %d", len,
+               buf[2] | buf[3] << 8, client_sk);
 
        err = parse_request(buf + 2, len - 2, query, sizeof(query));
        if (err < 0 || (g_slist_length(server_list) == 0)) {
@@ -2381,13 +2496,9 @@ static gboolean tcp_listener_event(GIOChannel *channel, GIOCondition condition,
        req->client_sk = client_sk;
        req->protocol = IPPROTO_TCP;
 
-       request_id += 2;
-       if (request_id == 0x0000 || request_id == 0xffff)
-               request_id += 2;
-
        req->srcid = buf[2] | (buf[3] << 8);
-       req->dstid = request_id;
-       req->altid = request_id + 1;
+       req->dstid = get_id();
+       req->altid = get_id();
        req->request_len = len;
 
        buf[2] = req->dstid & 0xff;
@@ -2396,63 +2507,82 @@ static gboolean tcp_listener_event(GIOChannel *channel, GIOCondition condition,
        req->numserv = 0;
        req->ifdata = (struct listener_data *) ifdata;
        req->append_domain = FALSE;
-       request_list = g_slist_append(request_list, req);
 
-       for (list = server_list; list; list = list->next) {
-               struct server_data *data = list->data;
-               GList *domains;
+       /*
+        * Check if the answer is found in the cache before
+        * creating sockets to the server.
+        */
+       entry = cache_check(buf, &qtype, IPPROTO_TCP);
+       if (entry != NULL) {
+               int ttl_left = 0;
+               struct cache_data *data;
 
-               if (data->protocol != IPPROTO_UDP || data->enabled == FALSE)
-                       continue;
+               DBG("cache hit %s type %s", query, qtype == 1 ? "A" : "AAAA");
+               if (qtype == 1)
+                       data = entry->ipv4;
+               else
+                       data = entry->ipv6;
 
-               server = create_server(data->interface, NULL,
-                                       data->server, IPPROTO_TCP);
+               if (data != NULL) {
+                       ttl_left = data->valid_until - time(NULL);
+                       entry->hits++;
 
-               /*
-                * If server is NULL, we're not connected yet.
-                * Copy the relevant buffers and continue with
-                * the next nameserver.
-                * The request will actually be sent once we're
-                * properly connected over TCP to this nameserver.
-                */
-               if (server == NULL) {
-                       req->request = g_try_malloc0(req->request_len);
-                       if (req->request == NULL)
-                               return TRUE;
+                       send_cached_response(client_sk, data->data,
+                                       data->data_len, NULL, 0, IPPROTO_TCP,
+                                       req->srcid, data->answers, ttl_left);
 
-                       memcpy(req->request, buf, req->request_len);
+                       g_free(req);
+                       return TRUE;
+               } else
+                       DBG("data missing, ignoring cache for this query");
+       }
 
-                       req->name = g_try_malloc0(sizeof(query));
-                       if (req->name == NULL) {
-                               g_free(req->request);
-                               return TRUE;
-                       }
-                       memcpy(req->name, query, sizeof(query));
+       for (list = server_list; list; list = list->next) {
+               struct server_data *data = list->data;
 
+               if (data->protocol != IPPROTO_UDP || data->enabled == FALSE)
                        continue;
-               }
 
-               if (req->timeout > 0)
-                       g_source_remove(req->timeout);
+               if(create_server(data->interface, NULL,
+                                       data->server, IPPROTO_TCP) == NULL)
+                       continue;
 
-               for (domains = data->domains; domains;
-                               domains = domains->next) {
-                       char *dom = domains->data;
+               waiting_for_connect = TRUE;
+       }
 
-                       DBG("Adding domain %s to %s", dom, server->server);
+       if (waiting_for_connect == FALSE) {
+               /* No server is waiting for connect */
+               send_response(client_sk, buf, len, NULL, 0, IPPROTO_TCP);
+               g_free(req);
+               return TRUE;
+       }
 
-                       server->domains = g_list_append(server->domains,
-                                               g_strdup(dom));
-               }
+       /*
+        * The server is not connected yet.
+        * Copy the relevant buffers.
+        * The request will actually be sent once we're
+        * properly connected over TCP to the nameserver.
+        */
+       req->request = g_try_malloc0(req->request_len);
+       if (req->request == NULL) {
+               send_response(client_sk, buf, len, NULL, 0, IPPROTO_TCP);
+               g_free(req);
+               return TRUE;
+       }
+       memcpy(req->request, buf, req->request_len);
 
-               req->timeout = g_timeout_add_seconds(30, request_timeout, req);
-               if (ns_resolv(server, req, buf, query) > 0) {
-                       if (req->timeout > 0) {
-                               g_source_remove(req->timeout);
-                               req->timeout = 0;
-                       }
-               }
+       req->name = g_try_malloc0(sizeof(query));
+       if (req->name == NULL) {
+               send_response(client_sk, buf, len, NULL, 0, IPPROTO_TCP);
+               g_free(req->request);
+               g_free(req);
+               return TRUE;
        }
+       memcpy(req->name, query, sizeof(query));
+
+       req->timeout = g_timeout_add_seconds(30, request_timeout, req);
+
+       request_list = g_slist_append(request_list, req);
 
        return TRUE;
 }
@@ -2500,13 +2630,9 @@ static gboolean udp_listener_event(GIOChannel *channel, GIOCondition condition,
        req->client_sk = 0;
        req->protocol = IPPROTO_UDP;
 
-       request_id += 2;
-       if (request_id == 0x0000 || request_id == 0xffff)
-               request_id += 2;
-
        req->srcid = buf[0] | (buf[1] << 8);
-       req->dstid = request_id;
-       req->altid = request_id + 1;
+       req->dstid = get_id();
+       req->altid = get_id();
        req->request_len = len;
 
        buf[0] = req->dstid & 0xff;
@@ -2514,11 +2640,18 @@ static gboolean udp_listener_event(GIOChannel *channel, GIOCondition condition,
 
        req->numserv = 0;
        req->ifdata = (struct listener_data *) ifdata;
-       req->timeout = g_timeout_add_seconds(5, request_timeout, req);
        req->append_domain = FALSE;
+
+       if (resolv(req, buf, query) == TRUE) {
+               /* a cached result was sent, so the request can be released */
+               g_free(req);
+               return TRUE;
+       }
+
+       req->timeout = g_timeout_add_seconds(5, request_timeout, req);
        request_list = g_slist_append(request_list, req);
 
-       return resolv(req, buf, query);
+       return TRUE;
 }
 
 static int create_dns_listener(int protocol, struct listener_data *ifdata)
@@ -2668,17 +2801,6 @@ static int create_listener(struct listener_data *ifdata)
        return 0;
 }
 
-static void destroy_request_data(struct request_data *req)
-{
-       if (req->timeout > 0)
-               g_source_remove(req->timeout);
-
-       g_free(req->resp);
-       g_free(req->request);
-       g_free(req->name);
-       g_free(req);
-}
-
 static void destroy_listener(struct listener_data *ifdata)
 {
        GSList *list;
@@ -2686,18 +2808,6 @@ static void destroy_listener(struct listener_data *ifdata)
        if (g_strcmp0(ifdata->ifname, "lo") == 0)
                __connman_resolvfile_remove("lo", NULL, "127.0.0.1");
 
-       for (list = request_pending_list; list; list = list->next) {
-               struct request_data *req = list->data;
-
-               DBG("Dropping pending request (id 0x%04x -> 0x%04x)",
-                                               req->srcid, req->dstid);
-               destroy_request_data(req);
-               list->data = NULL;
-       }
-
-       g_slist_free(request_pending_list);
-       request_pending_list = NULL;
-
        for (list = request_list; list; list = list->next) {
                struct request_data *req = list->data;
 
@@ -2777,6 +2887,8 @@ int __connman_dnsproxy_init(void)
 
        DBG("");
 
+       srandom(time(NULL));
+
        listener_table = g_hash_table_new_full(g_str_hash, g_str_equal,
                                                        g_free, g_free);
        err = __connman_dnsproxy_add_listener("lo");
index effa68c..7208d4e 100644 (file)
@@ -2174,6 +2174,24 @@ int __connman_inet_rtnl_addattr32(struct nlmsghdr *n, size_t maxlen, int type,
        return 0;
 }
 
+int connman_inet_check_ipaddress(const char *host)
+{
+       struct addrinfo hints;
+       struct addrinfo *addr;
+       int result;
+
+       memset(&hints, 0, sizeof(struct addrinfo));
+       hints.ai_flags = AI_NUMERICHOST;
+       addr = NULL;
+
+       result = getaddrinfo(host, NULL, &hints, &addr);
+       if (result == 0)
+               result = addr->ai_family;
+       freeaddrinfo(addr);
+
+       return result;
+}
+
 /* Check routine modified from ics-dhcp 4.2.3-P2 */
 connman_bool_t connman_inet_check_hostname(const char *ptr, size_t len)
 {
index 5f6e950..5e34ac0 100644 (file)
@@ -1245,6 +1245,7 @@ void __connman_ipconfig_set_prefixlen(struct connman_ipconfig *ipconfig, unsigne
 static struct connman_ipconfig *create_ipv6config(int index)
 {
        struct connman_ipconfig *ipv6config;
+       struct connman_ipdevice *ipdevice;
 
        DBG("index %d", index);
 
@@ -1258,7 +1259,10 @@ static struct connman_ipconfig *create_ipv6config(int index)
        ipv6config->enabled = FALSE;
        ipv6config->type = CONNMAN_IPCONFIG_TYPE_IPV6;
        ipv6config->method = CONNMAN_IPCONFIG_METHOD_AUTO;
-       ipv6config->ipv6_privacy_config = 0;
+
+       ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
+       if (ipdevice != NULL)
+               ipv6config->ipv6_privacy_config = ipdevice->ipv6_privacy;
 
        ipv6config->address = connman_ipaddress_alloc(AF_INET6);
        if (ipv6config->address == NULL) {
@@ -1849,6 +1853,7 @@ static int string2privacy(const char *privacy)
 void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig,
                                                        DBusMessageIter *iter)
 {
+       struct connman_ipaddress *append_addr = NULL;
        const char *str;
 
        DBG("");
@@ -1862,33 +1867,52 @@ void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig,
 
        connman_dbus_dict_append_basic(iter, "Method", DBUS_TYPE_STRING, &str);
 
-       if (ipconfig->system == NULL)
+       append_addr = ipconfig->system;
+
+       switch (ipconfig->method) {
+       case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
+       case CONNMAN_IPCONFIG_METHOD_OFF:
+               return;
+
+       case CONNMAN_IPCONFIG_METHOD_FIXED:
+               if (append_addr == NULL)
+                       append_addr = ipconfig->address;
+               break;
+
+       case CONNMAN_IPCONFIG_METHOD_MANUAL:
+       case CONNMAN_IPCONFIG_METHOD_DHCP:
+       case CONNMAN_IPCONFIG_METHOD_AUTO:
+               break;
+       }
+
+       if (append_addr == NULL)
                return;
 
-       if (ipconfig->system->local != NULL) {
+       if (append_addr->local != NULL) {
                in_addr_t addr;
                struct in_addr netmask;
                char *mask;
 
                connman_dbus_dict_append_basic(iter, "Address",
-                               DBUS_TYPE_STRING, &ipconfig->system->local);
+                               DBUS_TYPE_STRING, &append_addr->local);
 
-               addr = 0xffffffff << (32 - ipconfig->system->prefixlen);
+               addr = 0xffffffff << (32 - append_addr->prefixlen);
                netmask.s_addr = htonl(addr);
                mask = inet_ntoa(netmask);
                connman_dbus_dict_append_basic(iter, "Netmask",
                                                DBUS_TYPE_STRING, &mask);
        }
 
-       if (ipconfig->system->gateway != NULL)
+       if (append_addr->gateway != NULL)
                connman_dbus_dict_append_basic(iter, "Gateway",
-                               DBUS_TYPE_STRING, &ipconfig->system->gateway);
+                               DBUS_TYPE_STRING, &append_addr->gateway);
 }
 
 void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig,
                                        DBusMessageIter *iter,
                                        struct connman_ipconfig *ipconfig_ipv4)
 {
+       struct connman_ipaddress *append_addr = NULL;
        const char *str, *privacy;
 
        DBG("");
@@ -1908,20 +1932,38 @@ void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig,
 
        connman_dbus_dict_append_basic(iter, "Method", DBUS_TYPE_STRING, &str);
 
-       if (ipconfig->system == NULL)
+       append_addr = ipconfig->system;
+
+       switch (ipconfig->method) {
+       case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
+       case CONNMAN_IPCONFIG_METHOD_OFF:
+               return;
+
+       case CONNMAN_IPCONFIG_METHOD_FIXED:
+               if (append_addr == NULL)
+                       append_addr = ipconfig->address;
+               break;
+
+       case CONNMAN_IPCONFIG_METHOD_MANUAL:
+       case CONNMAN_IPCONFIG_METHOD_DHCP:
+       case CONNMAN_IPCONFIG_METHOD_AUTO:
+               break;
+       }
+
+       if (append_addr == NULL)
                return;
 
-       if (ipconfig->system->local != NULL) {
+       if (append_addr->local != NULL) {
                connman_dbus_dict_append_basic(iter, "Address",
-                               DBUS_TYPE_STRING, &ipconfig->system->local);
+                               DBUS_TYPE_STRING, &append_addr->local);
                connman_dbus_dict_append_basic(iter, "PrefixLength",
                                                DBUS_TYPE_BYTE,
-                                               &ipconfig->system->prefixlen);
+                                               &append_addr->prefixlen);
        }
 
-       if (ipconfig->system->gateway != NULL)
+       if (append_addr->gateway != NULL)
                connman_dbus_dict_append_basic(iter, "Gateway",
-                               DBUS_TYPE_STRING, &ipconfig->system->gateway);
+                               DBUS_TYPE_STRING, &append_addr->gateway);
 
        privacy = privacy2string(ipconfig->ipv6_privacy_config);
        connman_dbus_dict_append_basic(iter, "Privacy",
@@ -2302,8 +2344,9 @@ int __connman_ipconfig_save(struct connman_ipconfig *ipconfig,
        }
 
        key = g_strdup_printf("%snetmask_prefixlen", prefix);
-       g_key_file_set_integer(keyfile, identifier,
-                       key, ipconfig->address->prefixlen);
+       if (ipconfig->address->prefixlen != 0)
+               g_key_file_set_integer(keyfile, identifier,
+                               key, ipconfig->address->prefixlen);
        g_free(key);
 
        key = g_strdup_printf("%slocal_address", prefix);
index 58a0d28..52446ce 100644 (file)
@@ -258,7 +258,11 @@ void __connman_ippool_newaddr(int index, const char *address,
        if (is_private_address(start) == FALSE)
                return;
 
-       mask = ~(0xffffffff >> prefixlen);
+       if (prefixlen >= 32)
+               mask = 0xffffffff;
+       else
+               mask = ~(0xffffffff >> prefixlen);
+
        start = start & mask;
        end = start | ~mask;
 
index 7b0e25d..531e933 100644 (file)
@@ -1526,7 +1526,7 @@ static int iptables_command(int argc, char *argv[])
        insert = FALSE;
        delete = FALSE;
        compare = FALSE;
-       table_name = chain = new_chain = match_name = target_name = NULL;
+       chain = new_chain = match_name = target_name = NULL;
        flush_chain = delete_chain = policy = NULL;
        memset(&ip, 0, sizeof(struct ipt_ip));
        table = NULL;
index 48a956c..a39adb3 100644 (file)
 
 #include "connman.h"
 
+#define DEFAULT_INPUT_REQUEST_TIMEOUT 120 * 1000
+#define DEFAULT_BROWSER_LAUNCH_TIMEOUT 300 * 1000
+
 static struct {
        connman_bool_t bg_scan;
        char **pref_timeservers;
        unsigned int *auto_connect;
        unsigned int *preferred_techs;
        char **fallback_nameservers;
+       unsigned int timeout_inputreq;
+       unsigned int timeout_browserlaunch;
+       char **blacklisted_interfaces;
 } connman_settings  = {
        .bg_scan = TRUE,
        .pref_timeservers = NULL,
        .auto_connect = NULL,
        .preferred_techs = NULL,
        .fallback_nameservers = NULL,
+       .timeout_inputreq = DEFAULT_INPUT_REQUEST_TIMEOUT,
+       .timeout_browserlaunch = DEFAULT_BROWSER_LAUNCH_TIMEOUT,
+       .blacklisted_interfaces = NULL,
 };
 
 static GKeyFile *load_config(const char *file)
@@ -106,8 +115,6 @@ static char **parse_fallback_nameservers(char **nameservers, gsize len)
 {
        char **servers;
        int i, j;
-       struct addrinfo hints;
-       struct addrinfo *addr;
 
        servers = g_try_new0(char *, len + 1);
        if (servers == NULL)
@@ -116,15 +123,10 @@ static char **parse_fallback_nameservers(char **nameservers, gsize len)
        i = 0;
        j = 0;
        while (nameservers[i] != NULL) {
-               memset(&hints, 0, sizeof(struct addrinfo));
-               hints.ai_flags = AI_NUMERICHOST;
-               addr = NULL;
-               if (getaddrinfo(nameservers[i], NULL, &hints, &addr) == 0) {
+               if (connman_inet_check_ipaddress(nameservers[i]) > 0) {
                        servers[j] = g_strdup(nameservers[i]);
                        j += 1;
                }
-
-               freeaddrinfo(addr);
                i += 1;
        }
 
@@ -136,18 +138,27 @@ static void parse_config(GKeyFile *config)
        GError *error = NULL;
        gboolean boolean;
        char **timeservers;
+       char **interfaces;
        char **str_list;
        gsize len;
-       char *default_auto_connect[] = {
+       static char *default_auto_connect[] = {
                "wifi",
                "ethernet",
                "cellular",
                NULL
        };
+       static char *default_blacklist[] = {
+               "vmnet",
+               "vboxnet",
+               "virbr",
+               NULL
+       };
+       int timeout;
 
        if (config == NULL) {
                connman_settings.auto_connect =
                        parse_service_types(default_auto_connect, 3);
+               connman_settings.blacklisted_interfaces = default_blacklist;
                return;
        }
 
@@ -202,6 +213,30 @@ static void parse_config(GKeyFile *config)
        g_strfreev(str_list);
 
        g_clear_error(&error);
+
+       timeout = g_key_file_get_integer(config, "General",
+                       "InputRequestTimeout", &error);
+       if (error == NULL && timeout >= 0)
+               connman_settings.timeout_inputreq = timeout * 1000;
+
+       g_clear_error(&error);
+
+       timeout = g_key_file_get_integer(config, "General",
+                       "BrowserLaunchTimeout", &error);
+       if (error == NULL && timeout >= 0)
+               connman_settings.timeout_browserlaunch = timeout * 1000;
+
+       g_clear_error(&error);
+
+       interfaces = g_key_file_get_string_list(config, "General",
+                       "NetworkInterfaceBlacklist", &len, &error);
+
+       if (error == NULL)
+               connman_settings.blacklisted_interfaces = interfaces;
+       else
+               connman_settings.blacklisted_interfaces = default_blacklist;
+
+       g_clear_error(&error);
 }
 
 static GMainLoop *main_loop = NULL;
@@ -360,6 +395,9 @@ char **connman_setting_get_string_list(const char *key)
        if (g_str_equal(key, "FallbackNameservers") == TRUE)
                return connman_settings.fallback_nameservers;
 
+       if (g_str_equal(key, "NetworkInterfaceBlacklist") == TRUE)
+               return connman_settings.blacklisted_interfaces;
+
        return NULL;
 }
 
@@ -374,6 +412,14 @@ unsigned int *connman_setting_get_uint_list(const char *key)
        return NULL;
 }
 
+unsigned int connman_timeout_input_request(void) {
+       return connman_settings.timeout_inputreq;
+}
+
+unsigned int connman_timeout_browser_launch(void) {
+       return connman_settings.timeout_browserlaunch;
+}
+
 int main(int argc, char *argv[])
 {
        GOptionContext *context;
index 86e846e..1bf9189 100644 (file)
@@ -393,34 +393,69 @@ static DBusMessage *release_private_network(DBusConnection *conn,
        return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
 
-static GDBusMethodTable manager_methods[] = {
-       { "GetProperties",     "",      "a{sv}", get_properties     },
-       { "SetProperty",       "sv",    "",      set_property,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "GetTechnologies",   "",      "a(oa{sv})", get_technologies   },
-       { "RemoveProvider",    "o",     "",      remove_provider    },
-       { "GetServices",       "",      "a(oa{sv})", get_services   },
-       { "ConnectProvider",   "a{sv}", "o",     connect_provider,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "RegisterAgent",     "o",     "",      register_agent     },
-       { "UnregisterAgent",   "o",     "",      unregister_agent   },
-       { "RegisterCounter",   "ouu",   "",      register_counter   },
-       { "UnregisterCounter", "o",     "",      unregister_counter },
-       { "CreateSession",     "a{sv}o", "o",    create_session     },
-       { "DestroySession",    "o",     "",      destroy_session    },
-       { "RequestPrivateNetwork",    "",     "oa{sv}h",
-                                               request_private_network,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "ReleasePrivateNetwork",    "o",    "",
-                                               release_private_network },
+static const GDBusMethodTable manager_methods[] = {
+       { GDBUS_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       get_properties) },
+       { GDBUS_ASYNC_METHOD("SetProperty",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
+                       NULL, set_property) },
+       { GDBUS_METHOD("GetTechnologies",
+                       NULL, GDBUS_ARGS({ "technologies", "a(oa{sv})" }),
+                       get_technologies) },
+       { GDBUS_METHOD("RemoveProvider",
+                       GDBUS_ARGS({ "provider", "o" }), NULL,
+                       remove_provider) },
+       { GDBUS_METHOD("GetServices",
+                       NULL, GDBUS_ARGS({ "services", "a(oa{sv})" }),
+                       get_services) },
+       { GDBUS_ASYNC_METHOD("ConnectProvider",
+                             GDBUS_ARGS({ "provider", "a{sv}" }),
+                             GDBUS_ARGS({ "path", "o" }),
+                             connect_provider) },
+       { GDBUS_METHOD("RegisterAgent",
+                       GDBUS_ARGS({ "path", "o" }), NULL,
+                       register_agent) },
+       { GDBUS_METHOD("UnregisterAgent",
+                       GDBUS_ARGS({ "path", "o" }), NULL,
+                       unregister_agent) },
+       { GDBUS_METHOD("RegisterCounter",
+                       GDBUS_ARGS({ "path", "o" }, { "accuracy", "u" },
+                                       { "period", "u" }),
+                       NULL, register_counter) },
+       { GDBUS_METHOD("UnregisterCounter",
+                       GDBUS_ARGS({ "path", "o" }), NULL,
+                       unregister_counter) },
+       { GDBUS_METHOD("CreateSession",
+                       GDBUS_ARGS({ "settings", "a{sv}" },
+                                               { "notifier", "o" }),
+                       GDBUS_ARGS({ "session", "o" }),
+                       create_session) },
+       { GDBUS_METHOD("DestroySession",
+                       GDBUS_ARGS({ "session", "o" }), NULL,
+                       destroy_session) },
+       { GDBUS_ASYNC_METHOD("RequestPrivateNetwork",
+                             NULL, GDBUS_ARGS({ "path", "o" },
+                                              { "settings", "a{sv}" },
+                                              { "socket", "h" }),
+                             request_private_network) },
+       { GDBUS_METHOD("ReleasePrivateNetwork",
+                       GDBUS_ARGS({ "path", "o" }), NULL,
+                       release_private_network) },
        { },
 };
 
-static GDBusSignalTable manager_signals[] = {
-       { "PropertyChanged", "sv" },
-       { "TechnologyAdded", "oa{sv}" },
-       { "TechnologyRemoved", "o" },
-       { "ServicesChanged",   "a(oa{sv})ao" },
+static const GDBusSignalTable manager_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
+       { GDBUS_SIGNAL("TechnologyAdded",
+                       GDBUS_ARGS({ "path", "o" },
+                                  { "properties", "a{sv}" })) },
+       { GDBUS_SIGNAL("TechnologyRemoved",
+                       GDBUS_ARGS({ "path", "o" })) },
+       { GDBUS_SIGNAL("ServicesChanged",
+                       GDBUS_ARGS({ "changed", "a(oa{sv})" },
+                                       { "removed", "ao" })) },
        { },
 };
 
index 10f1bf3..bf01767 100644 (file)
 
 #include "connman.h"
 
+/*
+ * How many times to send RS with the purpose of
+ * refreshing RDNSS entries before they actually expire.
+ * With a value of 1, one RS will be sent, with no retries.
+ */
+#define RS_REFRESH_COUNT       1
+
+/*
+ * Value in seconds to wait for RA after RS was sent.
+ * After this time elapsed, we can send another RS.
+ */
+#define RS_REFRESH_TIMEOUT     3
+
 static GSList *network_list = NULL;
 static GSList *driver_list = NULL;
 
@@ -46,6 +59,7 @@ struct connman_network {
        char *path;
        int index;
        int router_solicit_count;
+       int router_solicit_refresh_count;
 
        struct connman_network_driver *driver;
        void *driver_data;
@@ -1113,6 +1127,58 @@ static void check_dhcpv6(struct nd_router_advert *reply,
        connman_network_unref(network);
 }
 
+static void receive_refresh_rs_reply(struct nd_router_advert *reply,
+               unsigned int length, void *user_data)
+{
+       struct connman_network *network = user_data;
+
+       DBG("reply %p", reply);
+
+       if (reply == NULL) {
+               /*
+                * Router solicitation message seem to get lost easily so
+                * try to send it again.
+                */
+               if (network->router_solicit_refresh_count > 1) {
+                       network->router_solicit_refresh_count--;
+                       DBG("re-send router solicitation %d",
+                                       network->router_solicit_refresh_count);
+                       __connman_inet_ipv6_send_rs(network->index,
+                                       RS_REFRESH_TIMEOUT,
+                                       receive_refresh_rs_reply,
+                                       network);
+                       return;
+               }
+       }
+
+       /* RS refresh not in progress anymore */
+       network->router_solicit_refresh_count = 0;
+
+       connman_network_unref(network);
+       return;
+}
+
+int __connman_refresh_rs_ipv6(struct connman_network *network, int index)
+{
+       int ret = 0;
+
+       DBG("network %p index %d", network, index);
+
+       /* Send only one RS for all RDNSS entries which are about to expire */
+       if (network->router_solicit_refresh_count > 0) {
+               DBG("RS refresh already started");
+               return 0;
+       }
+
+       network->router_solicit_refresh_count = RS_REFRESH_COUNT;
+
+       connman_network_ref(network);
+
+       ret = __connman_inet_ipv6_send_rs(index, RS_REFRESH_TIMEOUT,
+                       receive_refresh_rs_reply, network);
+       return ret;
+}
+
 static void autoconf_ipv6_set(struct connman_network *network)
 {
        struct connman_service *service;
@@ -1389,17 +1455,36 @@ connman_bool_t connman_network_get_associating(struct connman_network *network)
        return network->associating;
 }
 
+void connman_network_clear_hidden(void *user_data)
+{
+       if (user_data == NULL)
+               return;
+
+       DBG("user_data %p", user_data);
+
+       /*
+        * Hidden service does not have a connect timeout so
+        * we do not need to remove it. We can just return
+        * error to the caller telling that we could not find
+        * any network that we could connect to.
+        */
+       __connman_service_reply_dbus_pending(user_data, EIO);
+}
+
 int connman_network_connect_hidden(struct connman_network *network,
-                               char *identity, char* passphrase)
+                       char *identity, char* passphrase, void *user_data)
 {
        int err = 0;
        struct connman_service *service;
 
-       DBG("");
-
        service = __connman_service_lookup_from_network(network);
-       if (service == NULL)
-               return -EINVAL;
+
+       DBG("network %p service %p user_data %p", network, service, user_data);
+
+       if (service == NULL) {
+               err = -EINVAL;
+               goto out;
+       }
 
        if (identity != NULL)
                __connman_service_set_agent_identity(service, identity);
@@ -1410,12 +1495,17 @@ int connman_network_connect_hidden(struct connman_network *network,
        if (err == -ENOKEY) {
                __connman_service_indicate_error(service,
                                        CONNMAN_SERVICE_ERROR_INVALID_KEY);
-               return err;
+               goto out;
        } else {
                __connman_service_set_hidden(service);
                __connman_service_set_userconnect(service, TRUE);
+               __connman_service_set_hidden_data(service, user_data);
                return __connman_service_connect(service);
        }
+
+out:
+       __connman_service_return_error(service, -err, user_data);
+       return err;
 }
 
 /**
index 9bc548d..91a8832 100644 (file)
--- a/src/ntp.c
+++ b/src/ntp.c
@@ -196,6 +196,8 @@ static void decode_msg(void *base, size_t len, struct timeval *tv)
 
        poll_id = g_timeout_add_seconds(transmit_delay, next_poll, NULL);
 
+       connman_info("ntp: time slew %+.6f s", offset);
+
        if (offset < STEPTIME_MIN_OFFSET && offset > -STEPTIME_MIN_OFFSET) {
                struct timeval adj;
 
index 9656838..a9d1341 100644 (file)
 
 #define RESOLVER_FLAG_PUBLIC (1 << 0)
 
+/*
+ * Threshold for RDNSS lifetime. Will be used to trigger RS
+ * before RDNSS entries actually expire
+ */
+#define RESOLVER_LIFETIME_REFRESH_THRESHOLD 0.8
+
 struct entry_data {
        char *interface;
        char *domain;
        char *server;
        unsigned int flags;
+       unsigned int lifetime;
        guint timeout;
 };
 
@@ -253,11 +260,47 @@ static gboolean resolver_expire_cb(gpointer user_data)
        return FALSE;
 }
 
+static gboolean resolver_refresh_cb(gpointer user_data)
+{
+       struct entry_data *entry = user_data;
+       int index;
+       unsigned int interval;
+       struct connman_service *service = NULL;
+
+       /* Round up what we have left from lifetime */
+       interval = entry->lifetime *
+               (1 - RESOLVER_LIFETIME_REFRESH_THRESHOLD) + 1.0;
+
+       DBG("RDNSS start interface %s domain %s "
+                       "server %s remaining lifetime %d",
+                       entry->interface, entry->domain,
+                       entry->server, interval);
+
+       entry->timeout = g_timeout_add_seconds(interval,
+                       resolver_expire_cb, entry);
+
+       index = connman_inet_ifindex(entry->interface);
+       if (index >= 0) {
+               service = __connman_service_lookup_from_index(index);
+               if (service != NULL) {
+                       /*
+                        * Send Router Solicitation to refresh RDNSS entries
+                        * before their lifetime expires
+                        */
+                       __connman_refresh_rs_ipv6(
+                                       __connman_service_get_network(service),
+                                       index);
+               }
+       }
+       return FALSE;
+}
+
 static int append_resolver(const char *interface, const char *domain,
                                const char *server, unsigned int lifetime,
                                                        unsigned int flags)
 {
        struct entry_data *entry;
+       unsigned int interval;
 
        DBG("interface %s domain %s server %s lifetime %d flags %d",
                                interface, domain, server, lifetime, flags);
@@ -273,17 +316,24 @@ static int append_resolver(const char *interface, const char *domain,
        entry->domain = g_strdup(domain);
        entry->server = g_strdup(server);
        entry->flags = flags;
+       entry->lifetime = lifetime;
        if (lifetime) {
                int index;
-               entry->timeout = g_timeout_add_seconds(lifetime,
-                                               resolver_expire_cb, entry);
+               interval = lifetime * RESOLVER_LIFETIME_REFRESH_THRESHOLD;
+
+               DBG("RDNSS start interface %s domain %s "
+                               "server %s lifetime threshold %d",
+                               interface, domain, server, interval);
+
+               entry->timeout = g_timeout_add_seconds(interval,
+                               resolver_refresh_cb, entry);
 
                /*
                 * We update the service only for those nameservers
                 * that are automagically added via netlink (lifetime > 0)
                 */
                index = connman_inet_ifindex(interface);
-               if (index >= 0) {
+               if (server != NULL && index >= 0) {
                        struct connman_service *service;
                        service = __connman_service_lookup_from_index(index);
                        if (service != NULL)
@@ -312,7 +362,7 @@ static int append_resolver(const char *interface, const char *domain,
 int connman_resolver_append(const char *interface, const char *domain,
                                                const char *server)
 {
-       GSList *list, *matches = NULL;
+       GSList *list;
 
        DBG("interface %s domain %s server %s", interface, domain, server);
 
@@ -322,18 +372,15 @@ int connman_resolver_append(const char *interface, const char *domain,
        for (list = entry_list; list; list = list->next) {
                struct entry_data *entry = list->data;
 
-               if (entry->timeout > 0 ||
-                               g_strcmp0(entry->interface, interface) != 0 ||
-                               g_strcmp0(entry->domain, domain) != 0 ||
-                               g_strcmp0(entry->server, server) != 0)
+               if (entry->timeout > 0)
                        continue;
 
-               matches = g_slist_append(matches, entry);
+               if (g_strcmp0(entry->interface, interface) == 0 &&
+                               g_strcmp0(entry->domain, domain) == 0 &&
+                               g_strcmp0(entry->server, server) == 0)
+                       return -EEXIST;
        }
 
-       if (matches != NULL)
-               remove_entries(matches);
-
        return append_resolver(interface, domain, server, 0, 0);
 }
 
@@ -350,20 +397,21 @@ int connman_resolver_append_lifetime(const char *interface, const char *domain,
                                const char *server, unsigned int lifetime)
 {
        GSList *list;
+       unsigned int interval;
 
        DBG("interface %s domain %s server %s lifetime %d",
                                interface, domain, server, lifetime);
 
-       if (server == NULL)
+       if (server == NULL && domain == NULL)
                return -EINVAL;
 
        for (list = entry_list; list; list = list->next) {
                struct entry_data *entry = list->data;
 
-               if (!entry->timeout ||
-                               g_strcmp0(entry->interface, interface) ||
-                               g_strcmp0(entry->domain, domain) ||
-                               g_strcmp0(entry->server, server))
+               if (entry->timeout == 0 ||
+                               g_strcmp0(entry->interface, interface) != 0 ||
+                               g_strcmp0(entry->domain, domain) != 0 ||
+                               g_strcmp0(entry->server, server) != 0)
                        continue;
 
                g_source_remove(entry->timeout);
@@ -373,8 +421,14 @@ int connman_resolver_append_lifetime(const char *interface, const char *domain,
                        return 0;
                }
 
-               entry->timeout = g_timeout_add_seconds(lifetime,
-                                               resolver_expire_cb, entry);
+               interval = lifetime * RESOLVER_LIFETIME_REFRESH_THRESHOLD;
+
+               DBG("RDNSS start interface %s domain %s "
+                               "server %s lifetime threshold %d",
+                               interface, domain, server, interval);
+
+               entry->timeout = g_timeout_add_seconds(interval,
+                               resolver_refresh_cb, entry);
                return 0;
        }
 
@@ -396,23 +450,20 @@ int connman_resolver_remove(const char *interface, const char *domain,
 
        DBG("interface %s domain %s server %s", interface, domain, server);
 
-       if (server == NULL)
-               return -EINVAL;
-
        for (list = entry_list; list; list = list->next) {
                struct entry_data *entry = list->data;
 
-               if (interface != NULL &&
-                               g_strcmp0(entry->interface, interface) != 0)
+               if (g_strcmp0(entry->interface, interface) != 0)
                        continue;
 
-               if (domain != NULL && g_strcmp0(entry->domain, domain) != 0)
+               if (g_strcmp0(entry->domain, domain) != 0)
                        continue;
 
                if (g_strcmp0(entry->server, server) != 0)
                        continue;
 
                matches = g_slist_append(matches, entry);
+               break;
        }
 
        if (matches == NULL)
@@ -493,6 +544,13 @@ int __connman_resolver_redo_servers(const char *interface)
                 */
                __connman_dnsproxy_remove(entry->interface, entry->domain,
                                        entry->server);
+               /*
+                * Remove also the resolver timer for the old server entry.
+                * A new timer will be set for the new server entry
+                * when the next Router Advertisement message arrives
+                * with RDNSS/DNSSL settings.
+                */
+               g_source_remove(entry->timeout);
 
                __connman_dnsproxy_append(entry->interface, entry->domain,
                                        entry->server);
index e53f5e8..4e7ef4d 100644 (file)
@@ -90,16 +90,7 @@ static connman_bool_t ether_blacklisted(const char *name)
        if (name == NULL)
                return TRUE;
 
-       /* virtual interface from VMware */
-       if (g_str_has_prefix(name, "vmnet") == TRUE)
-               return TRUE;
-
-       /* virtual interface from VirtualBox */
-       if (g_str_has_prefix(name, "vboxnet") == TRUE)
-               return TRUE;
-
-       /* virtual interface from Virtual Machine Manager */
-       if (g_str_has_prefix(name, "virbr") == TRUE)
+       if (__connman_device_isfiltered(name) == TRUE)
                return TRUE;
 
        return FALSE;
@@ -1189,22 +1180,22 @@ static const char **rtnl_nd_opt_dnssl(struct nd_opt_hdr *opt, guint32 *lifetime)
 static void rtnl_newnduseropt(struct nlmsghdr *hdr)
 {
        struct nduseroptmsg *msg = (struct nduseroptmsg *) NLMSG_DATA(hdr);
-       struct nd_opt_hdr *opt = (void *)&msg[1];
+       struct nd_opt_hdr *opt;
        guint32 lifetime = -1;
        const char **domains = NULL;
        struct in6_addr *servers = NULL;
-       int nr_servers = 0;
+       int i, nr_servers = 0;
        int msglen = msg->nduseropt_opts_len;
        char *interface;
 
-       DBG("family %02x index %x len %04x type %02x code %02x",
-           msg->nduseropt_family, msg->nduseropt_ifindex,
-           msg->nduseropt_opts_len, msg->nduseropt_icmp_type,
-           msg->nduseropt_icmp_code);
+       DBG("family %d index %d len %d type %d code %d",
+               msg->nduseropt_family, msg->nduseropt_ifindex,
+               msg->nduseropt_opts_len, msg->nduseropt_icmp_type,
+               msg->nduseropt_icmp_code);
 
        if (msg->nduseropt_family != AF_INET6 ||
-           msg->nduseropt_icmp_type != ND_ROUTER_ADVERT ||
-           msg->nduseropt_icmp_code != 0)
+                       msg->nduseropt_icmp_type != ND_ROUTER_ADVERT ||
+                       msg->nduseropt_icmp_code != 0)
                return;
 
        interface = connman_inet_ifname(msg->nduseropt_ifindex);
@@ -1212,40 +1203,37 @@ static void rtnl_newnduseropt(struct nlmsghdr *hdr)
                return;
 
        for (opt = (void *)&msg[1];
-            msglen >= 2 && msglen >= opt->nd_opt_len && opt->nd_opt_len;
-            msglen -= opt->nd_opt_len,
-                    opt = ((void *)opt) + opt->nd_opt_len*8) {
-
-               DBG("nd opt type %d len %d\n",
-                   opt->nd_opt_type, opt->nd_opt_len);
+                       msglen > 0;
+                       msglen -= opt->nd_opt_len * 8,
+                       opt = ((void *)opt) + opt->nd_opt_len*8) {
 
-               if (opt->nd_opt_type == 25)
-                       servers = rtnl_nd_opt_rdnss(opt, &lifetime,
-                                                   &nr_servers);
-               else if (opt->nd_opt_type == 31)
-                       domains = rtnl_nd_opt_dnssl(opt, &lifetime);
-       }
+               DBG("remaining %d nd opt type %d len %d\n",
+                       msglen, opt->nd_opt_type, opt->nd_opt_len);
 
-       if (nr_servers) {
-               int i, j;
-               char buf[40];
+               if (opt->nd_opt_type == 25) { /* ND_OPT_RDNSS */
+                       char buf[40];
 
-               for (i = 0; i < nr_servers; i++) {
-                       if (!inet_ntop(AF_INET6, servers + i, buf, sizeof(buf)))
-                               continue;
+                       servers = rtnl_nd_opt_rdnss(opt, &lifetime,
+                                                               &nr_servers);
+                       for (i = 0; i < nr_servers; i++) {
+                               if (!inet_ntop(AF_INET6, servers + i, buf,
+                                                               sizeof(buf)))
+                                       continue;
 
-                       if (domains == NULL || domains[0] == NULL) {
                                connman_resolver_append_lifetime(interface,
                                                        NULL, buf, lifetime);
-                               continue;
                        }
 
-                       for (j = 0; domains[j]; j++)
+               } else if (opt->nd_opt_type == 31) { /* ND_OPT_DNSSL */
+                       g_free(domains);
+
+                       domains = rtnl_nd_opt_dnssl(opt, &lifetime);
+                       for (i = 0; domains != NULL && domains[i] != NULL; i++)
                                connman_resolver_append_lifetime(interface,
-                                                               domains[j],
-                                                               buf, lifetime);
+                                               domains[i], NULL, lifetime);
                }
        }
+
        g_free(domains);
        g_free(interface);
 }
@@ -1267,6 +1255,8 @@ static const char *type2string(uint16_t type)
                return "NEWLINK";
        case RTM_DELLINK:
                return "DELLINK";
+       case RTM_GETADDR:
+               return "GETADDR";
        case RTM_NEWADDR:
                return "NEWADDR";
        case RTM_DELADDR:
index 9e52dd3..72f5af4 100644 (file)
@@ -44,6 +44,7 @@ static GHashTable *service_hash = NULL;
 static GSList *counter_list = NULL;
 static unsigned int autoconnect_timeout = 0;
 static struct connman_service *current_default = NULL;
+static connman_bool_t services_dirty = FALSE;
 
 struct connman_stats {
        connman_bool_t valid;
@@ -118,6 +119,8 @@ struct connman_service {
        connman_bool_t do_split_routing;
        connman_bool_t new_service;
        connman_bool_t hidden_service;
+       char *config_file;
+       char *config_entry;
 };
 
 struct find_data {
@@ -676,6 +679,15 @@ static int service_save(struct connman_service *service)
                g_key_file_set_boolean(keyfile, service->identifier, "Hidden",
                                                                        TRUE);
 
+       if (service->config_file != NULL && strlen(service->config_file) > 0)
+               g_key_file_set_string(keyfile, service->identifier,
+                               "Config.file", service->config_file);
+
+       if (service->config_entry != NULL &&
+                                       strlen(service->config_entry) > 0)
+               g_key_file_set_string(keyfile, service->identifier,
+                               "Config.ident", service->config_entry);
+
 done:
        __connman_storage_save_service(keyfile, service->identifier);
 
@@ -684,6 +696,11 @@ done:
        return err;
 }
 
+void __connman_service_save(struct connman_service *service)
+{
+       service_save(service);
+}
+
 static enum connman_service_state combine_state(
                                        enum connman_service_state state_a,
                                        enum connman_service_state state_b)
@@ -840,6 +857,74 @@ static connman_bool_t is_connected(struct connman_service *service)
        return is_connected_state(service, service->state);
 }
 
+static const char *nameserver_get_ifname(struct connman_service *service)
+{
+       const char *ifname;
+
+       if (service->ipconfig_ipv4)
+               ifname = __connman_ipconfig_get_ifname(service->ipconfig_ipv4);
+       else if (service->ipconfig_ipv6)
+               ifname = __connman_ipconfig_get_ifname(service->ipconfig_ipv6);
+       else
+               ifname = NULL;
+
+       if (ifname == NULL)
+               return NULL;
+
+       switch (combine_state(service->state_ipv4, service->state_ipv6)) {
+       case CONNMAN_SERVICE_STATE_UNKNOWN:
+       case CONNMAN_SERVICE_STATE_IDLE:
+       case CONNMAN_SERVICE_STATE_ASSOCIATION:
+       case CONNMAN_SERVICE_STATE_CONFIGURATION:
+       case CONNMAN_SERVICE_STATE_FAILURE:
+       case CONNMAN_SERVICE_STATE_DISCONNECT:
+               return NULL;
+       case CONNMAN_SERVICE_STATE_READY:
+       case CONNMAN_SERVICE_STATE_ONLINE:
+               break;
+       }
+
+       return ifname;
+}
+
+static void remove_nameservers(struct connman_service *service,
+               const char* interface, char **ns)
+{
+       const char *ifname = interface;
+       int i;
+
+       if (ns == NULL)
+               return;
+
+       if (interface == NULL)
+               ifname = nameserver_get_ifname(service);
+
+       if (ifname == NULL)
+                       return;
+
+       for (i = 0; ns[i] != NULL; i++)
+               connman_resolver_remove(ifname, NULL, ns[i]);
+}
+
+static void remove_searchdomains(struct connman_service *service,
+               const char *interface, char **sd)
+{
+       const char *ifname = interface;
+       int i;
+
+       if (sd == NULL)
+               return;
+
+       if (interface == NULL)
+               ifname = nameserver_get_ifname(service);
+
+       if (ifname == NULL)
+               return;
+
+       for (i = 0; sd[i] != NULL; i++)
+               connman_resolver_remove(ifname, sd[i], NULL);
+}
+
 static void update_nameservers(struct connman_service *service)
 {
        const char *ifname;
@@ -872,25 +957,38 @@ static void update_nameservers(struct connman_service *service)
        if (service->nameservers_config != NULL) {
                int i;
 
-               for (i = 0; service->nameservers_config[i] != NULL; i++) {
+               remove_nameservers(service, ifname, service->nameservers);
+
+               i = g_strv_length(service->nameservers_config);
+               while (i != 0) {
+                       i--;
                        connman_resolver_append(ifname, NULL,
-                                               service->nameservers_config[i]);
+                                       service->nameservers_config[i]);
                }
        } else if (service->nameservers != NULL) {
                int i;
 
-               for (i = 0; service->nameservers[i] != NULL; i++) {
+               i = g_strv_length(service->nameservers);
+               while (i != 0) {
+                       i--;
                        connman_resolver_append(ifname, NULL,
-                                               service->nameservers[i]);
+                                       service->nameservers[i]);
                }
        }
 
        if (service->domains != NULL) {
+               char *searchdomains[2] = {NULL, NULL};
                int i;
 
-               for (i = 0; service->domains[i]; i++)
+               searchdomains[0] = service->domainname;
+               remove_searchdomains(service, ifname, searchdomains);
+
+               i = g_strv_length(service->domains);
+               while (i != 0) {
+                       i--;
                        connman_resolver_append(ifname, service->domains[i],
                                                NULL);
+               }
        } else if (service->domainname != NULL)
                connman_resolver_append(ifname, service->domainname, NULL);
 
@@ -1050,48 +1148,26 @@ static void add_nameserver_route(int family, int index, char *nameserver,
 static void nameserver_add_routes(int index, char **nameservers,
                                        const char *gw)
 {
-       int i, ret, family;
-       struct addrinfo hints;
-       struct addrinfo *addr;
+       int i, family;
 
        for (i = 0; nameservers[i] != NULL; i++) {
-               memset(&hints, 0, sizeof(struct addrinfo));
-               hints.ai_flags = AI_NUMERICHOST;
-               addr = NULL;
-
-               ret = getaddrinfo(nameservers[i], NULL, &hints, &addr);
-               if (ret == EAI_NONAME)
-                       family = AF_INET; /* use the IPv4 as a default */
-               else if (ret != 0)
+               family = connman_inet_check_ipaddress(nameservers[i]);
+               if (family < 0)
                        continue;
-               else
-                       family = addr->ai_family;
 
                add_nameserver_route(family, index, nameservers[i], gw);
-
-               freeaddrinfo(addr);
        }
 }
 
 static void nameserver_del_routes(int index, char **nameservers,
                                enum connman_ipconfig_type type)
 {
-       int i, ret, family;
-       struct addrinfo hints;
-       struct addrinfo *addr;
+       int i, family;
 
        for (i = 0; nameservers[i] != NULL; i++) {
-               memset(&hints, 0, sizeof(struct addrinfo));
-               hints.ai_flags = AI_NUMERICHOST;
-               addr = NULL;
-
-               ret = getaddrinfo(nameservers[i], NULL, &hints, &addr);
-               if (ret == EAI_NONAME)
-                       family = AF_INET; /* use the IPv4 as a default */
-               else if (ret != 0)
+               family = connman_inet_check_ipaddress(nameservers[i]);
+               if (family < 0)
                        continue;
-               else
-                       family = addr->ai_family;
 
                switch (family) {
                case AF_INET:
@@ -1105,8 +1181,6 @@ static void nameserver_del_routes(int index, char **nameservers,
                                                        nameservers[i]);
                        break;
                }
-
-               freeaddrinfo(addr);
        }
 }
 
@@ -1438,14 +1512,14 @@ static void append_ipv6config(DBusMessageIter *iter, void *user_data)
                                                        iter);
 }
 
-static void append_nameserver(DBusMessageIter *iter, char ***nameservers)
+static void append_nameservers(DBusMessageIter *iter, char **servers)
 {
-       char **servers;
        int i;
 
-       servers = *nameservers;
+       DBG("%p", servers);
 
        for (i = 0; servers[i] != NULL; i++) {
+               DBG("servers[%d] %s", i, servers[i]);
                dbus_message_iter_append_basic(iter,
                                        DBUS_TYPE_STRING, &servers[i]);
        }
@@ -1459,30 +1533,25 @@ static void append_dns(DBusMessageIter *iter, void *user_data)
                return;
 
        if (service->nameservers_config != NULL) {
-               append_nameserver(iter, &service->nameservers_config);
+               append_nameservers(iter, service->nameservers_config);
                return;
        } else {
                if (service->nameservers != NULL)
-                       append_nameserver(iter, &service->nameservers);
+                       append_nameservers(iter, service->nameservers);
 
                if (service->nameservers_auto != NULL)
-                       append_nameserver(iter, &service->nameservers_auto);
+                       append_nameservers(iter, service->nameservers_auto);
        }
 }
 
 static void append_dnsconfig(DBusMessageIter *iter, void *user_data)
 {
        struct connman_service *service = user_data;
-       int i;
 
        if (service->nameservers_config == NULL)
                return;
 
-       for (i = 0; service->nameservers_config[i]; i++) {
-               dbus_message_iter_append_basic(iter,
-                               DBUS_TYPE_STRING,
-                               &service->nameservers_config[i]);
-       }
+       append_nameservers(iter, service->nameservers_config);
 }
 
 static void append_ts(DBusMessageIter *iter, void *user_data)
@@ -1515,32 +1584,32 @@ static void append_tsconfig(DBusMessageIter *iter, void *user_data)
        }
 }
 
-static void append_domain(DBusMessageIter *iter, void *user_data)
+static void append_domainconfig(DBusMessageIter *iter, void *user_data)
 {
        struct connman_service *service = user_data;
+       int i;
 
-       if (is_connected(service) == FALSE &&
-                               is_connecting(service) == FALSE)
-               return;
-
-       if (service->domainname == NULL)
+       if (service->domains == NULL)
                return;
 
-       dbus_message_iter_append_basic(iter,
-                               DBUS_TYPE_STRING, &service->domainname);
+       for (i = 0; service->domains[i]; i++)
+               dbus_message_iter_append_basic(iter,
+                               DBUS_TYPE_STRING, &service->domains[i]);
 }
 
-static void append_domainconfig(DBusMessageIter *iter, void *user_data)
+static void append_domain(DBusMessageIter *iter, void *user_data)
 {
        struct connman_service *service = user_data;
-       int i;
 
-       if (service->domains == NULL)
+       if (is_connected(service) == FALSE &&
+                               is_connecting(service) == FALSE)
                return;
 
-       for (i = 0; service->domains[i]; i++)
+       if (service->domains != NULL)
+               append_domainconfig(iter, user_data);
+       else if (service->domainname != NULL)
                dbus_message_iter_append_basic(iter,
-                               DBUS_TYPE_STRING, &service->domains[i]);
+                               DBUS_TYPE_STRING, &service->domainname);
 }
 
 static void append_proxies(DBusMessageIter *iter, void *user_data)
@@ -2549,14 +2618,23 @@ void __connman_service_set_agent_identity(struct connman_service *service,
                                        service->agent_identity);
 }
 
-static int check_passphrase(enum connman_service_security security,
+static int check_passphrase(struct connman_service *service,
+                               enum connman_service_security security,
                                const char *passphrase)
 {
        guint i;
        gsize length;
 
-       if (passphrase == NULL)
-               return 0;
+       if (passphrase == NULL) {
+               /*
+                * This will prevent __connman_service_set_passphrase() to
+                * wipe the passphrase out in case of -ENOKEY error for a
+                * favorite service. */
+               if (service->favorite == TRUE)
+                       return 1;
+               else
+                       return 0;
+       }
 
        length = strlen(passphrase);
 
@@ -2605,7 +2683,7 @@ int __connman_service_set_passphrase(struct connman_service *service,
        if (service->immutable == TRUE || service->hidden == TRUE)
                return -EINVAL;
 
-       err = check_passphrase(service->security, passphrase);
+       err = check_passphrase(service, service->security, passphrase);
 
        if (err == 0) {
                g_free(service->passphrase);
@@ -2621,6 +2699,14 @@ int __connman_service_set_passphrase(struct connman_service *service,
        return err;
 }
 
+const char *__connman_service_get_passphrase(struct connman_service *service)
+{
+       if (service == NULL)
+               return NULL;
+
+       return service->passphrase;
+}
+
 void __connman_service_set_agent_passphrase(struct connman_service *service,
                                                const char *agent_passphrase)
 {
@@ -2948,12 +3034,15 @@ static DBusMessage *set_property(DBusConnection *conn,
                        const char *val;
                        dbus_message_iter_get_basic(&entry, &val);
                        dbus_message_iter_next(&entry);
-                       if (str->len > 0)
-                               g_string_append_printf(str, " %s", val);
-                       else
-                               g_string_append(str, val);
+                       if (connman_inet_check_ipaddress(val) > 0) {
+                               if (str->len > 0)
+                                       g_string_append_printf(str, " %s", val);
+                               else
+                                       g_string_append(str, val);
+                       }
                }
 
+               remove_nameservers(service, NULL, service->nameservers_config);
                g_strfreev(service->nameservers_config);
 
                if (str->len > 0) {
@@ -3037,6 +3126,7 @@ static DBusMessage *set_property(DBusConnection *conn,
                                g_string_append(str, val);
                }
 
+               remove_searchdomains(service, NULL, service->domains);
                g_strfreev(service->domains);
 
                if (str->len > 0)
@@ -3298,39 +3388,78 @@ static void remove_timeout(struct connman_service *service)
        }
 }
 
-static void reply_pending(struct connman_service *service, int error)
+void __connman_service_reply_dbus_pending(DBusMessage *pending, int error)
 {
-       remove_timeout(service);
-
-       if (service->pending != NULL) {
+       if (pending != NULL) {
                if (error > 0) {
                        DBusMessage *reply;
 
-                       reply = __connman_error_failed(service->pending,
-                                                               error);
+                       reply = __connman_error_failed(pending, error);
                        if (reply != NULL)
                                g_dbus_send_message(connection, reply);
                } else {
-                       const char *sender;
+                       const char *sender, *path;
 
-                       sender = dbus_message_get_interface(service->pending);
+                       sender = dbus_message_get_interface(pending);
+                       path = dbus_message_get_path(pending);
 
-                       DBG("sender %s", sender);
+                       DBG("sender %s path %s", sender, path);
 
                        if (g_strcmp0(sender, CONNMAN_MANAGER_INTERFACE) == 0)
-                               g_dbus_send_reply(connection, service->pending,
-                                       DBUS_TYPE_OBJECT_PATH, &service->path,
+                               g_dbus_send_reply(connection, pending,
+                                       DBUS_TYPE_OBJECT_PATH, &path,
                                                        DBUS_TYPE_INVALID);
                        else
-                               g_dbus_send_reply(connection, service->pending,
+                               g_dbus_send_reply(connection, pending,
                                                        DBUS_TYPE_INVALID);
                }
 
-               dbus_message_unref(service->pending);
+               dbus_message_unref(pending);
+       }
+}
+
+static void reply_pending(struct connman_service *service, int error)
+{
+       remove_timeout(service);
+
+       if (service->pending != NULL) {
+               __connman_service_reply_dbus_pending(service->pending, error);
                service->pending = NULL;
        }
 }
 
+static void check_pending_msg(struct connman_service *service)
+{
+       if (service->pending == NULL)
+               return;
+
+       DBG("service %p pending msg %p already exists", service,
+                                               service->pending);
+       dbus_message_unref(service->pending);
+}
+
+void __connman_service_set_hidden_data(struct connman_service *service,
+                                                       gpointer user_data)
+{
+       DBusMessage *pending = user_data;
+
+       DBG("service %p pending %p", service, pending);
+
+       check_pending_msg(service);
+
+       service->pending = pending;
+}
+
+void __connman_service_return_error(struct connman_service *service,
+                               int error, gpointer user_data)
+{
+       DBG("service %p error %d user_data %p", service, error, user_data);
+
+       __connman_service_set_hidden_data(service, user_data);
+
+       reply_pending(service, error);
+}
+
 static gboolean connect_timeout(gpointer user_data)
 {
        struct connman_service *service = user_data;
@@ -3476,22 +3605,17 @@ static DBusMessage *disconnect_service(DBusConnection *conn,
        return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
 
-static DBusMessage *remove_service(DBusConnection *conn,
-                                       DBusMessage *msg, void *user_data)
+gboolean __connman_service_remove(struct connman_service *service)
 {
-       struct connman_service *service = user_data;
-
-       DBG("service %p", service);
-
        if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET)
-               return __connman_error_not_supported(msg);
+               return FALSE;
 
        if (service->immutable == TRUE || service->hidden == TRUE)
-               return __connman_error_not_supported(msg);
+               return FALSE;
 
        if (service->favorite == FALSE && service->state !=
                                                CONNMAN_SERVICE_STATE_FAILURE)
-               return __connman_error_not_supported(msg);
+               return FALSE;
 
        set_reconnect_state(service, FALSE);
 
@@ -3500,11 +3624,37 @@ static DBusMessage *remove_service(DBusConnection *conn,
        g_free(service->passphrase);
        service->passphrase = NULL;
 
+       g_free(service->agent_passphrase);
+       service->agent_passphrase = NULL;
+
+       g_free(service->identity);
+       service->identity = NULL;
+
+       g_free(service->agent_identity);
+       service->agent_identity = NULL;
+
+       g_free(service->eap);
+       service->eap = NULL;
+
        set_idle(service);
 
        __connman_service_set_favorite(service, FALSE);
+
        service_save(service);
 
+       return TRUE;
+}
+
+static DBusMessage *remove_service(DBusConnection *conn,
+                                       DBusMessage *msg, void *user_data)
+{
+       struct connman_service *service = user_data;
+
+       DBG("service %p", service);
+
+       if (__connman_service_remove(service) == FALSE)
+               return __connman_error_not_supported(msg);
+
        return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
 
@@ -3811,22 +3961,34 @@ static void service_schedule_removed(struct connman_service *service)
        service_schedule_changed();
 }
 
-static GDBusMethodTable service_methods[] = {
-       { "GetProperties", "",   "a{sv}", get_properties     },
-       { "SetProperty",   "sv", "",      set_property       },
-       { "ClearProperty", "s",  "",      clear_property     },
-       { "Connect",       "",   "",      connect_service,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
-       { "Disconnect",    "",   "",      disconnect_service },
-       { "Remove",        "",   "",      remove_service     },
-       { "MoveBefore",    "o",  "",      move_before        },
-       { "MoveAfter",     "o",  "",      move_after         },
-       { "ResetCounters", "",   "",      reset_counters     },
+static const GDBusMethodTable service_methods[] = {
+       { GDBUS_DEPRECATED_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       get_properties) },
+       { GDBUS_METHOD("SetProperty",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
+                       NULL, set_property) },
+       { GDBUS_METHOD("ClearProperty",
+                       GDBUS_ARGS({ "name", "s" }), NULL,
+                       clear_property) },
+       { GDBUS_ASYNC_METHOD("Connect", NULL, NULL,
+                             connect_service) },
+       { GDBUS_METHOD("Disconnect", NULL, NULL,
+                       disconnect_service) },
+       { GDBUS_METHOD("Remove", NULL, NULL, remove_service) },
+       { GDBUS_METHOD("MoveBefore",
+                       GDBUS_ARGS({ "service", "o" }), NULL,
+                       move_before) },
+       { GDBUS_METHOD("MoveAfter",
+                       GDBUS_ARGS({ "service", "o" }), NULL,
+                       move_after) },
+       { GDBUS_METHOD("ResetCounters", NULL, NULL, reset_counters) },
        { },
 };
 
-static GDBusSignalTable service_signals[] = {
-       { "PropertyChanged", "sv" },
+static const GDBusSignalTable service_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
        { },
 };
 
@@ -3904,6 +4066,8 @@ static void service_free(gpointer user_data)
        g_free(service->private_key_file);
        g_free(service->private_key_passphrase);
        g_free(service->phase2);
+       g_free(service->config_file);
+       g_free(service->config_entry);
 
        if (service->stats.timer != NULL)
                g_timer_destroy(service->stats.timer);
@@ -4251,15 +4415,22 @@ connman_bool_t __connman_service_wps_enabled(struct connman_service *service)
        return service->wps;
 }
 
+void __connman_service_mark_dirty()
+ {
+       services_dirty = TRUE;
+ }
+
 /**
- * __connman_service_set_favorite:
+ * __connman_service_set_favorite_delayed:
  * @service: service structure
  * @favorite: favorite value
+ * @delay_ordering: do not order service sequence
  *
  * Change the favorite setting of service
  */
-int __connman_service_set_favorite(struct connman_service *service,
-                                               connman_bool_t favorite)
+int __connman_service_set_favorite_delayed(struct connman_service *service,
+                                       connman_bool_t favorite,
+                                       gboolean delay_ordering)
 {
        GSequenceIter *iter;
 
@@ -4273,20 +4444,39 @@ int __connman_service_set_favorite(struct connman_service *service,
                return -EALREADY;
 
        service->favorite = favorite;
-       service->order = __connman_service_get_order(service);
+
+       if (delay_ordering == FALSE)
+               service->order = __connman_service_get_order(service);
 
        favorite_changed(service);
 
-       if (g_sequence_get_length(service_list) > 1) {
-               g_sequence_sort_changed(iter, service_compare, NULL);
-               service_schedule_changed();
-       }
+       if (delay_ordering == FALSE) {
 
-       __connman_connection_update_gateway();
+               if (g_sequence_get_length(service_list) > 1) {
+                       g_sequence_sort_changed(iter, service_compare, NULL);
+                       service_schedule_changed();
+               }
+
+               __connman_connection_update_gateway();
+       }
 
        return 0;
 }
 
+/**
+ * __connman_service_set_favorite:
+ * @service: service structure
+ * @favorite: favorite value
+ *
+ * Change the favorite setting of service
+ */
+int __connman_service_set_favorite(struct connman_service *service,
+                                               connman_bool_t favorite)
+{
+       return __connman_service_set_favorite_delayed(service, favorite,
+                                                       FALSE);
+}
+
 int __connman_service_set_immutable(struct connman_service *service,
                                                connman_bool_t immutable)
 {
@@ -4441,15 +4631,27 @@ static void request_input_cb (struct connman_service *service,
                if (g_strcmp0(error,
                                "net.connman.Agent.Error.Canceled") == 0) {
                        err = -EINVAL;
+
+                       if (service->hidden == TRUE)
+                               __connman_service_return_error(service,
+                                                       ECANCELED, user_data);
                        goto done;
+               } else {
+                       if (service->hidden == TRUE)
+                               __connman_service_return_error(service,
+                                                       ETIMEDOUT, user_data);
                }
        }
 
        if (service->hidden == TRUE && name_len > 0 && name_len <= 32) {
                device = connman_network_get_device(service->network);
-               __connman_device_request_hidden_scan(device,
+               err = __connman_device_request_hidden_scan(device,
                                                name, name_len,
-                                               identity, passphrase);
+                                               identity, passphrase,
+                                               user_data);
+               if (err < 0)
+                       __connman_service_return_error(service, -err,
+                                                       user_data);
        }
 
        if (values_received == FALSE || service->hidden == TRUE) {
@@ -4473,6 +4675,9 @@ static void request_input_cb (struct connman_service *service,
 
  done:
        if (err >= 0) {
+               /* We forget any previous error. */
+               service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
+
                __connman_service_connect(service);
 
                /* Never cache agent provided credentials */
@@ -4489,6 +4694,17 @@ static void request_input_cb (struct connman_service *service,
                 * when failing is due to wrong user input */
                service->state = CONNMAN_SERVICE_STATE_IDLE;
 
+               if (service->hidden == FALSE) {
+                       /*
+                        * If there was a real error when requesting
+                        * hidden scan, then that error is returned already
+                        * to the user somewhere above so do not try to
+                        * do this again.
+                        */
+                       __connman_service_return_error(service, -err,
+                                                       user_data);
+               }
+
                service_complete(service);
                __connman_connection_update_gateway();
        }
@@ -4706,7 +4922,7 @@ static int service_indicate_state(struct connman_service *service)
                if (service->userconnect == TRUE &&
                        __connman_agent_report_error(service,
                                        error2string(service->error),
-                                       report_error_cb, NULL) == -EIO)
+                                       report_error_cb, NULL) == -EINPROGRESS)
                        return 0;
                service_complete(service);
        } else
@@ -4762,7 +4978,7 @@ int __connman_service_clear_error(struct connman_service *service)
 
        service->state_ipv4 = service->state_ipv6 =
                                                CONNMAN_SERVICE_STATE_UNKNOWN;
-       service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;;
+       service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
 
        if (service->favorite == TRUE)
                set_reconnect_state(service, TRUE);
@@ -5130,7 +5346,9 @@ static int service_connect(struct connman_service *service)
                                                        service->network,
                                                        "WiFi.UseWPS") == FALSE)
                                        return -ENOKEY;
-                       }
+                       } else if (service->error ==
+                                       CONNMAN_SERVICE_ERROR_INVALID_KEY)
+                               return -ENOKEY;
                        break;
                case CONNMAN_SERVICE_SECURITY_8021X:
                        if (service->eap == NULL)
@@ -5240,13 +5458,6 @@ int __connman_service_connect(struct connman_service *service)
                return -EINPROGRESS;
        }
 
-       __connman_service_ipconfig_indicate_state(service,
-                                       CONNMAN_SERVICE_STATE_FAILURE,
-                                       CONNMAN_IPCONFIG_TYPE_IPV4);
-       __connman_service_ipconfig_indicate_state(service,
-                                       CONNMAN_SERVICE_STATE_FAILURE,
-                                       CONNMAN_IPCONFIG_TYPE_IPV6);
-
        if (service->network != NULL)
                __connman_network_disconnect(service->network);
        else if (service->type == CONNMAN_SERVICE_TYPE_VPN &&
@@ -5255,10 +5466,25 @@ int __connman_service_connect(struct connman_service *service)
 
        if (service->userconnect == TRUE) {
                if (err == -ENOKEY || err == -EPERM) {
-                       if (__connman_agent_request_passphrase_input(service,
-                                                       request_input_cb,
-                                                       NULL) == -EIO)
-                               return -EINPROGRESS;
+                       DBusMessage *pending = NULL;
+
+                       /*
+                        * We steal the reply here. The idea is that the
+                        * connecting client will see the connection status
+                        * after the real hidden network is connected or
+                        * connection failed.
+                        */
+                       if (service->hidden == TRUE) {
+                               pending = service->pending;
+                               service->pending = NULL;
+                       }
+
+                       err = __connman_agent_request_passphrase_input(service,
+                                       request_input_cb, pending);
+                       if (service->hidden == TRUE && err != -EINPROGRESS)
+                               service->pending = pending;
+
+                       return err;
                }
                reply_pending(service, -err);
        }
@@ -5353,17 +5579,62 @@ static struct connman_service *lookup_by_identifier(const char *identifier)
        return NULL;
 }
 
+struct provision_user_data {
+       const char *ident;
+       int ret;
+};
+
 static void provision_changed(gpointer value, gpointer user_data)
 {
        struct connman_service *service = value;
-       char *path = user_data;
+       struct provision_user_data *data = user_data;
+       const char *path = data->ident;
+       int ret;
+
+       ret = __connman_config_provision_service_ident(service, path,
+                       service->config_file, service->config_entry);
+       if (ret > 0)
+               data->ret = ret;
+}
+
+int __connman_service_provision_changed(const char *ident)
+{
+       struct provision_user_data data = {
+               .ident = ident,
+               .ret = 0
+       };
+
+       g_sequence_foreach(service_list, provision_changed, (void *)&data);
+
+       /*
+        * Because the provision_changed() might have set some services
+        * as favorite, we must sort the sequence now.
+        */
+       if (services_dirty == TRUE) {
+               services_dirty = FALSE;
+
+               if (g_sequence_get_length(service_list) > 1) {
+                       g_sequence_sort(service_list, service_compare, NULL);
+                       service_schedule_changed();
+               }
 
-       __connman_config_provision_service_ident(service, path);
+               __connman_connection_update_gateway();
+       }
+
+       return data.ret;
 }
 
-void __connman_service_provision_changed(const char *ident)
+void __connman_service_set_config(struct connman_service *service,
+                               const char *file_id, const char *entry)
 {
-       g_sequence_foreach(service_list, provision_changed, (void *)ident);
+       if (service == NULL)
+               return;
+
+       g_free(service->config_file);
+       service->config_file = g_strdup(file_id);
+
+       g_free(service->config_entry);
+       service->config_entry = g_strdup(entry);
 }
 
 /**
@@ -5681,6 +5952,11 @@ struct connman_service *__connman_service_lookup_from_index(int index)
        return NULL;
 }
 
+struct connman_service *__connman_service_lookup_from_ident(const char *identifier)
+{
+       return lookup_by_identifier(identifier);
+}
+
 const char *__connman_service_get_ident(struct connman_service *service)
 {
        return service->identifier;
@@ -5924,7 +6200,7 @@ struct connman_service * __connman_service_create_from_network(struct connman_ne
 
        if (service->favorite == TRUE) {
                device = connman_network_get_device(service->network);
-               if (device && __connman_device_scanning(device) == FALSE)
+               if (device && connman_device_get_scanning(device) == FALSE)
                        __connman_service_auto_connect();
        }
 
@@ -6081,6 +6357,66 @@ __connman_service_create_from_provider(struct connman_provider *provider)
        return service;
 }
 
+static void remove_unprovisioned_services()
+{
+       gchar **services;
+       GKeyFile *keyfile, *configkeyfile;
+       char *file, *section;
+       int i = 0;
+
+       services = connman_storage_get_services();
+       if (services == NULL)
+               return;
+
+       for (;services[i] != NULL; i++) {
+               file = section = NULL;
+               keyfile = configkeyfile = NULL;
+
+               keyfile = connman_storage_load_service(services[i]);
+               if (keyfile == NULL)
+                       continue;
+
+               file = g_key_file_get_string(keyfile, services[i],
+                                       "Config.file", NULL);
+               if (file == NULL)
+                       goto next;
+
+               section = g_key_file_get_string(keyfile, services[i],
+                                       "Config.ident", NULL);
+               if (section == NULL)
+                       goto next;
+
+               configkeyfile = __connman_storage_load_config(file);
+               if (configkeyfile == NULL) {
+                       /*
+                        * Config file is missing, remove the provisioned
+                        * service.
+                        */
+                       __connman_storage_remove_service(services[i]);
+                       goto next;
+               }
+
+               if (g_key_file_has_group(configkeyfile, section) == FALSE)
+                       /*
+                        * Config section is missing, remove the provisioned
+                        * service.
+                        */
+                       __connman_storage_remove_service(services[i]);
+
+       next:
+               if (keyfile != NULL)
+                       g_key_file_free(keyfile);
+
+               if (configkeyfile != NULL)
+                       g_key_file_free(configkeyfile);
+
+               g_free(section);
+               g_free(file);
+       }
+
+       g_strfreev(services);
+}
+
 int __connman_service_init(void)
 {
        DBG("");
@@ -6097,6 +6433,8 @@ int __connman_service_init(void)
                        g_str_equal, g_free, NULL);
        services_notify->add = g_hash_table_new(g_str_hash, g_str_equal);
 
+       remove_unprovisioned_services();
+
        return 0;
 }
 
index dd26087..a5db7ad 100644 (file)
@@ -1555,11 +1555,14 @@ static DBusMessage *destroy_session(DBusConnection *conn,
        return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
 
-static GDBusMethodTable session_methods[] = {
-       { "Destroy",    "",   "", destroy_session    },
-       { "Connect",    "",   "", connect_session    },
-       { "Disconnect", "",   "", disconnect_session },
-       { "Change",     "sv", "", change_session     },
+static const GDBusMethodTable session_methods[] = {
+       { GDBUS_METHOD("Destroy", NULL, NULL, destroy_session) },
+       { GDBUS_METHOD("Connect", NULL, NULL, connect_session) },
+       { GDBUS_METHOD("Disconnect", NULL, NULL,
+                       disconnect_session ) },
+       { GDBUS_METHOD("Change",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
+                       NULL, change_session) },
        { },
 };
 
index 2faab75..47bd0cb 100644 (file)
@@ -58,20 +58,24 @@ static GKeyFile *storage_load(const char *pathname)
        return keyfile;
 }
 
-static void storage_save(GKeyFile *keyfile, char *pathname)
+static int storage_save(GKeyFile *keyfile, char *pathname)
 {
        gchar *data = NULL;
        gsize length = 0;
        GError *error = NULL;
+       int ret = 0;
 
        data = g_key_file_to_data(keyfile, &length, NULL);
 
        if (!g_file_set_contents(pathname, data, length, &error)) {
                DBG("Failed to store information: %s", error->message);
                g_error_free(error);
+               ret = -EIO;
        }
 
        g_free(data);
+
+       return ret;
 }
 
 static void storage_delete(const char *pathname)
@@ -98,17 +102,20 @@ GKeyFile *__connman_storage_load_global()
        return keyfile;
 }
 
-void __connman_storage_save_global(GKeyFile *keyfile)
+int __connman_storage_save_global(GKeyFile *keyfile)
 {
        gchar *pathname;
+       int ret;
 
        pathname = g_strdup_printf("%s/%s", STORAGEDIR, SETTINGS);
        if(pathname == NULL)
-               return;
+               return -ENOMEM;
 
-       storage_save(keyfile, pathname);
+       ret = storage_save(keyfile, pathname);
 
        g_free(pathname);
+
+       return ret;
 }
 
 void __connman_storage_delete_global()
@@ -140,30 +147,6 @@ GKeyFile *__connman_storage_load_config(const char *ident)
        return keyfile;
 }
 
-void __connman_storage_save_config(GKeyFile *keyfile, const char *ident)
-{
-       gchar *pathname;
-
-       pathname = g_strdup_printf("%s/%s.config", STORAGEDIR, ident);
-       if(pathname == NULL)
-               return;
-
-       storage_save(keyfile, pathname);
-}
-
-void __connman_storage_delete_config(const char *ident)
-{
-       gchar *pathname;
-
-       pathname = g_strdup_printf("%s/%s.config", STORAGEDIR, ident);
-       if(pathname == NULL)
-               return;
-
-       storage_delete(pathname);
-
-       g_free(pathname);
-}
-
 GKeyFile *__connman_storage_open_service(const char *service_id)
 {
        gchar *pathname;
@@ -249,34 +232,25 @@ GKeyFile *connman_storage_load_service(const char *service_id)
 
        keyfile =  storage_load(pathname);
        g_free(pathname);
-       if (keyfile)
-               return keyfile;
-
-       pathname = g_strdup_printf("%s/%s", STORAGEDIR, DEFAULT);
-       if(pathname == NULL)
-               return NULL;
-
-       keyfile =  storage_load(pathname);
-
-       g_free(pathname);
 
        return keyfile;
 }
 
-void __connman_storage_save_service(GKeyFile *keyfile, const char *service_id)
+int __connman_storage_save_service(GKeyFile *keyfile, const char *service_id)
 {
+       int ret = 0;
        gchar *pathname, *dirname;
 
        dirname = g_strdup_printf("%s/%s", STORAGEDIR, service_id);
        if(dirname == NULL)
-               return;
+               return -ENOMEM;
 
        /* If the dir doesn't exist, create it */
        if (!g_file_test(dirname, G_FILE_TEST_IS_DIR)) {
                if(mkdir(dirname, MODE) < 0) {
                        if (errno != EEXIST) {
                                g_free(dirname);
-                               return;
+                               return -errno;
                        }
                }
        }
@@ -285,9 +259,74 @@ void __connman_storage_save_service(GKeyFile *keyfile, const char *service_id)
 
        g_free(dirname);
 
-       storage_save(keyfile, pathname);
+       ret = storage_save(keyfile, pathname);
+
+       g_free(pathname);
+
+       return ret;
+}
+
+static gboolean remove_file(const char *service_id, const char *file)
+{
+       gchar *pathname;
+       gboolean ret = FALSE;
+
+       pathname = g_strdup_printf("%s/%s/%s", STORAGEDIR, service_id, file);
+       if(pathname == NULL)
+               return FALSE;
+
+       if (g_file_test(pathname, G_FILE_TEST_EXISTS) == FALSE) {
+               ret = TRUE;
+       } else if (g_file_test(pathname, G_FILE_TEST_IS_REGULAR) == TRUE) {
+               unlink(pathname);
+               ret = TRUE;
+       }
 
        g_free(pathname);
+       return ret;
+}
+
+static gboolean remove_dir(const char *service_id)
+{
+       gchar *pathname;
+       gboolean ret = FALSE;
+
+       pathname = g_strdup_printf("%s/%s", STORAGEDIR, service_id);
+       if(pathname == NULL)
+               return FALSE;
+
+       if (g_file_test(pathname, G_FILE_TEST_EXISTS) == FALSE) {
+               ret = TRUE;
+       } else if (g_file_test(pathname, G_FILE_TEST_IS_DIR) == TRUE) {
+               rmdir(pathname);
+               ret = TRUE;
+       }
+
+       g_free(pathname);
+       return ret;
+}
+
+gboolean __connman_storage_remove_service(const char *service_id)
+{
+       gboolean removed;
+
+       /* Remove service configuration file */
+       removed = remove_file(service_id, SETTINGS);
+       if (removed == FALSE)
+               return FALSE;
+
+       /* Remove the statistics file also */
+       removed = remove_file(service_id, "data");
+       if (removed == FALSE)
+               return FALSE;
+
+       removed = remove_dir(service_id);
+       if (removed == FALSE)
+               return FALSE;
+
+       DBG("Removed service dir %s/%s", STORAGEDIR, service_id);
+
+       return TRUE;
 }
 
 GKeyFile *__connman_storage_load_provider(const char *identifier)
@@ -387,24 +426,82 @@ void __connman_storage_migrate()
        GKeyFile *keyfile_def = NULL;
        GKeyFile *keyfile = NULL;
        GError *error = NULL;
+       connman_bool_t delete_old_config = TRUE;
+       char **services, **keys, *value;
+       int i, k, err;
        connman_bool_t val;
 
+       pathname = g_strdup_printf("%s/%s", STORAGEDIR, DEFAULT);
+       if (pathname == NULL)
+               return;
+
        /* If setting file exists, migration has been done. */
        keyfile = __connman_storage_load_global();
        if (keyfile) {
                g_key_file_free(keyfile);
+               unlink(pathname);
+               g_free(pathname);
                return;
        }
 
-       pathname = g_strdup_printf("%s/%s", STORAGEDIR, DEFAULT);
-       if(pathname == NULL)
-               return;
-
        /* If default.profile exists, create new settings file */
        keyfile_def = storage_load(pathname);
        if (keyfile_def == NULL)
                goto done;
 
+       services = g_key_file_get_groups(keyfile_def, NULL);
+       for (i = 0; services != NULL && services[i] != NULL; i++) {
+               if (strncmp(services[i], "wifi_", 5) != 0 &&
+                               strncmp(services[i], "ethernet_", 9) != 0 &&
+                               strncmp(services[i], "cellular_", 9) != 0 &&
+                               strncmp(services[i], "bluetooth_", 10) != 0 &&
+                               strncmp(services[i], "wimax_", 6) != 0 &&
+                               strncmp(services[i], "vpn_", 4) != 0)
+                       continue;
+
+               keyfile = connman_storage_load_service(services[i]);
+               if (keyfile != NULL) {
+                       g_key_file_free(keyfile);
+                       DBG("already exists %s", services[i]);
+                       continue;
+               }
+
+               keyfile = g_key_file_new();
+               if (keyfile == NULL) {
+                       connman_warn("Migrating %s failed", services[i]);
+                       delete_old_config = FALSE;
+                       continue;
+               }
+
+               keys = g_key_file_get_keys(keyfile_def, services[i],
+                               NULL, NULL);
+
+               for (k = 0; keys != NULL && keys[k] != NULL; k++) {
+                       value = g_key_file_get_value(keyfile_def, services[i],
+                                       keys[k], NULL);
+                       g_key_file_set_value(keyfile, services[i],
+                                       keys[k], value);
+                       g_free(value);
+               }
+
+               if (keys != NULL && keys[0] != NULL) {
+                       err = __connman_storage_save_service(keyfile,
+                                       services[i]);
+                       if (err >= 0)
+                               DBG("migrated %s", services[i]);
+                       else {
+                               connman_warn("Migrating %s failed %s",
+                                               services[i], strerror(-err));
+                               delete_old_config = FALSE;
+                       }
+               } else
+                       DBG("no keys in %s", services[i]);
+
+               g_strfreev(keys);
+               g_key_file_free(keyfile);
+       }
+       g_strfreev(services);
+
        /* Copy global settings from default.profile to settings. */
        keyfile = g_key_file_new();
 
@@ -418,11 +515,19 @@ void __connman_storage_migrate()
        g_key_file_set_boolean(keyfile, "global",
                                        "OfflineMode", val);
 
+       /* Migrate Powered/Enable state key/value pairs from legacy
+        * settings
+        */
+
        val = g_key_file_get_boolean(keyfile_def, "WiFi",
                                        "Enable", &error);
        if (error != NULL) {
                g_clear_error(&error);
-               val = FALSE;
+               val = g_key_file_get_boolean(keyfile_def, "device_Wireless", "Powered", &error);
+               if (error != NULL) {
+                       g_clear_error(&error);
+                       val = FALSE;
+               }
        }
 
        g_key_file_set_boolean(keyfile, "WiFi",
@@ -432,7 +537,11 @@ void __connman_storage_migrate()
                                        "Enable", &error);
        if (error != NULL) {
                g_clear_error(&error);
-               val = FALSE;
+               val = g_key_file_get_boolean(keyfile_def, "device_Bluetooth", "Powered", &error);
+               if (error != NULL) {
+                       g_clear_error(&error);
+                       val = FALSE;
+               }
        }
 
        g_key_file_set_boolean(keyfile, "Bluetooth",
@@ -442,7 +551,11 @@ void __connman_storage_migrate()
                                        "Enable", &error);
        if (error != NULL) {
                g_clear_error(&error);
-               val = FALSE;
+               val = g_key_file_get_boolean(keyfile_def, "device_Ethernet", "Powered", &error);
+               if (error != NULL) {
+                       g_clear_error(&error);
+                       val = FALSE;
+               }
        }
 
        g_key_file_set_boolean(keyfile, "Wired",
@@ -452,7 +565,11 @@ void __connman_storage_migrate()
                                        "Enable", &error);
        if (error != NULL) {
                g_clear_error(&error);
-               val = FALSE;
+               val = g_key_file_get_boolean(keyfile_def, "device_Cellular", "Powered", &error);
+               if (error != NULL) {
+                       g_clear_error(&error);
+                       val = FALSE;
+               }
        }
 
        g_key_file_set_boolean(keyfile, "Cellular",
@@ -462,18 +579,29 @@ void __connman_storage_migrate()
                                        "Enable", &error);
        if (error != NULL) {
                g_clear_error(&error);
-               val = FALSE;
+               val = g_key_file_get_boolean(keyfile_def, "device_WiMAX", "Powered", &error);
+               if (error != NULL) {
+                       g_clear_error(&error);
+                       val = FALSE;
+               }
        }
 
        g_key_file_set_boolean(keyfile, "WiMAX",
                                        "Enable", val);
 
-       __connman_storage_save_global(keyfile);
+       if (__connman_storage_save_global(keyfile) < 0) {
+               connman_warn("Migrating global config failed");
+               delete_old_config = FALSE;
+       }
 
        g_key_file_free(keyfile);
 
        g_key_file_free(keyfile_def);
 
+       if (delete_old_config == TRUE) {
+               DBG("migration done for %s", pathname);
+               unlink(pathname);
+       }
 done:
        g_free(pathname);
 }
index fd4f767..3781b0c 100644 (file)
@@ -609,7 +609,10 @@ done:
                        technology->pending_timeout = g_timeout_add_seconds(10,
                                        technology_pending_reply, technology);
                } else {
-                       reply = __connman_error_failed(msg, -err);
+                       if (err == -EALREADY)
+                               reply = __connman_error_already_enabled(msg);
+                       else
+                               reply = __connman_error_failed(msg, -err);
                        if (reply != NULL)
                                g_dbus_send_message(connection, reply);
                }
@@ -670,7 +673,10 @@ done:
                        technology->pending_timeout = g_timeout_add_seconds(10,
                                        technology_pending_reply, technology);
                } else {
-                       reply = __connman_error_failed(msg, -err);
+                       if (err == -EALREADY)
+                               reply = __connman_error_already_disabled(msg);
+                       else
+                               reply = __connman_error_failed(msg, -err);
                        if (reply != NULL)
                                g_dbus_send_message(connection, reply);
                }
@@ -831,7 +837,7 @@ void __connman_technology_scan_stopped(struct connman_device *device)
                if (__connman_device_get_service_type(other_device) != type)
                        continue;
 
-               if (__connman_device_scanning(other_device))
+               if (connman_device_get_scanning(other_device) == TRUE)
                        count += 1;
        }
 
@@ -858,16 +864,20 @@ static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
        return NULL;
 }
 
-static GDBusMethodTable technology_methods[] = {
-       { "GetProperties", "",   "a{sv}", get_properties },
-       { "SetProperty",   "sv", "",      set_property   },
-       { "Scan",          "",    "",     scan,
-                                               G_DBUS_METHOD_FLAG_ASYNC },
+static const GDBusMethodTable technology_methods[] = {
+       { GDBUS_DEPRECATED_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       get_properties) },
+       { GDBUS_METHOD("SetProperty",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
+                       NULL, set_property) },
+       { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
        { },
 };
 
-static GDBusSignalTable technology_signals[] = {
-       { "PropertyChanged", "sv" },
+static const GDBusSignalTable technology_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
        { },
 };
 
@@ -1097,9 +1107,6 @@ int __connman_technology_remove_device(struct connman_device *device)
                return -ENXIO;
        }
 
-       if (__connman_device_scanning(device))
-               __connman_technology_scan_stopped(device);
-
        technology->device_list = g_slist_remove(technology->device_list,
                                                                device);
        technology_put(technology);
@@ -1130,8 +1137,10 @@ int __connman_technology_enabled(enum connman_service_type type)
        if (technology == NULL)
                return -ENXIO;
 
-       if (__sync_fetch_and_add(&technology->enabled, 1) == 0)
-               powered_changed(technology);
+       if (__sync_fetch_and_add(&technology->enabled, 1) != 0)
+               return -EALREADY;
+
+       powered_changed(technology);
 
        if (technology->pending_reply != NULL) {
                g_dbus_send_reply(connection, technology->pending_reply, DBUS_TYPE_INVALID);
@@ -1152,6 +1161,9 @@ int __connman_technology_disabled(enum connman_service_type type)
        if (technology == NULL)
                return -ENXIO;
 
+       if (__sync_fetch_and_sub(&technology->enabled, 1) != 1)
+               return -EINPROGRESS;
+
        if (technology->pending_reply != NULL) {
                g_dbus_send_reply(connection, technology->pending_reply, DBUS_TYPE_INVALID);
                dbus_message_unref(technology->pending_reply);
@@ -1160,8 +1172,7 @@ int __connman_technology_disabled(enum connman_service_type type)
                technology->pending_timeout = 0;
        }
 
-       if (__sync_fetch_and_sub(&technology->enabled, 1) == 1)
-               powered_changed(technology);
+       powered_changed(technology);
 
        return 0;
 }
index c67f200..265408b 100644 (file)
@@ -421,7 +421,7 @@ int __connman_private_network_request(DBusMessage *msg, const char *owner)
        pn->fd = fd;
        pn->interface = iface;
        pn->index = index;
-       pn->pool = __connman_ippool_create(pn->fd, 1, 1, ippool_disconnect, pn);
+       pn->pool = __connman_ippool_create(pn->index, 1, 1, ippool_disconnect, pn);
        if (pn->pool == NULL) {
                errno = -ENOMEM;
                goto error;
index 2601d36..467da52 100644 (file)
@@ -65,7 +65,6 @@ static void save_timeservers(char **servers)
 static char **load_timeservers()
 {
        GKeyFile *keyfile;
-       GError *error = NULL;
        char **servers = NULL;
 
        keyfile = __connman_storage_load_global();
@@ -73,11 +72,7 @@ static char **load_timeservers()
                return NULL;
 
        servers = g_key_file_get_string_list(keyfile, "global",
-                                               "Timeservers", NULL, &error);
-       if (error) {
-               DBG("Error loading timeservers: %s", error->message);
-               g_error_free(error);
-       }
+                                               "Timeservers", NULL, NULL);
 
        g_key_file_free(keyfile);
 
@@ -115,9 +110,6 @@ static void resolv_result(GResolvResultStatus status, char **results, gpointer u
 void __connman_timeserver_sync_next()
 {
        char *server;
-       int ret;
-       struct addrinfo hints;
-       struct addrinfo *addr;
 
        __connman_ntp_stop();
 
@@ -129,15 +121,8 @@ void __connman_timeserver_sync_next()
 
        ts_list = g_slist_delete_link(ts_list, ts_list);
 
-       memset(&hints, 0, sizeof(struct addrinfo));
-       hints.ai_flags = AI_NUMERICHOST;
-       addr = NULL;
-
-       ret = getaddrinfo(server, NULL, &hints, &addr);
-       freeaddrinfo(addr);
-
        /* if its a IP , directly query it. */
-       if (ret == 0) {
+       if (connman_inet_check_ipaddress(server) > 0) {
                DBG("Using timeservers %s", server);
 
                __connman_ntp_start(server);
index 4fe9e75..9412f1e 100644 (file)
@@ -386,7 +386,7 @@ static void xml_wispr_parser_callback(const char *str, gpointer user_data)
        result = g_markup_parse_context_parse(parser_context,
                                        str, strlen(str), NULL);
        if (result == TRUE)
-               result = g_markup_parse_context_end_parse(parser_context, NULL);
+               g_markup_parse_context_end_parse(parser_context, NULL);
 
        g_markup_parse_context_free(parser_context);
 }
@@ -610,7 +610,7 @@ static gboolean wispr_manage_message(GWebResult *result,
 
                if (__connman_agent_request_login_input(wp_context->service,
                                        wispr_portal_request_wispr_login,
-                                       wp_context) != -EIO)
+                                       wp_context) != -EINPROGRESS)
                        wispr_portal_error(wp_context);
 
                break;
@@ -692,8 +692,9 @@ static gboolean wispr_portal_web_result(GWebResult *result, gpointer user_data)
 
                break;
        case 302:
-               if (g_web_result_get_header(result, "Location",
-                                               &redirect) == FALSE) {
+               if (g_web_supports_tls() == FALSE ||
+                               g_web_result_get_header(result, "Location",
+                                                       &redirect) == FALSE) {
                        __connman_agent_request_browser(wp_context->service,
                                        wispr_portal_browser_reply_cb,
                                        wp_context->status_url, wp_context);
index 9fba23e..881fa0b 100644 (file)
@@ -1516,7 +1516,7 @@ int main(int argc, char *argv[])
        insert = FALSE;
        delete_rule = FALSE;
        compare_rule = FALSE;
-       table_name = chain = new_chain = match_name = target_name = NULL;
+       chain = new_chain = match_name = target_name = NULL;
        delete_chain = flush_chain = policy = NULL;
        memset(&ip, 0, sizeof(struct ipt_ip));
        table = NULL;
index b1d28d2..1c96823 100644 (file)
@@ -894,8 +894,6 @@ static void extract_rsn(struct supplicant_bss *bss,
                }
        }
 
-       buf += 2 + (count * 4);
-       len -= 2 + (count * 4);
 }
 
 static void bss_rates(DBusMessageIter *iter, void *user_data)
@@ -1745,10 +1743,8 @@ static void interface_get_result(const char *error,
        const char *path = NULL;
        int err;
 
-       if (error != NULL) {
-               err = -EIO;
+       if (error != NULL)
                goto create;
-       }
 
        dbus_message_iter_get_basic(iter, &path);
        if (path == NULL) {
index 69ee871..122bea5 100644 (file)
@@ -290,7 +290,7 @@ static void parser_callback(const char *str, gpointer user_data)
 
        result = g_markup_parse_context_parse(context, str, strlen(str), NULL);
        if (result == TRUE)
-               result = g_markup_parse_context_end_parse(context, NULL);
+               g_markup_parse_context_end_parse(context, NULL);
 
        g_markup_parse_context_free(context);
 }
index ce07d14..14d48cf 100644 (file)
@@ -285,9 +285,11 @@ static DBusMessage *notify_update(DBusConnection *conn,
        return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
 
-static GDBusMethodTable notify_methods[] = {
-       { "Release", "",      "", notify_release },
-       { "Update",  "a{sv}", "", notify_update  },
+static const GDBusMethodTable notify_methods[] = {
+       { GDBUS_METHOD("Release", NULL, NULL, notify_release) },
+       { GDBUS_METHOD("Update",
+                       GDBUS_ARGS({ "settings", "a{sv}" }), NULL,
+                       notify_update) },
        { },
 };
 
index 6ff1c71..758528a 100644 (file)
@@ -137,7 +137,7 @@ void util_setup(struct test_fix *fix, gconstpointer data)
                                                connman_died,
                                                NULL, NULL);
        fix->manager_watch = g_dbus_add_signal_watch(fix->main_connection,
-                                               NULL, NULL,
+                                               CONNMAN_SERVICE, NULL,
                                                CONNMAN_MANAGER_INTERFACE,
                                                PROPERTY_CHANGED,
                                                handle_manager_changed,