Merge tag 'upstream/1.40' into tizen. 79/271279/4 submit/tizen/20220224.061208
authorNiraj Kumar Goit <niraj.g@samsung.com>
Thu, 17 Feb 2022 16:13:13 +0000 (21:43 +0530)
committerNiraj Kumar Goit <niraj.g@samsung.com>
Wed, 23 Feb 2022 15:30:32 +0000 (21:00 +0530)
Change-Id: I4ed89827d776db6eeec11878bc1cd0cd6c5e1e80
Signed-off-by: Niraj Kumar Goit <niraj.g@samsung.com>
Signed-off-by: Anjali Nijhara <a.nijhara@samsung.com>
68 files changed:
1  2 
AUTHORS
Makefile.am
Makefile.plugins
README
configure.ac
doc/clock-api.txt
doc/vpn-connection-api.txt
gdbus/watch.c
gdhcp/client.c
gsupplicant/supplicant.c
include/inet.h
include/ipaddress.h
include/network.h
include/provider.h
include/service.h
include/setting.h
packaging/connman.spec
plugins/bluetooth.c
plugins/dundee.c
plugins/ethernet.c
plugins/iwd.c
plugins/loopback.c
plugins/neard.c
plugins/ofono.c
plugins/vpn.c
plugins/wifi.c
src/bridge.c
src/clock.c
src/connection.c
src/connman.h
src/dbus.c
src/device.c
src/dhcp.c
src/dhcpv6.c
src/dnsproxy.c
src/inet.c
src/ipaddress.c
src/ipconfig.c
src/iptables.c
src/main.c
src/main.conf
src/manager.c
src/network.c
src/peer.c
src/provider.c
src/rtnl.c
src/service.c
src/session.c
src/shared/util.c
src/technology.c
src/tethering.c
src/timeserver.c
src/wispr.c
vpn/main.c
vpn/plugins/l2tp.c
vpn/plugins/openconnect.c
vpn/plugins/openvpn.c
vpn/plugins/pptp.c
vpn/plugins/vpn.c
vpn/plugins/vpn.h
vpn/plugins/vpnc.c
vpn/plugins/wireguard.c
vpn/vpn-config.c
vpn/vpn-dbus.conf
vpn/vpn-ipconfig.c
vpn/vpn-provider.c
vpn/vpn-provider.h
vpn/vpn.h

diff --cc AUTHORS
index e03a071,438d45f..438d45f
mode 100755,100644..100755
+++ b/AUTHORS
diff --cc Makefile.am
@@@ -205,37 -178,15 +205,37 @@@ vpn_connman_vpnd_SOURCES = $(gdhcp_sour
                        vpn/vpn-manager.c vpn/vpn-provider.c \
                        vpn/vpn-provider.h vpn/vpn-rtnl.h \
                        vpn/vpn-ipconfig.c src/inet.c vpn/vpn-rtnl.c \
 -                      src/dbus.c src/storage.c src/ipaddress.c src/agent.c \
 -                      vpn/vpn-agent.c vpn/vpn-agent.h src/inotify.c \
 -                      vpn/vpn-config.c vpn/vpn-settings.c vpn/vpn-util.c
 +                      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-connman.c \
 +                      src/agent.c src/notifier.c src/provider.c \
 +                      src/resolver.c src/ipconfig.c src/detect.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 src/ipaddress.c \
 +                      src/inotify.c src/firewall-iptables.c src/ipv6pd.c src/peer.c \
 +                      src/peer_service.c src/machine.c src/util.c \
-                       vpn/vpn-agent.c vpn/vpn-agent.h \
++                      vpn/vpn-agent.c vpn/vpn-util.c vpn/vpn-agent.h \
 +                      vpn/vpn-config.c vpn/vpn-settings.c src/acd.c
 +
 +if TIZEN_EXT_WIFI_MESH
 +vpn_connman_vpnd_SOURCES += src/mesh.c src/mesh-netlink.c
 +endif
  
  vpn_connman_vpnd_LDADD = gdbus/libgdbus-internal.la $(builtin_vpn_libadd) \
 -                              @GLIB_LIBS@ @DBUS_LIBS@ @GNUTLS_LIBS@ \
 +                              @DLOG_LIBS@ @GLIB_LIBS@ @DBUS_LIBS@ @GNUTLS_LIBS@ \
 +                              @LIBSYSTEMD_LIBS@ @XTABLES_LIBS@ \
                                -lresolv -ldl
  
 +if TIZEN_EXT_WIFI_MESH
 +vpn_connman_vpnd_LDADD += @LIBNL_LIBS@ @LIBNL_GENL_LIBS@
 +endif
 +
  vpn_connman_vpnd_LDFLAGS = -Wl,--export-dynamic \
                                -Wl,--version-script=$(srcdir)/vpn/vpn.ver
  endif
index 004bbe9,8e32361..a0c17cf
mode 100755,100644..100755
diff --cc README
index e911bc2,b8154e6..b8154e6
mode 100755,100644..100755
--- 1/README
--- 2/README
+++ b/README
diff --cc configure.ac
Simple merge
index 6818f5a,a7fdf55..a7fdf55
mode 100755,100644..100755
diff --cc gdbus/watch.c
index 1ca3c4b,8fa76cd..8fa76cd
mode 100755,100644..100755
diff --cc gdhcp/client.c
index bdaa882,c7b85e5..cc0379e
mode 100755,100644..100755
diff --cc include/inet.h
@@@ -82,12 -78,15 +82,20 @@@ int connman_inet_ipv6_get_dest_addr(in
  int connman_inet_check_ipaddress(const char *host);
  bool connman_inet_check_hostname(const char *ptr, size_t len);
  bool connman_inet_is_ipv6_supported();
+ bool connman_inet_is_default_route(int family, const char *host,
+                               const char *gateway, const char *netmask);
+ int connman_inet_get_route_addresses(int index, char **network, char **netmask,
+                                                       char **destination);
+ int connman_inet_ipv6_get_route_addresses(int index, char **network,
+                                                       char **netmask,
+                                                       char **destination);
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +char *connman_inet_ifaddr(const char *name);
 +char *connman_inet_ifname2addr(const char *name);
 +#endif
 +
  #ifdef __cplusplus
  }
  #endif
index 3655ca8,652db0f..652db0f
mode 100755,100644..100755
index 9f5bb1f,8f9dd94..4d09dff
mode 100755,100644..100755
@@@ -300,9 -163,8 +302,11 @@@ struct connman_network_driver 
        void (*remove) (struct connman_network *network);
        int (*connect) (struct connman_network *network);
        int (*disconnect) (struct connman_network *network);
+       int (*set_autoconnect) (struct connman_network *network,
+                               bool autoconnect);
 +#if defined TIZEN_EXT
 +      int (*merge) (struct connman_network *network);
 +#endif
  };
  
  int connman_network_driver_register(struct connman_network_driver *driver);
index b585665,1f12099..1f12099
mode 100755,100644..100755
index acd8852,8f6b36b..041949f
mode 100755,100644..100755
index 3625f3e,920e675..f141bf6
mode 100755,100644..100755
@@@ -29,10 -29,8 +29,11 @@@ extern "C" 
  #endif
  
  bool connman_setting_get_bool(const char *key);
- unsigned int connman_setting_get_uint(const char *key);
 +#if defined TIZEN_EXT
 +int connman_setting_get_int(const char *key);
 +#endif
+ unsigned int connman_setting_get_uint(const char *key);
+ char *connman_setting_get_string(const char *key);
  char **connman_setting_get_string_list(const char *key);
  unsigned int *connman_setting_get_uint_list(const char *key);
  
index ff92bd6,0000000..8fbb03d
mode 100644,000000..100644
--- /dev/null
@@@ -1,349 -1,0 +1,349 @@@
- Version:        1.38
- Release:        14
 +%bcond_with     connman_openconnect
 +%bcond_without  connman_wireguard
 +%bcond_without  connman_openvpn
 +%bcond_without  connman_ipsec
 +%bcond_without  connman_vpnd
 +
 +Name:           connman
++Version:        1.40
++Release:        1
 +License:        GPL-2.0+
 +Summary:        Connection Manager
 +Url:            http://connman.net
 +Group:          Network & Connectivity/Connection Management
 +Source0:        %{name}-%{version}.tar.gz
 +BuildRequires:  systemd-devel
 +BuildRequires:  pkgconfig(dlog)
 +BuildRequires:  pkgconfig(dbus-1)
 +BuildRequires:  pkgconfig(glib-2.0)
 +BuildRequires:  pkgconfig(gio-2.0)
 +BuildRequires:  pkgconfig(libiptc)
 +BuildRequires:  pkgconfig(xtables)
 +BuildRequires:  pkgconfig(libsmack)
 +BuildRequires:  pkgconfig(libnl-3.0)
 +BuildRequires:  pkgconfig(libnl-genl-3.0)
 +BuildRequires:  pkgconfig(libsystemd)
 +%if %{with connman_openconnect}
 +BuildRequires:  openconnect
 +%endif
 +%if %{with connman_openvpn}
 +BuildRequires:  openvpn
 +%endif
 +%if %{with connman_ipsec}
 +BuildRequires:  strongswan
 +%endif
 +BuildRequires:  readline-devel
 +#%systemd_requires
 +Requires:       iptables
 +Requires:         systemd
 +Requires(post):   systemd
 +Requires(preun):  systemd
 +Requires(postun): systemd
 +Requires:         security-config
 +Provides:       %{name}-profile_common = %{version}-%{release}
 +Provides:       %{name}-profile_mobile = %{version}-%{release}
 +Provides:       %{name}-profile_wearable = %{version}-%{release}
 +Provides:       %{name}-profile_robot = %{version}-%{release}
 +
 +%description
 +Connection Manager provides a daemon for managing Internet connections
 +within embedded devices running the Linux operating system.
 +
 +%if %{with connman_openconnect}
 +%package plugin-openconnect
 +Summary:        Openconnect Support for Connman
 +Requires:       %{name} = %{version}
 +Requires:       openconnect
 +
 +%description plugin-openconnect
 +Openconnect Support for Connman.
 +%endif
 +
 +%if %{with connman_openvpn}
 +%package plugin-openvpn
 +Summary:        Openvpn Support for Connman
 +Requires:       %{name} = %{version}
 +Requires:       openvpn
 +
 +%description plugin-openvpn
 +OpenVPN support for Connman.
 +%endif
 +
 +%if %{with connman_ipsec}
 +%package plugin-ipsec
 +Summary:        IPsec Support for Connman
 +Requires:       %{name} = %{version}
 +Requires:       strongswan
 +
 +%description plugin-ipsec
 +OpenVPN support for Connman.
 +%endif
 +
 +%if %{with connman_vpnd}
 +%package connman-vpnd
 +Summary:        VPN Support for Connman
 +#BuildRequires:  %{name} = %{version}
 +Requires:       %{name} = %{version}
 +
 +%description connman-vpnd
 +Provides VPN support for Connman
 +%endif
 +
 +%if %{with connman_wireguard}
 +%package plugin-wireguard
 +Summary:        Wireguard Support for Connman
 +BuildRequires:  pkgconfig(libmnl)
 +Requires:       %{name} = %{version}
 +
 +%description plugin-wireguard
 +Wireguard Support for Connman.
 +%endif
 +
 +%package test
 +Summary:        Test Scripts for Connection Manager
 +Group:          Development/Tools
 +Requires:       %{name} = %{version}
 +Requires:       dbus-python
 +Requires:       pygobject
 +Requires:       python-xml
 +
 +%description test
 +Scripts for testing Connman and its functionality
 +
 +%package devel
 +Summary:        Development files for connman
 +Group:          Development/Tools
 +Requires:       %{name} = %{version}
 +
 +%description devel
 +Header files and development files for connman.
 +
 +%package extension-tv
 +Summary:        Connman service script for TV profile
 +Requires:       %{name} = %{version}-%{release}
 +Provides:       %{name}-profile_tv = %{version}-%{release}
 +Conflicts:      %{name}-extension-ivi
 +Conflicts:      %{name}-extension-disable-eth
 +%description extension-tv
 +Supplies Tizen TV profile systemd service scripts instead of the default one.
 +This overwrites service script of %{name}.
 +
 +%package extension-ivi
 +Summary:        Connman configuration for IVI profile
 +Requires:       %{name} = %{version}-%{release}
 +Provides:       %{name}-profile_ivi = %{version}-%{release}
 +Conflicts:      %{name}-extension-tv
 +Conflicts:      %{name}-extension-disable-eth
 +%description extension-ivi
 +Supplies Tizen IVI profile configuration instead of the default one.
 +This overwrites conf file of %{name}.
 +
 +%package extension-disable-eth
 +Summary:        Connman configuration for testing which requires the ethernet to be disabled
 +Requires:       %{name} = %{version}-%{release}
 +Conflicts:      %{name}-extension-tv
 +Conflicts:      %{name}-extension-ivi
 +%description extension-disable-eth
 +Connman without ethernet support
 +This overwrites conf file of %{name}.
 +
 +%package profile_robot
 +Summary:              connman extension for robot profile
 +Requires:             %{name} = %{version}-%{release}
 +%description profile_robot
 +connman extension for Tizen robot profile
 +
 +%prep
 +%setup -q
 +
 +
 +%build
 +%if %{with connman_vpnd}
 +VPN_CFLAGS+=" -DTIZEN_EXT -lsmack -Werror"
 +%endif
 +
 +chmod +x bootstrap
 +./bootstrap
 +%configure \
 +          --sysconfdir=/etc \
 +          --enable-client \
 +          --enable-tizen-ext \
 +          --disable-tizen-ext-ins \
 +            --enable-tizen-ext-eap-on-ethernet \
 +          --enable-pacrunner \
 +            --enable-wifi=builtin \
 +%if %{with connman_openconnect}
 +            --enable-openconnect \
 +%endif
 +%if %{with connman_openvpn}
 +            --enable-openvpn \
 +%endif
 +%if %{with connman_ipsec}
 +            --enable-ipsec \
 +%endif
 +%if %{without connman_wireguard}
 +            --disable-wireguard \
 +%endif
 +%if 0%{?enable_connman_features}
 +            %connman_features \
 +%endif
 +            --disable-ofono \
 +            --enable-telephony=builtin \
 +            --enable-test \
 +          --enable-loopback \
 +          --enable-ethernet \
 +          --with-systemdunitdir=%{_unitdir} \
 +          --enable-pie \
 +          --disable-wispr \
 +          --disable-backtrace \
 +          --disable-tools
 +
 +make %{?_smp_mflags}
 +
 +%install
 +%make_install
 +
 +#Systemd service file
 +mkdir -p %{buildroot}%{_unitdir}
 +
 +cp src/connman_tv.service %{buildroot}%{_unitdir}/connman.service.tv
 +cp src/connman.service %{buildroot}%{_unitdir}/connman.service
 +cp vpn/connman-vpn.service %{buildroot}%{_unitdir}/connman-vpn.service
 +
 +mkdir -p %{buildroot}%{_unitdir}/multi-user.target.wants
 +ln -s ../connman.service %{buildroot}%{_unitdir}/multi-user.target.wants/connman.service
 +
 +#Systemd socket file for DNS proxy
 +cp src/connman.socket %{buildroot}%{_unitdir}/connman.socket
 +mkdir -p %{buildroot}%{_unitdir}/sockets.target.wants
 +ln -s ../connman.socket %{buildroot}%{_unitdir}/sockets.target.wants/connman.socket
 +
 +mkdir -p %{buildroot}/%{_localstatedir}/lib/connman
 +cp resources/var/lib/connman/settings %{buildroot}/%{_localstatedir}/lib/connman/settings
 +mkdir -p %{buildroot}%{_datadir}/dbus-1/system-services
 +cp resources/usr/share/dbus-1/system-services/net.connman.service %{buildroot}%{_datadir}/dbus-1/system-services/net.connman.service
 +mkdir -p %{buildroot}/etc/connman
 +
 +cp src/main_ivi.conf %{buildroot}/etc/connman/main.conf.ivi
 +cp src/main_tv.conf %{buildroot}/etc/connman/main.conf.tv
 +cp src/main_disable_eth.conf %{buildroot}/etc/connman/main.conf.disable.eth
 +cp src/main.conf %{buildroot}/etc/connman/main.conf
 +
 +rm %{buildroot}%{_sysconfdir}/dbus-1/system.d/*.conf
 +mkdir -p %{buildroot}%{_sysconfdir}/dbus-1/system.d/
 +cp src/connman.conf %{buildroot}%{_sysconfdir}/dbus-1/system.d/
 +cp src/connman-robot.conf %{buildroot}%{_sysconfdir}/dbus-1/system.d/
 +
 +%if %{with connman_vpnd}
 +cp vpn/vpn-dbus.conf %{buildroot}%{_sysconfdir}/dbus-1/system.d/connman-vpn-dbus.conf
 +%endif
 +
 +%post
 +#chsmack -a 'System' /%{_localstatedir}/lib/connman
 +#chsmack -a 'System' /%{_localstatedir}/lib/connman/settings
 +
 +%preun
 +
 +%postun
 +systemctl daemon-reload
 +
 +%docs_package
 +
 +%files
 +%manifest connman.manifest
 +%attr(500,network_fw,network_fw) %{_bindir}/connmand
 +%attr(500,network_fw,network_fw) %{_bindir}/connmanctl
 +%attr(600,network_fw,network_fw) /%{_localstatedir}/lib/connman/settings
 +%attr(644,root,root) %{_datadir}/dbus-1/system-services/net.connman.service
 +%attr(644,root,root) %{_sysconfdir}/dbus-1/system.d/*
 +%exclude %{_sysconfdir}/dbus-1/system.d/connman-robot.conf
 +%attr(644,network_fw,network_fw) %{_sysconfdir}/connman/main.conf
 +%attr(644,root,root) %{_sysconfdir}/dbus-1/system.d/*.conf
 +%attr(644,root,root) %{_unitdir}/connman.service
 +%attr(644,root,root) %{_unitdir}/multi-user.target.wants/connman.service
 +%attr(644,root,root) %{_unitdir}/connman.socket
 +%attr(644,root,root) %{_unitdir}/sockets.target.wants/connman.socket
 +%license COPYING
 +
 +%files test
 +%manifest connman.manifest
 +%{_libdir}/%{name}/test/*
 +
 +%files devel
 +%manifest connman.manifest
 +%{_includedir}/*
 +%{_libdir}/pkgconfig/*.pc
 +
 +%if %{with connman_openconnect}
 +%files plugin-openconnect
 +%manifest %{name}.manifest
 +%{_libdir}/connman/plugins-vpn/openconnect.so
 +%{_libdir}/connman/scripts/openconnect-script
 +%license COPYING
 +%endif
 +
 +%if %{with connman_openvpn}
 +%files plugin-openvpn
 +%manifest %{name}.manifest
 +%{_libdir}/%{name}/plugins-vpn/openvpn.so
 +%{_libdir}/%{name}/scripts/openvpn-script
 +%license COPYING
 +%endif
 +
 +%if %{with connman_ipsec}
 +%files plugin-ipsec
 +%manifest %{name}.manifest
 +%{_libdir}/%{name}/plugins-vpn/ipsec.so
 +%{_libdir}/%{name}/scripts/ipsec-script
 +%license COPYING
 +%endif
 +
 +%if %{with connman_vpnd}
 +%files connman-vpnd
 +%manifest %{name}.manifest
 +%{_bindir}/connman-vpnd
 +%dir %{_libdir}/%{name}
 +%dir %{_libdir}/%{name}/scripts
 +%dir %{_libdir}/%{name}/plugins-vpn
 +%attr(644,root,root) %config %{_sysconfdir}/dbus-1/system.d/connman-vpn-dbus.conf
 +%{_datadir}/dbus-1/system-services/net.connman.vpn.service
 +%license COPYING
 +%attr(644,root,root) %{_unitdir}/connman-vpn.service
 +%endif
 +
 +%if %{with connman_wireguard}
 +%files plugin-wireguard
 +%manifest %{name}.manifest
 +%{_libdir}/%{name}/plugins-vpn/wireguard.so
 +%license COPYING
 +%endif
 +
 +%post extension-tv
 +mv -f %{_unitdir}/connman.service.tv %{_unitdir}/connman.service
 +mv -f %{_sysconfdir}/connman/main.conf.tv %{_sysconfdir}/connman/main.conf
 +
 +%files extension-tv
 +%attr(644,network_fw,network_fw) %{_sysconfdir}/connman/main.conf.tv
 +%license COPYING
 +%attr(644,root,root) %{_unitdir}/connman.service.tv
 +
 +%post extension-ivi
 +mv -f %{_sysconfdir}/connman/main.conf.ivi %{_sysconfdir}/connman/main.conf
 +
 +%files extension-ivi
 +%attr(644,network_fw,network_fw) %{_sysconfdir}/connman/main.conf.ivi
 +%license COPYING
 +
 +%post extension-disable-eth
 +mv -f %{_sysconfdir}/connman/main.conf.disable.eth %{_sysconfdir}/connman/main.conf
 +
 +%files extension-disable-eth
 +%attr(644,network_fw,network_fw) %{_sysconfdir}/connman/main.conf.disable.eth
 +%license COPYING
 +
 +%post profile_robot
 +mv %{_sysconfdir}/dbus-1/system.d/connman-robot.conf %{_sysconfdir}/dbus-1/system.d/connman.conf
 +
 +%files profile_robot
 +%manifest %{name}.manifest
 +%attr(644,root,root) %{_sysconfdir}/dbus-1/system.d/connman-robot.conf
index 704d216,5336103..a8383e7
mode 100755,100644..100755
index b5420ac,57571ec..57571ec
mode 100755,100644..100755
  #include <connman/rtnl.h>
  #include <connman/log.h>
  #include <connman/setting.h>
- #include <connman/option.h>
 +#if defined TIZEN_EXT_WIFI_MESH
 +#include <connman/mesh.h>
 +#endif
 +
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +#include <gsupplicant/gsupplicant.h>
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
  
  static bool eth_tethering = false;
  
@@@ -150,240 -141,6 +151,239 @@@ static void eth_network_remove(struct c
        DBG("network %p", network);
  }
  
-       DBusMessageIter args;
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +#define NETCONFIG_SERVICE             "net.netconfig"
 +#define NETCONFIG_ETHERNET_INTERFACE  NETCONFIG_SERVICE ".ethernet"
 +#define NETCONFIG_ETHERNET_PATH               "/net/netconfig/ethernet"
 +
 +struct eapol_method_call_data {
 +      DBusConnection *connection;
 +      struct connman_network *network;
 +};
 +
 +static struct eapol_method_call_data enable_eapol_data;
 +
 +void handle_eap_signal(GSupplicantInterface *interface, bool status)
 +{
 +      DBG("captured EAP signal");
 +
 +      if (!enable_eapol_data.network)
 +              return;
 +
 +      if (g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
 +              return;
 +
 +      if (!connman_network_check_validity(enable_eapol_data.network))
 +              return;
 +
 +      DBG("network is valid");
 +
 +      g_supplicant_unregister_eap_callback();
 +
 +      if (!status) {
 +              // Should we mark service as non favorite or make autoconnect as false?
 +
 +              struct ethernet_data *ethernet = g_supplicant_interface_get_data(interface);
 +              if (ethernet && ethernet->interface) {
 +                      g_supplicant_interface_remove(ethernet->interface, NULL, NULL);
 +                      ethernet->interface = NULL;
 +              }
 +
 +              connman_network_set_error(enable_eapol_data.network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
 +              enable_eapol_data.network = NULL;
 +              return;
 +      }
 +
 +      connman_network_set_connected(enable_eapol_data.network, status);
 +      enable_eapol_data.network = NULL;
 +}
 +
 +static void interface_create_callback(int result,
 +              GSupplicantInterface *interface, void *user_data)
 +{
 +      struct ethernet_data *ethernet = user_data;
 +
 +      if (result < 0 || !interface || !ethernet)
 +              return;
 +
 +      DBG("result %d ifname %s, ethernet %p", result,
 +                      g_supplicant_interface_get_ifname(interface),
 +                      ethernet);
 +
 +      ethernet->interface = interface;
 +      g_supplicant_interface_set_data(interface, ethernet);
 +}
 +
 +static int eapol_interface_create(void)
 +{
 +      struct connman_network *network = enable_eapol_data.network;
 +      struct connman_service *service = connman_service_lookup_from_network(network);
 +
 +      if (!service) {
 +              DBG("service not found");
 +              return -1;
 +      }
 +
 +      struct connman_device *device = connman_network_get_device(network);
 +      struct ethernet_data *ethernet = connman_device_get_data(device);
 +      const char *driver = "wired";
 +      int index = connman_network_get_index(network);
 +      char *ifname = connman_inet_ifname(index);;
 +      char *config_file = NULL;
 +
 +      g_supplicant_register_eap_callback(handle_eap_signal);
 +
 +      if (asprintf(&config_file, "/var/lib/connman/%s-eapol.conf", ifname) < 0) {
 +              g_free(ifname);
 +              return -ENOMEM;
 +      }
 +
 +      DBG("config_file %s", config_file);
 +
 +      g_supplicant_replace_config_file(ifname, config_file);
 +      free(config_file);
 +
 +      /*
 +       *  TODO: RemoveInterface if already present because
 +       *  already created interface will not start EAP handshake.
 +       */
 +      return g_supplicant_interface_create(ifname, driver, NULL,
 +                      0, 0, 60, interface_create_callback, ethernet);
 +}
 +
 +static void enable_eapol_reply(DBusPendingCall *call, void *user_data)
 +{
 +      DBusMessage *reply;
 +      DBusError error;
 +
 +      DBG("");
 +
 +      reply = dbus_pending_call_steal_reply(call);
 +
 +      dbus_error_init(&error);
 +      if (dbus_set_error_from_message(&error, reply)) {
 +              DBG("enable_eapol_request() %s %s", error.name, error.message);
 +              dbus_error_free(&error);
 +              dbus_message_unref(reply);
 +              dbus_pending_call_unref(call);
 +              dbus_connection_unref(enable_eapol_data.connection);
 +
 +              enable_eapol_data.connection = NULL;
 +              return;
 +      }
 +
 +      if (eapol_interface_create() < 0)
 +              DBG("Failed to create eapol interface");
 +}
 +
 +static int eth_network_enable_eapol(struct connman_service *service, struct connman_network *network)
 +{
 +      DBusMessage *msg = NULL;
 +      DBusPendingCall *call;
 +
 +      DBusConnection *connection = connman_dbus_get_connection();
 +      if (!connection) {
 +              DBG("dbus connection does not exist");
 +              return -EINVAL;
 +      }
 +
 +      msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_ETHERNET_PATH,
 +                      NETCONFIG_ETHERNET_INTERFACE, "EnableEap");
 +      if (!msg) {
 +              dbus_connection_unref(connection);
 +              return -EINVAL;
 +      }
 +
 +      const char *path = __connman_service_get_path(service);
 +      dbus_bool_t enable = true;
 +
 +      dbus_message_append_args(msg, DBUS_TYPE_STRING, &path,
 +                      DBUS_TYPE_INVALID);
 +      dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &enable,
 +                      DBUS_TYPE_INVALID);
 +
 +      if (!dbus_connection_send_with_reply(connection, msg,
 +                              &call, DBUS_TIMEOUT_USE_DEFAULT)) {
 +              dbus_message_unref(msg);
 +              dbus_connection_unref(connection);
 +              return -EIO;
 +      }
 +
 +      if (!call) {
 +              dbus_message_unref(msg);
 +              dbus_connection_unref(connection);
 +              return -EIO;
 +      }
 +
 +      enable_eapol_data.connection = connection;
 +      enable_eapol_data.network = network;
 +
 +      dbus_pending_call_set_notify(call, enable_eapol_reply, NULL, NULL);
 +      dbus_message_unref(msg);
 +
 +      return 0;
 +}
 +
 +static int eth_network_connect(struct connman_network *network)
 +{
 +      DBG("network %p", network);
 +
 +      int err = 0;
 +      struct connman_service *service = connman_service_lookup_from_network(network);
 +
 +      if (service && __connman_service_get_use_eapol(service)) {
 +              /** Enable eapol on device reboot **/
 +              if (__connman_service_get_connect_reason(service) != CONNMAN_SERVICE_CONNECT_REASON_USER) {
 +                      err = eth_network_enable_eapol(service, network);
 +                      if (err < 0) {
 +                              DBG("Failed to enable eapol");
 +                              return err;
 +                      }
 +              } else {
 +                      err = eapol_interface_create();
 +                      if (err < 0) {
 +                              DBG("Failed to create eapol interface");
 +                              return err;
 +                      }
 +
 +                      return 0;
 +              }
 +      }
 +
 +      connman_network_set_connected(network, true);
 +
 +      return 0;
 +}
 +
 +static int eth_network_disconnect(struct connman_network *network)
 +{
 +      DBG("network %p", network);
 +
 +      struct connman_service *service = connman_service_lookup_from_network(network);
 +
 +      if (service && __connman_service_get_use_eapol(service)) {
 +              struct connman_device *device = connman_network_get_device(network);
 +              struct ethernet_data *ethernet = connman_device_get_data(device);
 +
 +              enable_eapol_data.network = NULL;
 +              g_supplicant_unregister_eap_callback();
 +              if (ethernet && ethernet->interface) {
 +                      g_supplicant_interface_remove(ethernet->interface, NULL, NULL);
 +                      ethernet->interface = NULL;
 +              }
 +              connman_network_set_associating(network, false);
 +              connman_network_set_connected(network, false);
 +
 +              return 0;
 +      }
 +
 +      connman_network_set_connected(network, false);
 +
 +      return 0;
 +}
 +
 +#else /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
  static int eth_network_connect(struct connman_network *network)
  {
        DBG("network %p", network);
diff --cc plugins/iwd.c
Simple merge
index 28a59c9,e113887..3809d8f
mode 100755,100644..100755
@@@ -48,50 -46,16 +48,51 @@@ static in_addr_t loopback_netmask
  
  static char system_hostname[HOST_NAME_MAX + 1];
  
- static void create_hostname(void)
- {
-       const char *name = "localhost";
-       if (sethostname(name, strlen(name)) < 0)
-               connman_error("Failed to set hostname to %s", name);
-       strncpy(system_hostname, name, HOST_NAME_MAX);
- }
 +#if defined TIZEN_EXT
 +static void _create_hostname(void)
 +{
 +      FILE *fp = NULL;
 +#define WIFI_MAC "/opt/etc/.mac.info"
 +
 +      memset(system_hostname, 0, sizeof(system_hostname));
 +
 +      char* rv = 0;
 +      gchar* dev_id = "TIZEN";
 +      char wifi_mac[HOST_NAME_MAX + 1];
 +
 +      fp = fopen(WIFI_MAC, "r");
 +      if(!fp){
 +              connman_error("Failed to get current hostname");
 +              strncpy(system_hostname, dev_id, strlen(dev_id));
 +              return;
 +      }
 +
 +      rv = fgets(wifi_mac, HOST_NAME_MAX, fp);
 +      if(!rv){
 +              connman_error("Failed to get current hostname");
 +              strncpy(system_hostname, dev_id, strlen(dev_id));
 +              fclose(fp);
 +              return;
 +      }
 +
 +      dev_id = g_base64_encode((const guchar *)wifi_mac, strlen(wifi_mac));
 +      g_sprintf(system_hostname, "TIZEN-%s", dev_id);
 +      g_free(dev_id);
 +      fclose(fp);
 +}
++#else
+ static void create_hostname(void)
+ {
+       const char *name = "localhost";
+       if (sethostname(name, strlen(name)) < 0)
+               connman_error("Failed to set hostname to %s", name);
+       strncpy(system_hostname, name, HOST_NAME_MAX);
+ }
 +#endif
 +
  static int setup_hostname(void)
  {
        char name[HOST_NAME_MAX + 1];
                connman_error("Failed to get current hostname");
                return -EIO;
        }
 +#if defined TIZEN_EXT
 +      if (strlen(system_hostname) > 0 &&
 +                      strcmp(system_hostname, "(none)") != 0 &&
 +                      strcmp(system_hostname, "localhost") != 0)
 +              connman_info("System hostname is %s", system_hostname);
 +      else
 +              _create_hostname();
 +#else
        if (strlen(system_hostname) > 0 &&
                                strcmp(system_hostname, "(none)") != 0)
                connman_info("System hostname is %s", system_hostname);
diff --cc plugins/neard.c
index 69586df,45effd4..45effd4
mode 100755,100644..100755
diff --cc plugins/ofono.c
index 36873d5,f0bd3c5..f0bd3c5
mode 100755,100644..100755
diff --cc plugins/vpn.c
index 5668c00,d708d1f..d708d1f
mode 100755,100644..100755
diff --cc plugins/wifi.c
index 26b988e,e701451..bcb9344
mode 100755,100644..100755
  #define P2P_LISTEN_PERIOD 500
  #define P2P_LISTEN_INTERVAL 2000
  
+ #define ASSOC_STATUS_AUTH_TIMEOUT 16
  #define ASSOC_STATUS_NO_CLIENT 17
 +#if defined TIZEN_EXT
 +#define LOAD_SHAPING_MAX_RETRIES 7
 +#else
  #define LOAD_SHAPING_MAX_RETRIES 3
 +#endif
 +
 +#if defined TIZEN_EXT
 +#define WIFI_EAP_FAST_PAC_FILE                "/var/lib/wifi/wifi.pac"        /* path of Pac file for EAP-FAST */
 +
 +      /* Wi-Fi Signal Strength (for 2.4G (dB))
 +       * Excellent :     ~ -63
 +       * Good      : -64 ~ -74
 +       * Weak      : -75 ~ -82
 +       * Very weak : -83 ~ -88
 +       * No signal : -89 ~
 +       *
 +       * Wi-Fi Signal Strength (for 5G (dB))
 +       * Excellent :     ~ -67
 +       * Good      : -68 ~ -76
 +       * Weak      : -77 ~ -82
 +       * Very weak : -83 ~ -88
 +       * No signal : -89 ~
 +       */
 +#define RSSI_LEVEL_2_5G  -77
 +#define RSSI_LEVEL_2_24G -75
 +#define RSSI_LEVEL_3_5G  -68
 +#define RSSI_LEVEL_3_24G -64
 +#define WIFI_BSSID_STR_LEN 18
 +#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
 +#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
 +#define ROAM_SCAN_INTERVAL 60 /* 60 seconds */
 +#endif
  
  static struct connman_technology *wifi_technology = NULL;
  static struct connman_technology *p2p_technology = NULL;
@@@ -192,38 -162,15 +193,42 @@@ struct wifi_data 
        bool p2p_connecting;
        bool p2p_device;
        int servicing;
 +#if defined TIZEN_EXT
 +      int assoc_retry_count;
 +      struct connman_network *scan_pending_network;
 +      bool allow_full_scan;
 +      unsigned int automaxspeed_timeout;
 +      GSupplicantScanParams *hidden_scan_params;
 +      unsigned int mac_policy;
 +      unsigned int preassoc_mac_policy;
 +      unsigned int mac_lifetime;
 +#endif
        int disconnect_code;
        int assoc_code;
 +#if defined TIZEN_EXT_WIFI_MESH
 +      bool mesh_interface;
 +      struct wifi_mesh_info *mesh_info;
 +#endif
  };
  
+ struct disconnect_data {
+       struct wifi_data *wifi;
+       struct connman_network *network;
+ };
 +#if defined TIZEN_EXT
 +#include "connman.h"
 +#include "dbus.h"
 +
 +#define TIZEN_ASSOC_RETRY_COUNT               4
 +
 +static gboolean wifi_first_scan = false;
 +static gboolean found_with_first_scan = false;
 +static gboolean is_wifi_notifier_registered = false;
 +static GHashTable *failed_bssids = NULL;
 +static unsigned char buff_bssid[WIFI_BSSID_LEN_MAX] = { 0, };
 +#endif
 +
  static GList *iface_list = NULL;
  
  static GList *pending_wifi_device = NULL;
@@@ -859,2096 -671,949 +864,2128 @@@ static void mesh_group_removed(GSupplic
                }
        }
  
 -      return 0;
 +      connman_mesh_peer_set_disconnect_reason(mesh, disconnect_reason);
 +      connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_DISCONNECT);
  }
  
 -static int peer_unregister_service(const unsigned char *specification,
 -                                              int specification_length,
 -                                              const unsigned char *query,
 -                                              int query_length, int version)
 +static void mesh_peer_connected(GSupplicantMeshPeer *mesh_peer)
  {
 -      GSupplicantP2PServiceParams *params;
 -      bool wfd = false;
 -      GList *list;
 -      int ret;
 +      const char *peer_address;
  
 -      if (specification && !version && !query &&
 -                      is_service_wfd(specification, specification_length)) {
 -              ret = peer_unregister_wfd_service();
 -              if (ret != 0 && ret != -EINPROGRESS)
 -                      return ret;
 -              wfd = true;
 -      }
 -
 -      for (list = iface_list; list; list = list->next) {
 -              struct wifi_data *wifi = list->data;
 -              GSupplicantInterface *iface = wifi->interface;
 -
 -              if (wfd)
 -                      goto stop_listening;
 -
 -              if (!g_supplicant_interface_has_p2p(iface))
 -                      continue;
 -
 -              params = fill_in_peer_service_params(specification,
 -                                              specification_length, query,
 -                                              query_length, version);
 -              if (!params)
 -                      continue;
 +      peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
  
 -              ret = g_supplicant_interface_p2p_del_service(iface, params);
 -              if (ret != 0 && ret != -EINPROGRESS)
 -                      free_peer_service_params(params);
 -stop_listening:
 -              wifi->servicing--;
 -              if (!wifi->servicing || wifi->servicing < 0) {
 -                      g_supplicant_interface_p2p_listen(iface, 0, 0);
 -                      wifi->servicing = 0;
 -              }
 -      }
 +      if (!peer_address)
 +              return;
  
 -      return 0;
 +      DBG("Peer %s connected", peer_address);
 +      connman_mesh_add_connected_peer(peer_address);
  }
  
 -static struct connman_peer_driver peer_driver = {
 -      .connect    = peer_connect,
 -      .disconnect = peer_disconnect,
 -      .register_service = peer_register_service,
 -      .unregister_service = peer_unregister_service,
 -};
 -
 -static void handle_tethering(struct wifi_data *wifi)
 +static void mesh_peer_disconnected(GSupplicantMeshPeer *mesh_peer)
  {
 -      if (!wifi->tethering)
 -              return;
 +      const char *peer_address;
 +      int reason;
  
 -      if (!wifi->bridge)
 -              return;
 +      peer_address = g_supplicant_mesh_peer_get_address(mesh_peer);
  
 -      if (wifi->bridged)
 +      if (!peer_address)
                return;
  
 -      DBG("index %d bridge %s", wifi->index, wifi->bridge);
 -
 -      if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
 -              return;
 +      reason = g_supplicant_mesh_peer_get_disconnect_reason(mesh_peer);
  
 -      wifi->bridged = true;
 +      DBG("Peer %s disconnected with reason %d", peer_address, reason);
 +      connman_mesh_remove_connected_peer(peer_address, reason);
  }
 +#endif
  
 -static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
 +static struct wifi_data *get_pending_wifi_data(const char *ifname)
  {
 -      struct connman_device *device = user_data;
 -      struct wifi_data *wifi = connman_device_get_data(device);
 -
 -      if (!wifi)
 -              return;
 +      GList *list;
  
 -      DBG("index %d flags %d change %d", wifi->index, flags, change);
 +      for (list = pending_wifi_device; list; list = list->next) {
 +              struct wifi_data *wifi;
 +              const char *dev_name;
  
 -      if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
 -              if (flags & IFF_UP)
 -                      DBG("interface up");
 -              else
 -                      DBG("interface down");
 -      }
 +              wifi = list->data;
 +              if (!wifi || !wifi->device)
 +                      continue;
  
 -      if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
 -              if (flags & IFF_LOWER_UP)
 -                      DBG("carrier on");
 -              else
 -                      DBG("carrier off");
 +              dev_name = connman_device_get_string(wifi->device, "Interface");
 +              if (!g_strcmp0(ifname, dev_name)) {
 +                      pending_wifi_device = g_list_delete_link(
 +                                              pending_wifi_device, list);
 +                      return wifi;
 +              }
        }
  
 -      if (flags & IFF_LOWER_UP)
 -              handle_tethering(wifi);
 -
 -      wifi->flags = flags;
 +      return NULL;
  }
  
 -static int wifi_probe(struct connman_device *device)
 +static void remove_pending_wifi_device(struct wifi_data *wifi)
  {
 -      struct wifi_data *wifi;
 -
 -      DBG("device %p", device);
 -
 -      wifi = g_try_new0(struct wifi_data, 1);
 -      if (!wifi)
 -              return -ENOMEM;
 -
 -      wifi->state = G_SUPPLICANT_STATE_INACTIVE;
 -      wifi->ap_supported = WIFI_AP_UNKNOWN;
 -      wifi->tethering_param = NULL;
 -
 -      connman_device_set_data(device, wifi);
 -      wifi->device = connman_device_ref(device);
 +      GList *link;
  
 -      wifi->index = connman_device_get_index(device);
 -      wifi->flags = 0;
 +      link = g_list_find(pending_wifi_device, wifi);
  
 -      wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
 -                                                      wifi_newlink, device);
 -      if (is_p2p_connecting())
 -              add_pending_wifi_device(wifi);
 -      else
 -              iface_list = g_list_append(iface_list, wifi);
 +      if (!link)
 +              return;
  
 -      return 0;
 +      pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
  }
  
 -static void remove_networks(struct connman_device *device,
 -                              struct wifi_data *wifi)
 +static void peer_cancel_timeout(struct wifi_data *wifi)
  {
 -      GSList *list;
 +      if (wifi->p2p_connection_timeout > 0)
 +              g_source_remove(wifi->p2p_connection_timeout);
  
 -      for (list = wifi->networks; list; list = list->next) {
 -              struct connman_network *network = list->data;
 +      wifi->p2p_connection_timeout = 0;
 +      wifi->p2p_connecting = false;
  
 -              connman_device_remove_network(device, network);
 -              connman_network_unref(network);
 +      if (wifi->pending_peer) {
 +              connman_peer_unref(wifi->pending_peer);
 +              wifi->pending_peer = NULL;
        }
 -
 -      g_slist_free(wifi->networks);
 -      wifi->networks = NULL;
  }
  
 -static void remove_peers(struct wifi_data *wifi)
 +static gboolean peer_connect_timeout(gpointer data)
  {
 -      GSList *list;
 +      struct wifi_data *wifi = data;
  
 -      for (list = wifi->peers; list; list = list->next) {
 -              struct connman_peer *peer = list->data;
 +      DBG("");
  
 -              connman_peer_unregister(peer);
 -              connman_peer_unref(peer);
 +      if (wifi->p2p_connecting) {
 +              enum connman_peer_state state = CONNMAN_PEER_STATE_FAILURE;
 +              GSupplicantPeer *gs_peer =
 +                      g_supplicant_interface_peer_lookup(wifi->interface,
 +                              connman_peer_get_identifier(wifi->pending_peer));
 +
 +              if (g_supplicant_peer_has_requested_connection(gs_peer))
 +                      state = CONNMAN_PEER_STATE_IDLE;
 +
 +              connman_peer_set_state(wifi->pending_peer, state);
        }
  
 -      g_slist_free(wifi->peers);
 -      wifi->peers = NULL;
 +      peer_cancel_timeout(wifi);
 +
 +      return FALSE;
  }
  
 -static void reset_autoscan(struct connman_device *device)
 +static void peer_connect_callback(int result, GSupplicantInterface *interface,
 +                                                      void *user_data)
  {
 -      struct wifi_data *wifi = connman_device_get_data(device);
 -      struct autoscan_params *autoscan;
 +      struct wifi_data *wifi = user_data;
 +      struct connman_peer *peer = wifi->pending_peer;
  
 -      DBG("");
 +      DBG("peer %p - %d", peer, result);
  
 -      if (!wifi || !wifi->autoscan)
 +      if (!peer)
                return;
  
 -      autoscan = wifi->autoscan;
 -
 -      autoscan->interval = 0;
 -
 -      if (autoscan->timeout == 0)
 +      if (result < 0) {
 +              peer_connect_timeout(wifi);
                return;
 +      }
  
 -      g_source_remove(autoscan->timeout);
 -      autoscan->timeout = 0;
 +      connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
  
 -      connman_device_unref(device);
 +      wifi->p2p_connection_timeout = g_timeout_add_seconds(
 +                                              P2P_CONNECTION_TIMEOUT,
 +                                              peer_connect_timeout, wifi);
  }
  
 -static void stop_autoscan(struct connman_device *device)
 +static int peer_connect(struct connman_peer *peer,
 +                      enum connman_peer_wps_method wps_method,
 +                      const char *wps_pin)
  {
 -      const struct wifi_data *wifi = connman_device_get_data(device);
 +      struct connman_device *device = connman_peer_get_device(peer);
 +      GSupplicantPeerParams *peer_params;
 +      GSupplicantPeer *gs_peer;
 +      struct wifi_data *wifi;
 +      bool pbc, pin;
 +      int ret;
  
 -      if (!wifi || !wifi->autoscan)
 -              return;
 +      DBG("peer %p", peer);
  
 -      reset_autoscan(device);
 +      if (!device)
 +              return -ENODEV;
  
 -      connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
 -}
 +      wifi = connman_device_get_data(device);
 +      if (!wifi || !wifi->interface)
 +              return -ENODEV;
  
 -static void check_p2p_technology(void)
 -{
 -      bool p2p_exists = false;
 -      GList *list;
 +      if (wifi->p2p_connecting)
 +              return -EBUSY;
  
 -      for (list = iface_list; list; list = list->next) {
 -              struct wifi_data *w = list->data;
 +      gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
 +                                      connman_peer_get_identifier(peer));
 +      if (!gs_peer)
 +              return -EINVAL;
  
 -              if (w->interface &&
 -                              g_supplicant_interface_has_p2p(w->interface))
 -                      p2p_exists = true;
 -      }
 +      pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
 +      pin = g_supplicant_peer_is_wps_pin(gs_peer);
  
 -      if (!p2p_exists) {
 -              connman_technology_driver_unregister(&p2p_tech_driver);
 -              connman_peer_driver_unregister(&peer_driver);
 +      switch (wps_method) {
 +      case CONNMAN_PEER_WPS_UNKNOWN:
 +              if ((pbc && pin) || pin)
 +                      return -ENOKEY;
 +              break;
 +      case CONNMAN_PEER_WPS_PBC:
 +              if (!pbc)
 +                      return -EINVAL;
 +              wps_pin = NULL;
 +              break;
 +      case CONNMAN_PEER_WPS_PIN:
 +              if (!pin || !wps_pin)
 +                      return -EINVAL;
 +              break;
        }
 -}
 -
 -static void wifi_remove(struct connman_device *device)
 -{
 -      struct wifi_data *wifi = connman_device_get_data(device);
  
 -      DBG("device %p wifi %p", device, wifi);
 +      peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
 +      if (!peer_params)
 +              return -ENOMEM;
  
 -      if (!wifi)
 +      peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
 +      if (wps_pin)
 +              peer_params->wps_pin = g_strdup(wps_pin);
 +
 +      peer_params->master = connman_peer_service_is_master();
 +
 +      ret = g_supplicant_interface_p2p_connect(wifi->interface, peer_params,
 +                                              peer_connect_callback, wifi);
 +      if (ret == -EINPROGRESS) {
 +              wifi->pending_peer = connman_peer_ref(peer);
 +              wifi->p2p_connecting = true;
 +      } else if (ret < 0) {
 +              g_free(peer_params->path);
 +              g_free(peer_params->wps_pin);
 +              g_free(peer_params);
 +      }
 +
 +      return ret;
 +}
 +
 +static int peer_disconnect(struct connman_peer *peer)
 +{
 +      struct connman_device *device = connman_peer_get_device(peer);
 +      GSupplicantPeerParams peer_params = {};
 +      GSupplicantPeer *gs_peer;
 +      struct wifi_data *wifi;
 +      int ret;
 +
 +      DBG("peer %p", peer);
 +
 +      if (!device)
 +              return -ENODEV;
 +
 +      wifi = connman_device_get_data(device);
 +      if (!wifi)
 +              return -ENODEV;
 +
 +      gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
 +                                      connman_peer_get_identifier(peer));
 +      if (!gs_peer)
 +              return -EINVAL;
 +
 +      peer_params.path = g_strdup(g_supplicant_peer_get_path(gs_peer));
 +
 +      ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
 +                                                      &peer_params);
 +      g_free(peer_params.path);
 +
 +      if (ret == -EINPROGRESS) {
 +              peer_cancel_timeout(wifi);
 +              wifi->p2p_device = false;
 +      }
 +
 +      return ret;
 +}
 +
 +struct peer_service_registration {
 +      peer_service_registration_cb_t callback;
 +      void *user_data;
 +};
 +
 +static bool is_service_wfd(const unsigned char *specs, int length)
 +{
 +      if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
 +              return false;
 +
 +      return true;
 +}
 +
 +static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
 +{
 +      struct wifi_data *wifi = data;
 +
 +      if (!wifi->interface ||
 +                      !g_supplicant_interface_has_p2p(wifi->interface))
 +              return;
 +
 +      if (!wifi->servicing) {
 +              g_supplicant_interface_p2p_listen(wifi->interface,
 +                              P2P_LISTEN_PERIOD, P2P_LISTEN_INTERVAL);
 +      }
 +
 +      wifi->servicing++;
 +}
 +
 +static void register_wfd_service_cb(int result,
 +                              GSupplicantInterface *iface, void *user_data)
 +{
 +      struct peer_service_registration *reg_data = user_data;
 +
 +      DBG("");
 +
 +      if (result == 0)
 +              g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
 +
 +      if (reg_data && reg_data->callback) {
 +              reg_data->callback(result, reg_data->user_data);
 +              g_free(reg_data);
 +      }
 +}
 +
 +static GSupplicantP2PServiceParams *fill_in_peer_service_params(
 +                              const unsigned char *spec,
 +                              int spec_length, const unsigned char *query,
 +                              int query_length, int version)
 +{
 +      GSupplicantP2PServiceParams *params;
 +
 +      params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
 +      if (!params)
 +              return NULL;
 +
 +      if (version > 0) {
 +              params->version = version;
-               params->service = g_memdup(spec, spec_length);
++              if (spec_length > 0) {
++                      params->service = g_malloc(spec_length);
++                      memcpy(params->service, spec, spec_length);
++              }
 +      } else if (query_length > 0 && spec_length > 0) {
-               params->query = g_memdup(query, query_length);
++              params->query = g_malloc(query_length);
++              memcpy(params->query, query, query_length);
 +              params->query_length = query_length;
 +
-               params->response = g_memdup(spec, spec_length);
++              params->response = g_malloc(spec_length);
++              memcpy(params->response, spec, spec_length);
 +              params->response_length = spec_length;
 +      } else {
-               params->wfd_ies = g_memdup(spec, spec_length);
++              if (spec_length > 0) {
++                      params->wfd_ies = g_malloc(spec_length);
++                      memcpy(params->wfd_ies, spec, spec_length);
++              }
 +              params->wfd_ies_length = spec_length;
 +      }
 +
 +      return params;
 +}
 +
 +static void free_peer_service_params(GSupplicantP2PServiceParams *params)
 +{
 +      if (!params)
 +              return;
 +
 +      g_free(params->service);
 +      g_free(params->query);
 +      g_free(params->response);
 +      g_free(params->wfd_ies);
 +
 +      g_free(params);
 +}
 +
 +static int peer_register_wfd_service(const unsigned char *specification,
 +                              int specification_length,
 +                              peer_service_registration_cb_t callback,
 +                              void *user_data)
 +{
 +      struct peer_service_registration *reg_data = NULL;
 +      static GSupplicantP2PServiceParams *params;
 +      int ret;
 +
 +      DBG("");
 +
 +      if (wfd_service_registered)
 +              return -EBUSY;
 +
 +      params = fill_in_peer_service_params(specification,
 +                                      specification_length, NULL, 0, 0);
 +      if (!params)
 +              return -ENOMEM;
 +
 +      reg_data = g_try_malloc0(sizeof(*reg_data));
 +      if (!reg_data) {
 +              ret = -ENOMEM;
 +              goto error;
 +      }
 +
 +      reg_data->callback = callback;
 +      reg_data->user_data = user_data;
 +
 +      ret = g_supplicant_set_widi_ies(params,
 +                                      register_wfd_service_cb, reg_data);
 +      if (ret < 0 && ret != -EINPROGRESS)
 +              goto error;
 +
 +      wfd_service_registered = true;
 +
 +      return ret;
 +error:
 +      free_peer_service_params(params);
 +      g_free(reg_data);
 +
 +      return ret;
 +}
 +
 +static void register_peer_service_cb(int result,
 +                              GSupplicantInterface *iface, void *user_data)
 +{
 +      struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
 +      struct peer_service_registration *reg_data = user_data;
 +
 +#if defined TIZEN_EXT
 +      if (!wifi)
                return;
-               if (flags & IFF_LOWER_UP) {
 +#endif
 +
 +      DBG("");
 +
 +      if (result == 0)
 +              apply_p2p_listen_on_iface(wifi, NULL);
 +
 +      if (reg_data->callback)
 +              reg_data->callback(result, reg_data->user_data);
 +
 +      g_free(reg_data);
 +}
 +
 +static int peer_register_service(const unsigned char *specification,
 +                              int specification_length,
 +                              const unsigned char *query,
 +                              int query_length, int version,
 +                              peer_service_registration_cb_t callback,
 +                              void *user_data)
 +{
 +      struct peer_service_registration *reg_data;
 +      GSupplicantP2PServiceParams *params;
 +      bool found = false;
 +      int ret, ret_f;
 +      GList *list;
 +
 +      DBG("");
 +
 +      if (specification && !version && !query &&
 +                      is_service_wfd(specification, specification_length)) {
 +              return peer_register_wfd_service(specification,
 +                              specification_length, callback, user_data);
 +      }
 +
 +      reg_data = g_try_malloc0(sizeof(*reg_data));
 +      if (!reg_data)
 +              return -ENOMEM;
 +
 +      reg_data->callback = callback;
 +      reg_data->user_data = user_data;
 +
 +      ret_f = -EOPNOTSUPP;
 +
 +      for (list = iface_list; list; list = list->next) {
 +              struct wifi_data *wifi = list->data;
 +              GSupplicantInterface *iface = wifi->interface;
 +
 +              if (!g_supplicant_interface_has_p2p(iface))
 +                      continue;
 +
 +              params = fill_in_peer_service_params(specification,
 +                                              specification_length, query,
 +                                              query_length, version);
 +              if (!params)
 +                      continue;
 +
 +              if (!found) {
 +                      ret_f = g_supplicant_interface_p2p_add_service(iface,
 +                              register_peer_service_cb, params, reg_data);
 +                      if (ret_f == 0 || ret_f == -EINPROGRESS)
 +                              found = true;
 +                      ret = ret_f;
 +              } else
 +                      ret = g_supplicant_interface_p2p_add_service(iface,
 +                              register_peer_service_cb, params, NULL);
 +              if (ret != 0 && ret != -EINPROGRESS)
 +                      free_peer_service_params(params);
 +      }
 +
 +      if (ret_f != 0 && ret_f != -EINPROGRESS)
 +              g_free(reg_data);
 +
 +      return ret_f;
 +}
 +
 +static int peer_unregister_wfd_service(void)
 +{
 +      GSupplicantP2PServiceParams *params;
 +      GList *list;
 +
 +      if (!wfd_service_registered)
 +              return -EALREADY;
 +
 +      params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
 +      if (!params)
 +              return -ENOMEM;
 +
 +      wfd_service_registered = false;
 +
 +      g_supplicant_set_widi_ies(params, NULL, NULL);
 +
 +      for (list = iface_list; list; list = list->next) {
 +              struct wifi_data *wifi = list->data;
 +
 +              if (!g_supplicant_interface_has_p2p(wifi->interface))
 +                      continue;
 +
 +              wifi->servicing--;
 +              if (!wifi->servicing || wifi->servicing < 0) {
 +                      g_supplicant_interface_p2p_listen(wifi->interface,
 +                                                                      0, 0);
 +                      wifi->servicing = 0;
 +              }
 +      }
 +
 +      return 0;
 +}
 +
 +static int peer_unregister_service(const unsigned char *specification,
 +                                              int specification_length,
 +                                              const unsigned char *query,
 +                                              int query_length, int version)
 +{
 +      GSupplicantP2PServiceParams *params;
 +      bool wfd = false;
 +      GList *list;
 +      int ret;
 +
 +      if (specification && !version && !query &&
 +                      is_service_wfd(specification, specification_length)) {
 +              ret = peer_unregister_wfd_service();
 +              if (ret != 0 && ret != -EINPROGRESS)
 +                      return ret;
 +              wfd = true;
 +      }
 +
 +      for (list = iface_list; list; list = list->next) {
 +              struct wifi_data *wifi = list->data;
 +              GSupplicantInterface *iface = wifi->interface;
 +
 +              if (wfd)
 +                      goto stop_listening;
 +
 +              if (!g_supplicant_interface_has_p2p(iface))
 +                      continue;
 +
 +              params = fill_in_peer_service_params(specification,
 +                                              specification_length, query,
 +                                              query_length, version);
 +              if (!params)
 +                      continue;
 +
 +              ret = g_supplicant_interface_p2p_del_service(iface, params);
 +              if (ret != 0 && ret != -EINPROGRESS)
 +                      free_peer_service_params(params);
 +stop_listening:
 +              wifi->servicing--;
 +              if (!wifi->servicing || wifi->servicing < 0) {
 +                      g_supplicant_interface_p2p_listen(iface, 0, 0);
 +                      wifi->servicing = 0;
 +              }
 +      }
 +
 +      return 0;
 +}
 +
 +static struct connman_peer_driver peer_driver = {
 +      .connect    = peer_connect,
 +      .disconnect = peer_disconnect,
 +      .register_service = peer_register_service,
 +      .unregister_service = peer_unregister_service,
 +};
 +
 +static void handle_tethering(struct wifi_data *wifi)
 +{
 +      if (!wifi->tethering)
 +              return;
 +
 +      if (!wifi->bridge)
 +              return;
 +
 +      if (wifi->bridged)
 +              return;
 +
 +      DBG("index %d bridge %s", wifi->index, wifi->bridge);
 +
 +      if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
 +              return;
 +
 +      wifi->bridged = true;
 +}
 +
 +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)
 +              return;
 +
 +      DBG("index %d flags %d change %d", wifi->index, flags, change);
 +
 +      if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
 +              if (flags & IFF_UP)
 +                      DBG("interface up");
 +              else
 +                      DBG("interface down");
 +      }
 +
 +      if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
-                       handle_tethering(wifi);
-               } else
++              if (flags & IFF_LOWER_UP)
 +                      DBG("carrier on");
++              else
 +                      DBG("carrier off");
 +      }
 +
++      if (flags & IFF_LOWER_UP)
++              handle_tethering(wifi);
++
 +      wifi->flags = flags;
 +}
 +
 +static int wifi_probe(struct connman_device *device)
 +{
 +      struct wifi_data *wifi;
 +
 +      DBG("device %p", device);
 +
 +      wifi = g_try_new0(struct wifi_data, 1);
 +      if (!wifi)
 +              return -ENOMEM;
 +
 +      wifi->state = G_SUPPLICANT_STATE_INACTIVE;
 +      wifi->ap_supported = WIFI_AP_UNKNOWN;
 +      wifi->tethering_param = NULL;
 +
 +      connman_device_set_data(device, wifi);
 +      wifi->device = connman_device_ref(device);
 +
 +      wifi->index = connman_device_get_index(device);
 +      wifi->flags = 0;
 +
 +      wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
 +                                                      wifi_newlink, device);
 +      if (is_p2p_connecting())
 +              add_pending_wifi_device(wifi);
 +      else
 +              iface_list = g_list_append(iface_list, wifi);
 +
 +      return 0;
 +}
 +
 +static void remove_networks(struct connman_device *device,
 +                              struct wifi_data *wifi)
 +{
 +      GSList *list;
 +
 +      for (list = wifi->networks; list; list = list->next) {
 +              struct connman_network *network = list->data;
 +
 +              connman_device_remove_network(device, network);
 +              connman_network_unref(network);
 +      }
 +
 +      g_slist_free(wifi->networks);
 +      wifi->networks = NULL;
 +}
 +
 +static void remove_peers(struct wifi_data *wifi)
 +{
 +      GSList *list;
 +
 +      for (list = wifi->peers; list; list = list->next) {
 +              struct connman_peer *peer = list->data;
 +
 +              connman_peer_unregister(peer);
 +              connman_peer_unref(peer);
 +      }
 +
 +      g_slist_free(wifi->peers);
 +      wifi->peers = NULL;
 +}
 +
 +static void reset_autoscan(struct connman_device *device)
 +{
 +      struct wifi_data *wifi = connman_device_get_data(device);
 +      struct autoscan_params *autoscan;
 +
 +      DBG("");
 +
 +      if (!wifi || !wifi->autoscan)
 +              return;
 +
 +      autoscan = wifi->autoscan;
 +
 +      autoscan->interval = 0;
 +
 +      if (autoscan->timeout == 0)
 +              return;
 +
 +      g_source_remove(autoscan->timeout);
 +      autoscan->timeout = 0;
 +
 +      connman_device_unref(device);
 +}
 +
 +static void stop_autoscan(struct connman_device *device)
 +{
 +      const struct wifi_data *wifi = connman_device_get_data(device);
 +
 +      if (!wifi || !wifi->autoscan)
 +              return;
 +
 +      reset_autoscan(device);
 +
 +      connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
 +}
 +
 +static void check_p2p_technology(void)
 +{
 +      bool p2p_exists = false;
 +      GList *list;
 +
 +      for (list = iface_list; list; list = list->next) {
 +              struct wifi_data *w = list->data;
 +
 +              if (w->interface &&
 +                              g_supplicant_interface_has_p2p(w->interface))
 +                      p2p_exists = true;
 +      }
 +
 +      if (!p2p_exists) {
 +              connman_technology_driver_unregister(&p2p_tech_driver);
 +              connman_peer_driver_unregister(&peer_driver);
 +      }
 +}
 +
 +struct last_connected {
 +      GTimeVal modified;
 +      gchar *ssid;
 +      int freq;
 +};
 +
 +static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
 +{
 +      GTimeVal *aval = (GTimeVal *)a;
 +      GTimeVal *bval = (GTimeVal *)b;
 +
 +      /* Note that the sort order is descending */
 +      if (aval->tv_sec < bval->tv_sec)
 +              return 1;
 +
 +      if (aval->tv_sec > bval->tv_sec)
 +              return -1;
 +
 +      return 0;
 +}
 +
 +static void free_entry(gpointer data)
 +{
 +      struct last_connected *entry = data;
 +
 +      g_free(entry->ssid);
 +      g_free(entry);
 +}
 +
 +static void wifi_remove(struct connman_device *device)
 +{
 +      struct wifi_data *wifi = connman_device_get_data(device);
 +
 +      DBG("device %p wifi %p", device, wifi);
 +
 +      if (!wifi)
 +              return;
 +
 +      stop_autoscan(device);
 +
 +      if (wifi->p2p_device)
 +              p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
 +      else
 +              iface_list = g_list_remove(iface_list, wifi);
 +
 +      check_p2p_technology();
 +#if defined TIZEN_EXT_WIFI_MESH
 +      check_mesh_technology();
 +#endif
 +
 +      remove_pending_wifi_device(wifi);
 +
 +      if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
 +              g_source_remove(wifi->p2p_find_timeout);
 +              connman_device_unref(wifi->device);
 +      }
 +
 +      if (wifi->p2p_connection_timeout)
 +              g_source_remove(wifi->p2p_connection_timeout);
 +
 +#if defined TIZEN_EXT
 +      if (wifi->automaxspeed_timeout != 0) {
 +              g_source_remove(wifi->automaxspeed_timeout);
 +              wifi->automaxspeed_timeout = 0;
 +      }
 +#endif
 +
 +      remove_networks(device, wifi);
 +      remove_peers(wifi);
 +
 +      connman_device_set_powered(device, false);
 +      connman_device_set_data(device, NULL);
 +      connman_device_unref(wifi->device);
 +      connman_rtnl_remove_watch(wifi->watch);
 +
 +      g_supplicant_interface_set_data(wifi->interface, NULL);
 +
 +      g_supplicant_interface_cancel(wifi->interface);
 +
 +      if (wifi->scan_params)
 +              g_supplicant_free_scan_params(wifi->scan_params);
 +#if defined TIZEN_EXT
 +      if (wifi->hidden_scan_params) {
 +              while (wifi->hidden_scan_params->ssids) {
 +                      struct scan_ssid *ssid;
 +                      ssid = wifi->hidden_scan_params->ssids->data;
 +                      wifi->hidden_scan_params->ssids = g_slist_remove(wifi->hidden_scan_params->ssids, ssid);
 +              }
 +              g_supplicant_free_scan_params(wifi->hidden_scan_params);
 +      }
 +#endif
 +
 +      g_free(wifi->autoscan);
 +      g_free(wifi->identifier);
 +      g_free(wifi);
 +}
 +
 +static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
 +{
 +      GSList *iter;
 +
 +      for (iter = list; iter; iter = g_slist_next(iter)) {
 +              struct scan_ssid *scan_ssid = iter->data;
 +
 +              if (ssid_len == scan_ssid->ssid_len &&
 +                              memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
 +                      return true;
 +      }
 +
 +      return false;
 +}
 +
 +static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
 +                      int freq, GSupplicantScanParams *scan_data,
 +                      int driver_max_scan_ssids, char *ssid_name)
 +{
 +      unsigned int i;
 +      struct scan_ssid *scan_ssid;
 +
 +      if ((driver_max_scan_ssids == 0 ||
 +                      driver_max_scan_ssids > scan_data->num_ssids) &&
 +                      (hex_ssid || raw_ssid)) {
 +              gchar *ssid;
 +              unsigned int j = 0, hex;
 +
 +              if (hex_ssid) {
 +                      size_t hex_ssid_len = strlen(hex_ssid);
 +
 +                      ssid = g_try_malloc0(hex_ssid_len / 2);
 +                      if (!ssid)
 +                              return -ENOMEM;
 +
 +                      for (i = 0; i < hex_ssid_len; i += 2) {
 +                              sscanf(hex_ssid + i, "%02x", &hex);
 +                              ssid[j++] = hex;
 +                      }
 +              } else {
 +                      ssid = raw_ssid;
 +                      j = ssid_len;
 +              }
 +
 +              /*
 +               * If we have already added hidden AP to the list,
 +               * then do not do it again. This might happen if you have
 +               * used or are using multiple wifi cards, so in that case
 +               * you might have multiple service files for same AP.
 +               */
 +              if (is_duplicate(scan_data->ssids, ssid, j)) {
 +                      if (hex_ssid)
 +                              g_free(ssid);
 +                      return 0;
 +              }
 +
 +              scan_ssid = g_try_new(struct scan_ssid, 1);
 +              if (!scan_ssid) {
 +                      if (hex_ssid)
 +                              g_free(ssid);
 +                      return -ENOMEM;
 +              }
 +
 +              memcpy(scan_ssid->ssid, ssid, j);
 +              scan_ssid->ssid_len = j;
 +              scan_data->ssids = g_slist_prepend(scan_data->ssids,
 +                                                              scan_ssid);
 +
 +              scan_data->num_ssids++;
 +
 +              DBG("SSID %s added to scanned list of %d entries", ssid_name,
 +                                                      scan_data->num_ssids);
 +
 +              if (hex_ssid)
 +                      g_free(ssid);
 +      } else
 +              return -EINVAL;
 +
 +      scan_data->ssids = g_slist_reverse(scan_data->ssids);
 +
 +      if (!scan_data->freqs) {
 +              scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
 +              if (!scan_data->freqs) {
 +                      g_slist_free_full(scan_data->ssids, g_free);
 +                      return -ENOMEM;
 +              }
 +
 +              scan_data->num_freqs = 1;
 +              scan_data->freqs[0] = freq;
 +      } else {
 +              bool duplicate = false;
 +
 +              /* Don't add duplicate entries */
 +              for (i = 0; i < scan_data->num_freqs; i++) {
 +                      if (scan_data->freqs[i] == freq) {
 +                              duplicate = true;
 +                              break;
 +                      }
 +              }
 +
 +              if (!duplicate) {
 +                      scan_data->num_freqs++;
 +                      scan_data->freqs = g_try_realloc(scan_data->freqs,
 +                              sizeof(uint16_t) * scan_data->num_freqs);
 +                      if (!scan_data->freqs) {
 +                              g_slist_free_full(scan_data->ssids, g_free);
 +                              return -ENOMEM;
 +                      }
 +                      scan_data->freqs[scan_data->num_freqs - 1] = freq;
 +              }
 +      }
 +
 +      return 1;
 +}
 +
 +static int get_hidden_connections(GSupplicantScanParams *scan_data)
 +{
 +      struct connman_config_entry **entries;
 +      GKeyFile *keyfile;
 +#if defined TIZEN_EXT
 +      gchar **services = NULL;
 +#else
 +      gchar **services;
 +#endif /* defined TIZEN_EXT */
 +      char *ssid, *name;
 +      int i, ret;
 +      bool value;
 +      int num_ssids = 0, add_param_failed = 0;
 +#if defined TIZEN_EXT
 +      GSequenceIter *iter;
 +      GSequence *latest_list;
 +      struct last_connected *entry;
 +      GTimeVal modified;
 +
 +      latest_list = g_sequence_new(free_entry);
 +      if (!latest_list)
 +              goto out;
 +#endif
 +      services = connman_storage_get_services();
 +      for (i = 0; services && services[i]; i++) {
 +              if (strncmp(services[i], "wifi_", 5) != 0)
 +                      continue;
 +
 +              keyfile = connman_storage_load_service(services[i]);
 +              if (!keyfile)
 +                      continue;
 +
 +              value = g_key_file_get_boolean(keyfile,
 +                                      services[i], "Hidden", NULL);
 +              if (!value) {
 +                      g_key_file_free(keyfile);
 +                      continue;
 +              }
 +
 +              value = g_key_file_get_boolean(keyfile,
 +                                      services[i], "Favorite", NULL);
 +              if (!value) {
 +                      g_key_file_free(keyfile);
 +                      continue;
 +              }
 +
 +#if defined TIZEN_EXT
 +              value = g_key_file_get_boolean(keyfile,
 +                                      services[i], "AutoConnect", NULL);
 +              if (!value) {
 +                      g_key_file_free(keyfile);
 +                      continue;
 +              }
 +
 +              gchar *str = g_key_file_get_string(keyfile,
 +                                      services[i], "Modified", NULL);
 +              if (!str) {
 +                      g_key_file_free(keyfile);
 +                      continue;
 +              }
 +              g_time_val_from_iso8601(str, &modified);
 +              g_free(str);
 +#endif
 +
 +              ssid = g_key_file_get_string(keyfile,
 +                                      services[i], "SSID", NULL);
 +
 +              name = g_key_file_get_string(keyfile, services[i], "Name",
 +                                                              NULL);
 +
 +#if defined TIZEN_EXT
 +              entry = g_try_new(struct last_connected, 1);
 +              if (!entry) {
 +                      g_sequence_free(latest_list);
 +                      g_free(ssid);
 +                      g_free(name);
 +                      g_key_file_free(keyfile);
 +                      goto out;
 +              }
 +
 +              entry->modified = modified;
 +              entry->ssid = ssid;
 +
 +              g_sequence_insert_sorted(latest_list, entry,
 +                              sort_entry, NULL);
 +#else
 +              ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
 +              if (ret < 0)
 +                      add_param_failed++;
 +              else if (ret > 0)
 +                      num_ssids++;
 +
 +              g_free(ssid);
 +#endif
 +              g_free(name);
 +              g_key_file_free(keyfile);
 +      }
 +
 +#if defined TIZEN_EXT
 +      gint length = g_sequence_get_length(latest_list);
 +      iter = g_sequence_get_begin_iter(latest_list);
 +
 +      for (i = 0; i < length; i++) {
 +              entry = g_sequence_get(iter);
 +
 +              ret = add_scan_param(entry->ssid, NULL, 0, 0, scan_data, 0, entry->ssid);
 +              if (ret < 0)
 +                      add_param_failed++;
 +              else if (ret > 0)
 +                      num_ssids++;
 +
 +              iter = g_sequence_iter_next(iter);
 +      }
 +
 +      g_sequence_free(latest_list);
 +out:
 +#endif
 +      /*
 +       * Check if there are any hidden AP that needs to be provisioned.
 +       */
 +      entries = connman_config_get_entries("wifi");
 +      for (i = 0; entries && entries[i]; i++) {
 +              int len;
 +
 +              if (!entries[i]->hidden)
 +                      continue;
 +
 +              if (!entries[i]->ssid) {
 +                      ssid = entries[i]->name;
 +                      len = strlen(ssid);
 +              } else {
 +                      ssid = entries[i]->ssid;
 +                      len = entries[i]->ssid_len;
 +              }
 +
 +              if (!ssid)
 +                      continue;
 +
 +              ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
 +              if (ret < 0)
 +                      add_param_failed++;
 +              else if (ret > 0)
 +                      num_ssids++;
 +      }
  
 -      stop_autoscan(device);
 +      connman_config_free_entries(entries);
  
 -      if (wifi->p2p_device)
 -              p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
 -      else
 -              iface_list = g_list_remove(iface_list, wifi);
 +      if (add_param_failed > 0)
 +              DBG("Unable to scan %d out of %d SSIDs",
 +                                      add_param_failed, num_ssids);
  
 -      check_p2p_technology();
 +      g_strfreev(services);
  
 -      remove_pending_wifi_device(wifi);
 +      return num_ssids;
 +}
  
 -      if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
 -              g_source_remove(wifi->p2p_find_timeout);
 -              connman_device_unref(wifi->device);
 +static int get_hidden_connections_params(struct wifi_data *wifi,
 +                                      GSupplicantScanParams *scan_params)
 +{
 +      int driver_max_ssids, i;
 +      GSupplicantScanParams *orig_params;
 +
 +      /*
 +       * Scan hidden networks so that we can autoconnect to them.
 +       * We will assume 1 as a default number of ssid to scan.
 +       */
 +      driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
 +                                                      wifi->interface);
 +      if (driver_max_ssids == 0)
 +              driver_max_ssids = 1;
 +
 +      DBG("max ssids %d", driver_max_ssids);
 +
 +#if defined TIZEN_EXT
 +      if (!wifi->hidden_scan_params) {
 +              wifi->hidden_scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
 +              if (!wifi->hidden_scan_params)
 +                      return 0;
 +
 +              if (get_hidden_connections(wifi->hidden_scan_params) == 0) {
 +                      g_supplicant_free_scan_params(wifi->hidden_scan_params);
 +                      wifi->hidden_scan_params = NULL;
 +
 +                      return 0;
 +              }
        }
  
 -      if (wifi->p2p_connection_timeout)
 -              g_source_remove(wifi->p2p_connection_timeout);
 +      orig_params = wifi->hidden_scan_params;
 +#else
 +      if (!wifi->scan_params) {
 +              wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
 +              if (!wifi->scan_params)
 +                      return 0;
  
 -      remove_networks(device, wifi);
 -      remove_peers(wifi);
 +              if (get_hidden_connections(wifi->scan_params) == 0) {
 +                      g_supplicant_free_scan_params(wifi->scan_params);
 +                      wifi->scan_params = NULL;
  
 -      connman_device_set_powered(device, false);
 -      connman_device_set_data(device, NULL);
 -      connman_device_unref(wifi->device);
 -      connman_rtnl_remove_watch(wifi->watch);
 +                      return 0;
 +              }
 +      }
  
 -      g_supplicant_interface_set_data(wifi->interface, NULL);
 +      orig_params = wifi->scan_params;
 +#endif
  
 -      g_supplicant_interface_cancel(wifi->interface);
 +      /* Let's transfer driver_max_ssids params */
 +      for (i = 0; i < driver_max_ssids; i++) {
 +              struct scan_ssid *ssid;
  
 -      if (wifi->scan_params)
 -              g_supplicant_free_scan_params(wifi->scan_params);
 +#if defined TIZEN_EXT
 +              if (!wifi->hidden_scan_params->ssids)
 +#else
 +              if (!wifi->scan_params->ssids)
 +#endif
 +                      break;
  
 -      g_free(wifi->autoscan);
 -      g_free(wifi->identifier);
 -      g_free(wifi);
 +              ssid = orig_params->ssids->data;
 +              orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
 +              scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
 +      }
 +
 +      if (i > 0) {
 +              scan_params->num_ssids = i;
 +              scan_params->ssids = g_slist_reverse(scan_params->ssids);
 +
-               scan_params->freqs = g_memdup(orig_params->freqs,
-                               sizeof(uint16_t) * orig_params->num_freqs);
-               if (!scan_params->freqs)
++              if (orig_params->num_freqs <= 0)
 +                      goto err;
 +
++              scan_params->freqs =
++                      g_malloc(sizeof(uint16_t) * orig_params->num_freqs);
++              memcpy(scan_params->freqs, orig_params->freqs,
++                      sizeof(uint16_t) *orig_params->num_freqs);
++
 +              scan_params->num_freqs = orig_params->num_freqs;
 +
 +      } else
 +              goto err;
 +
 +      orig_params->num_ssids -= scan_params->num_ssids;
 +
 +      return scan_params->num_ssids;
 +
 +err:
 +      g_slist_free_full(scan_params->ssids, g_free);
 +#if defined TIZEN_EXT
 +      g_supplicant_free_scan_params(wifi->hidden_scan_params);
 +      wifi->hidden_scan_params = NULL;
 +#else
 +      g_supplicant_free_scan_params(wifi->scan_params);
 +      wifi->scan_params = NULL;
 +#endif
 +
 +      return 0;
  }
  
 -static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
 +static int throw_wifi_scan(struct connman_device *device,
 +                      GSupplicantInterfaceCallback callback)
  {
 -      GSList *iter;
 +      struct wifi_data *wifi = connman_device_get_data(device);
 +      int ret;
  
 -      for (iter = list; iter; iter = g_slist_next(iter)) {
 -              struct scan_ssid *scan_ssid = iter->data;
 +      if (!wifi)
 +              return -ENODEV;
  
 -              if (ssid_len == scan_ssid->ssid_len &&
 -                              memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
 -                      return true;
 +      DBG("device %p %p", device, wifi->interface);
 +
 +      if (wifi->tethering)
 +              return -EBUSY;
 +
 +#if defined TIZEN_EXT
 +      if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI)
 +          && !wifi->allow_full_scan)
 +#else
 +      if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI))
 +#endif
 +              return -EALREADY;
 +
 +      connman_device_ref(device);
 +
 +      ret = g_supplicant_interface_scan(wifi->interface, NULL,
 +                                              callback, device);
 +      if (ret == 0) {
 +              connman_device_set_scanning(device,
 +                              CONNMAN_SERVICE_TYPE_WIFI, true);
 +      } else
 +              connman_device_unref(device);
 +
 +      return ret;
 +}
 +
 +static void hidden_free(struct hidden_params *hidden)
 +{
 +      if (!hidden)
 +              return;
 +
 +      if (hidden->scan_params)
 +              g_supplicant_free_scan_params(hidden->scan_params);
 +      g_free(hidden->identity);
 +      g_free(hidden->passphrase);
 +      g_free(hidden->security);
 +      g_free(hidden);
 +}
 +
 +#if defined TIZEN_EXT
 +static void service_state_changed(struct connman_service *service,
 +                                      enum connman_service_state state);
 +
 +static int network_connect(struct connman_network *network);
 +
 +static struct connman_notifier notifier = {
 +      .name                   = "wifi",
 +      .priority               = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
 +      .service_state_changed  = service_state_changed,
 +};
 +
 +static void service_state_changed(struct connman_service *service,
 +                                      enum connman_service_state state)
 +{
 +      enum connman_service_type type;
 +
 +      type = connman_service_get_type(service);
 +      if (type != CONNMAN_SERVICE_TYPE_WIFI)
 +              return;
 +
 +      DBG("service %p state %d", service, state);
 +
 +      switch (state) {
 +      case CONNMAN_SERVICE_STATE_READY:
 +      case CONNMAN_SERVICE_STATE_ONLINE:
 +      case CONNMAN_SERVICE_STATE_FAILURE:
 +              connman_notifier_unregister(&notifier);
 +              is_wifi_notifier_registered = FALSE;
 +
 +              __connman_device_request_scan(type);
 +              break;
 +
 +      default:
 +              break;
        }
 +}
  
 -      return false;
 +static gboolean need_bss_transition(uint16_t freq, int snr, int strength)
 +{
 +      /*
 +       * Since bssid->strength is a positive value,
 +       * it need to be changed to its original value.
 +       */
 +      int signal = strength - 120;
 +
 +      /*
 +       * If the currently connected AP matches the following conditions,
 +       * scan for BSS transition is started.
 +       *   - SNR is less than 20 or RSSI level is less than 3
 +       */
 +      if (snr < 20 && snr != 0)
 +              return TRUE;
 +      else if (freq > 4900 && signal <= RSSI_LEVEL_2_5G)
 +              return TRUE;
 +      else if (freq <= 4900 && signal <= RSSI_LEVEL_2_24G)
 +              return TRUE;
 +
 +      return FALSE;
  }
  
 -static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
 -                      int freq, GSupplicantScanParams *scan_data,
 -                      int driver_max_scan_ssids, char *ssid_name)
 +static gboolean check_bss_condition(uint16_t freq, int snr, uint16_t strength)
  {
 -      unsigned int i;
 -      struct scan_ssid *scan_ssid;
 +      /*
 +       * Since bssid->strength is a positive value,
 +       * it need to be changed to its original value.
 +       */
 +      int signal = strength - 120;
  
 -      if ((driver_max_scan_ssids == 0 ||
 -                      driver_max_scan_ssids > scan_data->num_ssids) &&
 -                      (hex_ssid || raw_ssid)) {
 -              gchar *ssid;
 -              unsigned int j = 0, hex;
 +      /*
 +       * If the AP that matches the following conditions exists in the SCAN result,
 +       * BSS transition is started.
 +       *   - SNR is 25 or more and RSSI level is greater than 3
 +       */
 +      if (snr < 25 && snr != 0)
 +              return FALSE;
  
 -              if (hex_ssid) {
 -                      size_t hex_ssid_len = strlen(hex_ssid);
 +      if (freq > 4900 && signal > RSSI_LEVEL_3_5G)
 +              return TRUE;
 +      else if (freq <= 4900 && signal > RSSI_LEVEL_3_24G)
 +              return TRUE;
  
 -                      ssid = g_try_malloc0(hex_ssid_len / 2);
 -                      if (!ssid)
 -                              return -ENOMEM;
 +      return FALSE;
 +}
  
 -                      for (i = 0; i < hex_ssid_len; i += 2) {
 -                              sscanf(hex_ssid + i, "%02x", &hex);
 -                              ssid[j++] = hex;
 -                      }
 -              } else {
 -                      ssid = raw_ssid;
 -                      j = ssid_len;
 -              }
 +static void scan_callback_hidden(int result,
 +                      GSupplicantInterface *interface, void *user_data);
  
 -              /*
 -               * If we have already added hidden AP to the list,
 -               * then do not do it again. This might happen if you have
 -               * used or are using multiple wifi cards, so in that case
 -               * you might have multiple service files for same AP.
 -               */
 -              if (is_duplicate(scan_data->ssids, ssid, j)) {
 -                      if (hex_ssid)
 -                              g_free(ssid);
 -                      return 0;
 -              }
 +static int network_disconnect(struct connman_network *network);
 +#endif
  
 -              scan_ssid = g_try_new(struct scan_ssid, 1);
 -              if (!scan_ssid) {
 -                      if (hex_ssid)
 -                              g_free(ssid);
 -                      return -ENOMEM;
 +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);
 +      bool scanning;
 +#if defined TIZEN_EXT
 +      bool roaming_needed = false;
 +      bool roaming_ap_found = false;
 +      GSList *list = NULL;
 +      GSList *bssid_list = NULL;
 +      bool favorite_exists = false;
 +      struct connman_network *network = NULL;
 +      struct connman_service *service = NULL;
 +#endif
 +
 +      DBG("result %d wifi %p", result, wifi);
 +
 +      if (wifi) {
 +              if (wifi->hidden && !wifi->postpone_hidden) {
 +                      connman_network_clear_hidden(wifi->hidden->user_data);
 +                      hidden_free(wifi->hidden);
 +                      wifi->hidden = NULL;
                }
  
 -              memcpy(scan_ssid->ssid, ssid, j);
 -              scan_ssid->ssid_len = j;
 -              scan_data->ssids = g_slist_prepend(scan_data->ssids,
 -                                                              scan_ssid);
 +              if (wifi->scan_params) {
 +                      g_supplicant_free_scan_params(wifi->scan_params);
 +                      wifi->scan_params = NULL;
 +              }
  
 -              scan_data->num_ssids++;
 +#if defined TIZEN_EXT
 +              if (wifi->hidden_scan_params && !wifi->hidden_scan_params->ssids) {
 +                      g_supplicant_free_scan_params(wifi->hidden_scan_params);
 +                      wifi->hidden_scan_params = NULL;
 +              }
 +#endif
 +      }
  
 -              DBG("SSID %s added to scanned list of %d entries", ssid_name,
 -                                                      scan_data->num_ssids);
 +      if (result < 0)
 +              connman_device_reset_scanning(device);
  
 -              if (hex_ssid)
 -                      g_free(ssid);
 -      } else
 -              return -EINVAL;
 +      /* User is connecting to a hidden AP, let's wait for finished event */
 +      if (wifi && wifi->hidden && wifi->postpone_hidden) {
 +              GSupplicantScanParams *scan_params;
 +              int ret;
  
 -      scan_data->ssids = g_slist_reverse(scan_data->ssids);
 +              wifi->postpone_hidden = false;
 +              scan_params = wifi->hidden->scan_params;
 +              wifi->hidden->scan_params = NULL;
  
 -      if (!scan_data->freqs) {
 -              scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
 -              if (!scan_data->freqs) {
 -                      g_slist_free_full(scan_data->ssids, g_free);
 -                      return -ENOMEM;
 -              }
 +              reset_autoscan(device);
  
 -              scan_data->num_freqs = 1;
 -              scan_data->freqs[0] = freq;
 -      } else {
 -              bool duplicate = false;
 +              ret = g_supplicant_interface_scan(wifi->interface, scan_params,
 +                                                      scan_callback, device);
 +              if (ret == 0)
 +                      return;
  
 -              /* Don't add duplicate entries */
 -              for (i = 0; i < scan_data->num_freqs; i++) {
 -                      if (scan_data->freqs[i] == freq) {
 -                              duplicate = true;
 +              /* On error, let's recall scan_callback, which will cleanup */
 +              return scan_callback(ret, interface, user_data);
 +      }
 +
 +#if defined TIZEN_EXT
 +      if (wifi) {
 +              for (list = wifi->networks; list; list = list->next) {
 +                      network = list->data;
 +                      service = connman_service_lookup_from_network(network);
 +
 +                      if (service != NULL &&
 +                              (connman_service_get_favorite(service) == true) &&
 +                              (connman_service_get_autoconnect(service) == true)) {
 +                              DBG("Favorite service exists [%s]",
 +                                              connman_network_get_string(network, "Name"));
 +                              favorite_exists = true;
                                break;
                        }
                }
 +      }
  
 -              if (!duplicate) {
 -                      scan_data->num_freqs++;
 -                      scan_data->freqs = g_try_realloc(scan_data->freqs,
 -                              sizeof(uint16_t) * scan_data->num_freqs);
 -                      if (!scan_data->freqs) {
 -                              g_slist_free_full(scan_data->ssids, g_free);
 -                              return -ENOMEM;
 -                      }
 -                      scan_data->freqs[scan_data->num_freqs - 1] = freq;
 +      if (favorite_exists == false) {
 +              if (wifi && wifi->allow_full_scan) {
 +                      int ret;
 +                      DBG("Trigger full channel scan");
 +                      wifi->allow_full_scan = false;
 +
 +                      ret = g_supplicant_interface_scan(wifi->interface, NULL,
 +                                                              scan_callback_hidden, device);
 +                      if (ret == 0)
 +                              return;
 +
 +                      /* On error, let's recall scan_callback, which will cleanup */
 +                      return scan_callback(ret, interface, user_data);
                }
 +      } else
 +              wifi->allow_full_scan = false;
 +#endif
 +
 +      scanning = connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI);
 +
 +      if (scanning) {
 +              connman_device_set_scanning(device,
 +                              CONNMAN_SERVICE_TYPE_WIFI, false);
        }
  
 -      return 1;
 -}
 +      if (result != -ENOLINK)
 +#if defined TIZEN_EXT
 +      if (result != -EIO)
 +#endif
 +              start_autoscan(device);
  
 -static int get_hidden_connections(GSupplicantScanParams *scan_data)
 -{
 -      struct connman_config_entry **entries;
 -      GKeyFile *keyfile;
 -      gchar **services;
 -      char *ssid, *name;
 -      int i, ret;
 -      bool value;
 -      int num_ssids = 0, add_param_failed = 0;
 +      /*
 +       * If we are here then we were scanning; however, if we are
 +       * also mid-flight disabling the interface, then wifi_disable
 +       * has already cleared the device scanning state and
 +       * unreferenced the device, obviating the need to do it here.
 +       */
  
 -      services = connman_storage_get_services();
 -      for (i = 0; services && services[i]; i++) {
 -              if (strncmp(services[i], "wifi_", 5) != 0)
 -                      continue;
 +      if (scanning)
 +              connman_device_unref(device);
  
 -              keyfile = connman_storage_load_service(services[i]);
 -              if (!keyfile)
 -                      continue;
 +#if defined TIZEN_EXT
 +      if (!wifi)
 +              goto done;
  
 -              value = g_key_file_get_boolean(keyfile,
 -                                      services[i], "Hidden", NULL);
 -              if (!value) {
 -                      g_key_file_free(keyfile);
 -                      continue;
 -              }
 +      if (wifi->scan_pending_network && result != -EIO) {
 +              network_connect(wifi->scan_pending_network);
 +              wifi->scan_pending_network = NULL;
 +              connman_network_set_connecting(wifi->network);
 +      } else if (connman_setting_get_bool("WifiRoaming") && wifi->network) {
 +              bssid_list = connman_network_get_bssid_list(wifi->network);
  
 -              value = g_key_file_get_boolean(keyfile,
 -                                      services[i], "Favorite", NULL);
 -              if (!value) {
 -                      g_key_file_free(keyfile);
 -                      continue;
 -              }
 +              if (g_slist_length(bssid_list) <= 1)
 +                      goto done;
  
 -              ssid = g_key_file_get_string(keyfile,
 -                                      services[i], "SSID", NULL);
 +              if (!connman_network_get_connected(wifi->network))
 +                      goto done;
  
 -              name = g_key_file_get_string(keyfile, services[i], "Name",
 -                                                              NULL);
 +              if (connman_network_get_bool(wifi->network, "WiFi.Roaming"))
 +                      goto done;
  
 -              ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
 -              if (ret < 0)
 -                      add_param_failed++;
 -              else if (ret > 0)
 -                      num_ssids++;
 +              if (!need_bss_transition(
 +                              connman_network_get_frequency(wifi->network),
 +                              connman_network_get_snr(wifi->network),
 +                              connman_network_get_strength(wifi->network)))
 +                      goto done;
  
 -              g_free(ssid);
 -              g_free(name);
 -              g_key_file_free(keyfile);
 -      }
 +              for (bssid_list; bssid_list; bssid_list = bssid_list->next) {
 +                      struct g_connman_bssids *bssid = bssid_list->data;
  
 -      /*
 -       * Check if there are any hidden AP that needs to be provisioned.
 -       */
 -      entries = connman_config_get_entries("wifi");
 -      for (i = 0; entries && entries[i]; i++) {
 -              int len;
 +                      if (check_bss_condition(bssid->frequency,
 +                                      bssid->score_snr, bssid->strength))
 +                              roaming_ap_found = true;
 +              }
  
 -              if (!entries[i]->hidden)
 -                      continue;
 +              if (roaming_ap_found) {
 +                      char bssid_buff[WIFI_BSSID_STR_LEN] = {0,};
 +                      char *bssid_str = bssid_buff;
 +                      unsigned char *bssid;
  
 -              if (!entries[i]->ssid) {
 -                      ssid = entries[i]->name;
 -                      len = strlen(ssid);
 -              } else {
 -                      ssid = entries[i]->ssid;
 -                      len = entries[i]->ssid_len;
 +                      bssid = connman_network_get_bssid(wifi->network);
 +                      snprintf(bssid_str, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bssid));
 +                      connman_network_set_string(wifi->network,
 +                                      "WiFi.RoamingCurBSSID", bssid_str);
 +
 +                      network_disconnect(wifi->network);
 +                      wifi->pending_network = wifi->network;
 +                      connman_network_set_bool(wifi->network, "WiFi.Roaming", true);
                }
 +      }
  
 -              if (!ssid)
 -                      continue;
 +done:
 +      if (is_wifi_notifier_registered != true &&
 +                      wifi_first_scan == true && found_with_first_scan == true) {
 +              wifi_first_scan = false;
 +              found_with_first_scan = false;
  
 -              ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
 -              if (ret < 0)
 -                      add_param_failed++;
 -              else if (ret > 0)
 -                      num_ssids++;
 +              connman_notifier_register(&notifier);
 +              is_wifi_notifier_registered = true;
        }
 +#endif
 +}
  
 -      connman_config_free_entries(entries);
 +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);
 +      GSupplicantScanParams *scan_params;
 +      int ret;
  
 -      if (add_param_failed > 0)
 -              DBG("Unable to scan %d out of %d SSIDs",
 -                                      add_param_failed, num_ssids);
 +      DBG("result %d wifi %p", result, wifi);
  
 -      g_strfreev(services);
 +      if (!wifi)
 +              goto out;
  
 -      return num_ssids;
 +      /* User is trying to connect to a hidden AP */
 +      if (wifi->hidden && wifi->postpone_hidden)
 +              goto out;
 +
 +      scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
 +      if (!scan_params)
 +              goto out;
 +
 +      if (get_hidden_connections_params(wifi, scan_params) > 0) {
 +              ret = g_supplicant_interface_scan(wifi->interface,
 +                                                      scan_params,
 +#if defined TIZEN_EXT
 +                                                      scan_callback,
 +#else
 +                                                      scan_callback_hidden,
 +#endif
 +                                                      device);
 +              if (ret == 0)
 +                      return;
 +      }
 +
 +      g_supplicant_free_scan_params(scan_params);
 +
 +out:
 +      scan_callback(result, interface, user_data);
  }
  
 -static int get_hidden_connections_params(struct wifi_data *wifi,
 -                                      GSupplicantScanParams *scan_params)
 +static gboolean autoscan_timeout(gpointer data)
  {
 -      int driver_max_ssids, i;
 -      GSupplicantScanParams *orig_params;
 +      struct connman_device *device = data;
 +      struct wifi_data *wifi = connman_device_get_data(device);
 +      struct autoscan_params *autoscan;
 +      int interval;
  
 -      /*
 -       * Scan hidden networks so that we can autoconnect to them.
 -       * We will assume 1 as a default number of ssid to scan.
 -       */
 -      driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
 -                                                      wifi->interface);
 -      if (driver_max_ssids == 0)
 -              driver_max_ssids = 1;
 +      if (!wifi)
 +              return FALSE;
  
 -      DBG("max ssids %d", driver_max_ssids);
 +      autoscan = wifi->autoscan;
  
 -      if (!wifi->scan_params) {
 -              wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
 -              if (!wifi->scan_params)
 -                      return 0;
 +#if defined TIZEN_EXT
 +      if (!autoscan)
 +              return FALSE;
 +#endif
  
 -              if (get_hidden_connections(wifi->scan_params) == 0) {
 -                      g_supplicant_free_scan_params(wifi->scan_params);
 -                      wifi->scan_params = NULL;
 +      if (autoscan->interval <= 0) {
 +              interval = autoscan->base;
 +              goto set_interval;
 +      } else
 +              interval = autoscan->interval * autoscan->base;
  
 -                      return 0;
 -              }
 -      }
 +#if defined TIZEN_EXT
 +      if (autoscan->interval >= autoscan->limit)
 +#else
 +      if (interval > autoscan->limit)
 +#endif
 +              interval = autoscan->limit;
  
 -      orig_params = wifi->scan_params;
 +      throw_wifi_scan(wifi->device, scan_callback_hidden);
  
 -      /* Let's transfer driver_max_ssids params */
 -      for (i = 0; i < driver_max_ssids; i++) {
 -              struct scan_ssid *ssid;
 +      /*
 +       * In case BackgroundScanning is disabled, interval will reach the
 +       * limit exactly after the very first passive scanning. It allows
 +       * to ensure at most one passive scan is performed in such cases.
 +       */
 +      if (!connman_setting_get_bool("BackgroundScanning") &&
 +                                      interval == autoscan->limit) {
 +              g_source_remove(autoscan->timeout);
 +              autoscan->timeout = 0;
  
 -              if (!wifi->scan_params->ssids)
 -                      break;
 +              connman_device_unref(device);
  
 -              ssid = orig_params->ssids->data;
 -              orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
 -              scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
 +              return FALSE;
        }
  
 -      if (i > 0) {
 -              scan_params->num_ssids = i;
 -              scan_params->ssids = g_slist_reverse(scan_params->ssids);
 +set_interval:
 +      DBG("interval %d", interval);
 +
 +      autoscan->interval = interval;
 +
 +      autoscan->timeout = g_timeout_add_seconds(interval,
 +                                              autoscan_timeout, device);
 +
 +      return FALSE;
 +}
 +
 +static void start_autoscan(struct connman_device *device)
 +{
 +      struct wifi_data *wifi = connman_device_get_data(device);
 +      struct autoscan_params *autoscan;
  
 -              if (orig_params->num_freqs <= 0)
 -                      goto err;
 +      DBG("");
  
 -              scan_params->freqs =
 -                      g_malloc(sizeof(uint16_t) * orig_params->num_freqs);
 -              memcpy(scan_params->freqs, orig_params->freqs,
 -                      sizeof(uint16_t) *orig_params->num_freqs);
 +      if (!wifi)
 +              return;
  
 -              scan_params->num_freqs = orig_params->num_freqs;
 +      if (wifi->p2p_device)
 +              return;
  
 -      } else
 -              goto err;
 +      if (wifi->connected)
 +              return;
  
 -      orig_params->num_ssids -= scan_params->num_ssids;
 +      autoscan = wifi->autoscan;
 +      if (!autoscan)
 +              return;
  
 -      return scan_params->num_ssids;
 +      if (autoscan->timeout > 0 || autoscan->interval > 0)
 +              return;
  
 -err:
 -      g_slist_free_full(scan_params->ssids, g_free);
 -      g_supplicant_free_scan_params(wifi->scan_params);
 -      wifi->scan_params = NULL;
 +      connman_device_ref(device);
  
 -      return 0;
 +      autoscan_timeout(device);
  }
  
 -static int throw_wifi_scan(struct connman_device *device,
 -                      GSupplicantInterfaceCallback callback)
 +static struct autoscan_params *parse_autoscan_params(const char *params)
  {
 -      struct wifi_data *wifi = connman_device_get_data(device);
 -      int ret;
 +      struct autoscan_params *autoscan;
 +      char **list_params;
 +      int limit;
 +      int base;
  
 -      if (!wifi)
 -              return -ENODEV;
 +      DBG("");
  
 -      DBG("device %p %p", device, wifi->interface);
 +      list_params = g_strsplit(params, ":", 0);
 +      if (list_params == 0)
 +              return NULL;
  
 -      if (wifi->tethering)
 -              return -EBUSY;
 +      if (!g_strcmp0(list_params[0], "exponential") &&
 +                              g_strv_length(list_params) == 3) {
 +              base = atoi(list_params[1]);
 +              limit = atoi(list_params[2]);
 +      } else if (!g_strcmp0(list_params[0], "single") &&
 +                              g_strv_length(list_params) == 2)
 +              base = limit = atoi(list_params[1]);
 +      else {
 +              g_strfreev(list_params);
 +              return NULL;
 +      }
  
 -      if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI))
 -              return -EALREADY;
 +      DBG("Setup %s autoscanning", list_params[0]);
  
 -      connman_device_ref(device);
 +      g_strfreev(list_params);
  
 -      ret = g_supplicant_interface_scan(wifi->interface, NULL,
 -                                              callback, device);
 -      if (ret == 0) {
 -              connman_device_set_scanning(device,
 -                              CONNMAN_SERVICE_TYPE_WIFI, true);
 -      } else
 -              connman_device_unref(device);
 +      autoscan = g_try_malloc0(sizeof(struct autoscan_params));
 +      if (!autoscan) {
 +              DBG("Could not allocate memory for autoscan");
 +              return NULL;
 +      }
  
 -      return ret;
 +      DBG("base %d - limit %d", base, limit);
 +      autoscan->base = base;
 +      autoscan->limit = limit;
 +
 +      return autoscan;
  }
  
 -static void hidden_free(struct hidden_params *hidden)
 +static void setup_autoscan(struct wifi_data *wifi)
  {
 -      if (!hidden)
 +      /*
 +       * If BackgroundScanning is enabled, setup exponential
 +       * autoscanning if it has not been previously done.
 +       */
 +      if (connman_setting_get_bool("BackgroundScanning")) {
 +              wifi->autoscan = parse_autoscan_params(AUTOSCAN_EXPONENTIAL);
                return;
 +      }
 +#if defined TIZEN_EXT
 +      else {
 +              if (wifi->autoscan) {
 +                      g_free(wifi->autoscan);
 +                      wifi->autoscan = NULL;
 +              }
  
 -      if (hidden->scan_params)
 -              g_supplicant_free_scan_params(hidden->scan_params);
 -      g_free(hidden->identity);
 -      g_free(hidden->passphrase);
 -      g_free(hidden->security);
 -      g_free(hidden);
 +              DBG("BackgroundScanning is disabled");
 +
 +              return;
 +      }
 +#else
 +
 +      /*
 +       * On the contrary, if BackgroundScanning is disabled, update autoscan
 +       * parameters based on the type of scanning that is being performed.
 +       */
 +      if (wifi->autoscan) {
 +              g_free(wifi->autoscan);
 +              wifi->autoscan = NULL;
 +      }
 +
 +      switch (wifi->scanning_type) {
 +      case WIFI_SCANNING_PASSIVE:
 +              /* Do not setup autoscan. */
 +              break;
 +      case WIFI_SCANNING_ACTIVE:
 +              /* Setup one single passive scan after active. */
 +              wifi->autoscan = parse_autoscan_params(AUTOSCAN_SINGLE);
 +              break;
 +      case WIFI_SCANNING_UNKNOWN:
 +              /* Setup autoscan in this case but we should never fall here. */
 +              wifi->autoscan = parse_autoscan_params(AUTOSCAN_SINGLE);
 +              break;
 +      }
 +#endif
  }
  
 -static void scan_callback(int result, GSupplicantInterface *interface,
 -                                              void *user_data)
 +static void finalize_interface_creation(struct wifi_data *wifi)
  {
 -      struct connman_device *device = user_data;
 -      struct wifi_data *wifi = connman_device_get_data(device);
 -      bool scanning;
 +      DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
  
 -      DBG("result %d wifi %p", result, wifi);
 +      if (!wifi->device) {
 +              connman_error("WiFi device not set");
 +              return;
 +      }
  
 -      if (wifi) {
 -              if (wifi->hidden && !wifi->postpone_hidden) {
 -                      connman_network_clear_hidden(wifi->hidden->user_data);
 -                      hidden_free(wifi->hidden);
 -                      wifi->hidden = NULL;
 -              }
 +      connman_device_set_powered(wifi->device, true);
  
 -              if (wifi->scan_params) {
 -                      g_supplicant_free_scan_params(wifi->scan_params);
 -                      wifi->scan_params = NULL;
 -              }
 -      }
 +      if (wifi->p2p_device)
 +              return;
  
 -      if (result < 0)
 -              connman_device_reset_scanning(device);
 +      if (!wifi->autoscan)
 +              setup_autoscan(wifi);
  
 -      /* User is connecting to a hidden AP, let's wait for finished event */
 -      if (wifi && wifi->hidden && wifi->postpone_hidden) {
 -              GSupplicantScanParams *scan_params;
 -              int ret;
 +      start_autoscan(wifi->device);
 +}
  
 -              wifi->postpone_hidden = false;
 -              scan_params = wifi->hidden->scan_params;
 -              wifi->hidden->scan_params = NULL;
 +static void interface_create_callback(int result,
 +                                      GSupplicantInterface *interface,
 +                                                      void *user_data)
 +{
 +      struct wifi_data *wifi = user_data;
++      char *bgscan_range_max;
++      long value;
  
 -              reset_autoscan(device);
 +      DBG("result %d ifname %s, wifi %p", result,
 +                              g_supplicant_interface_get_ifname(interface),
 +                              wifi);
  
 -              ret = g_supplicant_interface_scan(wifi->interface, scan_params,
 -                                                      scan_callback, device);
 -              if (ret == 0)
 -                      return;
 +      if (result < 0 || !wifi)
 +              return;
  
 -              /* On error, let's recall scan_callback, which will cleanup */
 -              return scan_callback(ret, interface, user_data);
 +      wifi->interface = interface;
 +      g_supplicant_interface_set_data(interface, wifi);
 +
 +      if (g_supplicant_interface_get_ready(interface)) {
 +              wifi->interface_ready = true;
 +              finalize_interface_creation(wifi);
        }
 -      scanning = connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI);
 -      if (scanning) {
 -              connman_device_set_scanning(device,
 -                              CONNMAN_SERVICE_TYPE_WIFI, false);
++      /*
++       * Set the BSS expiration age to match the long scanning
++       * interval to avoid the loss of unconnected networks between
++       * two scans.
++       */
++      bgscan_range_max = strrchr(BGSCAN_DEFAULT, ':');
++      if (!bgscan_range_max || strlen(bgscan_range_max) < 1)
++              return;
++      value = strtol(bgscan_range_max + 1, NULL, 10);
++      if (value <= 0 || errno == ERANGE)
++              return;
++
++      if (g_supplicant_interface_set_bss_expiration_age(interface,
++                                      value + SCAN_MAX_DURATION) < 0) {
++              connman_warn("Failed to set bss expiration age");
+       }
 +}
  
 -      if (result != -ENOLINK)
 -              start_autoscan(device);
 +static int wifi_enable(struct connman_device *device)
 +{
 +      struct wifi_data *wifi = connman_device_get_data(device);
 +      int index;
 +      char *interface;
-       const char *driver = connman_option_get_string("wifi");
++      const char *driver = connman_setting_get_string("wifi");
 +      int ret;
  
 -      /*
 -       * If we are here then we were scanning; however, if we are
 -       * also mid-flight disabling the interface, then wifi_disable
 -       * has already cleared the device scanning state and
 -       * unreferenced the device, obviating the need to do it here.
 -       */
 +      DBG("device %p %p", device, wifi);
  
 -      if (scanning)
 -              connman_device_unref(device);
 +      index = connman_device_get_index(device);
 +      if (!wifi || index < 0)
 +              return -ENODEV;
 +
 +      if (is_p2p_connecting())
 +              return -EINPROGRESS;
 +
 +      interface = connman_inet_ifname(index);
 +      ret = g_supplicant_interface_create(interface, driver, NULL,
 +#ifdef TIZEN_EXT
 +                      connman_device_get_mac_policy(device),
 +                      connman_device_get_preassoc_mac_policy(device),
 +                      connman_device_get_random_mac_lifetime(device),
 +#endif /* TIZEN_EXT */
 +                                              interface_create_callback,
 +                                                      wifi);
 +      g_free(interface);
 +
 +      if (ret < 0)
 +              return ret;
 +
 +      return -EINPROGRESS;
  }
  
 -static void scan_callback_hidden(int result,
 -                      GSupplicantInterface *interface, void *user_data)
 +static int wifi_disable(struct connman_device *device)
  {
 -      struct connman_device *device = user_data;
        struct wifi_data *wifi = connman_device_get_data(device);
 -      GSupplicantScanParams *scan_params;
        int ret;
  
 -      DBG("result %d wifi %p", result, wifi);
 +      DBG("device %p wifi %p", device, wifi);
  
        if (!wifi)
 -              goto out;
 +              return -ENODEV;
  
 -      /* User is trying to connect to a hidden AP */
 -      if (wifi->hidden && wifi->postpone_hidden)
 -              goto out;
 +      wifi->connected = false;
 +      wifi->disconnecting = false;
  
 -      scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
 -      if (!scan_params)
 -              goto out;
 +      if (wifi->pending_network)
 +              wifi->pending_network = NULL;
  
 -      if (get_hidden_connections_params(wifi, scan_params) > 0) {
 -              ret = g_supplicant_interface_scan(wifi->interface,
 -                                                      scan_params,
 -                                                      scan_callback_hidden,
 -                                                      device);
 -              if (ret == 0)
 -                      return;
 -      }
 +#if !defined TIZEN_EXT
 +      stop_autoscan(device);
 +#endif
  
 -      g_supplicant_free_scan_params(scan_params);
 +      if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
 +              g_source_remove(wifi->p2p_find_timeout);
 +              wifi->p2p_find_timeout = 0;
 +              connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
 +              connman_device_unref(wifi->device);
 +      }
  
 -out:
 -      scan_callback(result, interface, user_data);
 -}
 +#if defined TIZEN_EXT
 +      if (wifi->automaxspeed_timeout != 0) {
 +              g_source_remove(wifi->automaxspeed_timeout);
 +              wifi->automaxspeed_timeout = 0;
 +      }
 +#endif
  
 -static gboolean autoscan_timeout(gpointer data)
 -{
 -      struct connman_device *device = data;
 -      struct wifi_data *wifi = connman_device_get_data(device);
 -      struct autoscan_params *autoscan;
 -      int interval;
 +      /* In case of a user scan, device is still referenced */
 +      if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI)) {
 +              connman_device_set_scanning(device,
 +                              CONNMAN_SERVICE_TYPE_WIFI, false);
 +              connman_device_unref(wifi->device);
 +      }
  
 -      if (!wifi)
 -              return FALSE;
 +#if defined TIZEN_EXT
 +      stop_autoscan(device);
 +#endif
  
 -      autoscan = wifi->autoscan;
 +      remove_networks(device, wifi);
 +      remove_peers(wifi);
  
 -      if (autoscan->interval <= 0) {
 -              interval = autoscan->base;
 -              goto set_interval;
 -      } else
 -              interval = autoscan->interval * autoscan->base;
 +#if defined TIZEN_EXT
 +      wifi->scan_pending_network = NULL;
  
 -      if (interval > autoscan->limit)
 -              interval = autoscan->limit;
 +      if (is_wifi_notifier_registered == true) {
 +              connman_notifier_unregister(&notifier);
 +              is_wifi_notifier_registered = false;
 +      }
 +#endif
  
 -      throw_wifi_scan(wifi->device, scan_callback_hidden);
 +      ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
 +      if (ret < 0)
 +              return ret;
  
 -      /*
 -       * In case BackgroundScanning is disabled, interval will reach the
 -       * limit exactly after the very first passive scanning. It allows
 -       * to ensure at most one passive scan is performed in such cases.
 -       */
 -      if (!connman_setting_get_bool("BackgroundScanning") &&
 -                                      interval == autoscan->limit) {
 -              g_source_remove(autoscan->timeout);
 -              autoscan->timeout = 0;
 +      return -EINPROGRESS;
 +}
  
 -              connman_device_unref(device);
 +static int get_latest_connections(int max_ssids,
 +                              GSupplicantScanParams *scan_data)
 +{
 +      GSequenceIter *iter;
 +      GSequence *latest_list;
 +      struct last_connected *entry;
 +      GKeyFile *keyfile;
 +      GTimeVal modified;
 +      gchar **services;
 +      gchar *str;
 +      char *ssid;
 +      int i, freq;
 +      int num_ssids = 0;
  
 -              return FALSE;
 -      }
 +      latest_list = g_sequence_new(free_entry);
 +      if (!latest_list)
 +              return -ENOMEM;
  
 -set_interval:
 -      DBG("interval %d", interval);
 +      services = connman_storage_get_services();
 +      for (i = 0; services && services[i]; i++) {
 +              if (strncmp(services[i], "wifi_", 5) != 0)
 +                      continue;
  
 -      autoscan->interval = interval;
 +              keyfile = connman_storage_load_service(services[i]);
 +              if (!keyfile)
 +                      continue;
  
 -      autoscan->timeout = g_timeout_add_seconds(interval,
 -                                              autoscan_timeout, device);
 +              str = g_key_file_get_string(keyfile,
 +                                      services[i], "Favorite", NULL);
 +              if (!str || g_strcmp0(str, "true")) {
 +                      g_free(str);
 +                      g_key_file_free(keyfile);
 +                      continue;
 +              }
 +              g_free(str);
  
 -      return FALSE;
 -}
 +              str = g_key_file_get_string(keyfile,
 +                                      services[i], "AutoConnect", NULL);
 +              if (!str || g_strcmp0(str, "true")) {
 +                      g_free(str);
 +                      g_key_file_free(keyfile);
 +                      continue;
 +              }
 +              g_free(str);
  
 -static void start_autoscan(struct connman_device *device)
 -{
 -      struct wifi_data *wifi = connman_device_get_data(device);
 -      struct autoscan_params *autoscan;
 +              str = g_key_file_get_string(keyfile,
 +                                      services[i], "Modified", NULL);
 +              if (!str) {
 +                      g_key_file_free(keyfile);
 +                      continue;
 +              }
 +              util_iso8601_to_timeval(str, &modified);
 +              g_free(str);
  
 -      DBG("");
 +              ssid = g_key_file_get_string(keyfile,
 +                                      services[i], "SSID", NULL);
  
 -      if (!wifi)
 -              return;
 +              freq = g_key_file_get_integer(keyfile, services[i],
 +                                      "Frequency", NULL);
 +              if (freq) {
 +                      entry = g_try_new(struct last_connected, 1);
 +                      if (!entry) {
 +                              g_sequence_free(latest_list);
 +                              g_key_file_free(keyfile);
 +                              g_free(ssid);
 +#if defined TIZEN_EXT
 +                              g_strfreev(services);
 +#endif
 +                              return -ENOMEM;
 +                      }
  
 -      if (wifi->p2p_device)
 -              return;
 +                      entry->ssid = ssid;
 +                      entry->modified = modified;
 +                      entry->freq = freq;
  
 -      if (wifi->connected)
 -              return;
 +                      g_sequence_insert_sorted(latest_list, entry,
 +                                              sort_entry, NULL);
 +                      num_ssids++;
 +              } else
 +                      g_free(ssid);
  
 -      autoscan = wifi->autoscan;
 -      if (!autoscan)
 -              return;
 +              g_key_file_free(keyfile);
 +      }
  
 -      if (autoscan->timeout > 0 || autoscan->interval > 0)
 -              return;
 +      g_strfreev(services);
  
 -      connman_device_ref(device);
 +      num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
  
 -      autoscan_timeout(device);
 -}
 +      iter = g_sequence_get_begin_iter(latest_list);
  
 -static struct autoscan_params *parse_autoscan_params(const char *params)
 -{
 -      struct autoscan_params *autoscan;
 -      char **list_params;
 -      int limit;
 -      int base;
 +      for (i = 0; i < num_ssids; i++) {
 +              entry = g_sequence_get(iter);
  
 -      DBG("");
 +              DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
 +                                              entry->modified.tv_sec);
  
 -      list_params = g_strsplit(params, ":", 0);
 -      if (list_params == 0)
 -              return NULL;
 +              add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
 +                                              max_ssids, entry->ssid);
  
 -      if (!g_strcmp0(list_params[0], "exponential") &&
 -                              g_strv_length(list_params) == 3) {
 -              base = atoi(list_params[1]);
 -              limit = atoi(list_params[2]);
 -      } else if (!g_strcmp0(list_params[0], "single") &&
 -                              g_strv_length(list_params) == 2)
 -              base = limit = atoi(list_params[1]);
 -      else {
 -              g_strfreev(list_params);
 -              return NULL;
 +              iter = g_sequence_iter_next(iter);
        }
  
 -      DBG("Setup %s autoscanning", list_params[0]);
 +      g_sequence_free(latest_list);
 +      return num_ssids;
 +}
  
 -      g_strfreev(list_params);
 +static void wifi_update_scanner_type(struct wifi_data *wifi,
 +                                      enum wifi_scanning_type new_type)
 +{
 +      DBG("");
  
 -      autoscan = g_try_malloc0(sizeof(struct autoscan_params));
 -      if (!autoscan) {
 -              DBG("Could not allocate memory for autoscan");
 -              return NULL;
 -      }
 +      if (!wifi || wifi->scanning_type == new_type)
 +              return;
  
 -      DBG("base %d - limit %d", base, limit);
 -      autoscan->base = base;
 -      autoscan->limit = limit;
 +      wifi->scanning_type = new_type;
  
 -      return autoscan;
 +      setup_autoscan(wifi);
  }
  
 -static void setup_autoscan(struct wifi_data *wifi)
 +static int wifi_scan_simple(struct connman_device *device)
  {
 -      /*
 -       * If BackgroundScanning is enabled, setup exponential
 -       * autoscanning if it has not been previously done.
 -       */
 -      if (connman_setting_get_bool("BackgroundScanning")) {
 -              wifi->autoscan = parse_autoscan_params(AUTOSCAN_EXPONENTIAL);
 -              return;
 -      }
 +      struct wifi_data *wifi = connman_device_get_data(device);
  
 -      /*
 -       * On the contrary, if BackgroundScanning is disabled, update autoscan
 -       * parameters based on the type of scanning that is being performed.
 -       */
 -      if (wifi->autoscan) {
 -              g_free(wifi->autoscan);
 -              wifi->autoscan = NULL;
 -      }
 +      reset_autoscan(device);
 +
 +      /* Distinguish between devices performing passive and active scanning */
 +      if (wifi)
 +              wifi_update_scanner_type(wifi, WIFI_SCANNING_PASSIVE);
  
 -      switch (wifi->scanning_type) {
 -      case WIFI_SCANNING_PASSIVE:
 -              /* Do not setup autoscan. */
 -              break;
 -      case WIFI_SCANNING_ACTIVE:
 -              /* Setup one single passive scan after active. */
 -              wifi->autoscan = parse_autoscan_params(AUTOSCAN_SINGLE);
 -              break;
 -      case WIFI_SCANNING_UNKNOWN:
 -              /* Setup autoscan in this case but we should never fall here. */
 -              wifi->autoscan = parse_autoscan_params(AUTOSCAN_SINGLE);
 -              break;
 -      }
 +      return throw_wifi_scan(device, scan_callback_hidden);
  }
  
 -static void finalize_interface_creation(struct wifi_data *wifi)
 +static gboolean p2p_find_stop(gpointer data)
  {
 -      DBG("interface is ready wifi %p tethering %d", wifi, wifi->tethering);
 +      struct connman_device *device = data;
 +      struct wifi_data *wifi = connman_device_get_data(device);
  
 -      if (!wifi->device) {
 -              connman_error("WiFi device not set");
 -              return;
 -      }
 +      DBG("");
  
 -      connman_device_set_powered(wifi->device, true);
 +      if (wifi) {
 +              wifi->p2p_find_timeout = 0;
  
 -      if (wifi->p2p_device)
 -              return;
 +              g_supplicant_interface_p2p_stop_find(wifi->interface);
 +      }
  
 -      if (!wifi->autoscan)
 -              setup_autoscan(wifi);
 +      connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
  
 -      start_autoscan(wifi->device);
 +      connman_device_unref(device);
 +      start_autoscan(device);
 +
 +      return FALSE;
  }
  
 -static void interface_create_callback(int result,
 -                                      GSupplicantInterface *interface,
 +static void p2p_find_callback(int result, GSupplicantInterface *interface,
                                                        void *user_data)
  {
 -      struct wifi_data *wifi = user_data;
 -      char *bgscan_range_max;
 -      long value;
 -
 -      DBG("result %d ifname %s, wifi %p", result,
 -                              g_supplicant_interface_get_ifname(interface),
 -                              wifi);
 +      struct connman_device *device = user_data;
 +      struct wifi_data *wifi = connman_device_get_data(device);
  
 -      if (result < 0 || !wifi)
 -              return;
 +      DBG("result %d wifi %p", result, wifi);
  
 -      wifi->interface = interface;
 -      g_supplicant_interface_set_data(interface, wifi);
 +      if (!wifi)
 +              goto error;
  
 -      if (g_supplicant_interface_get_ready(interface)) {
 -              wifi->interface_ready = true;
 -              finalize_interface_creation(wifi);
 +      if (wifi->p2p_find_timeout) {
 +              g_source_remove(wifi->p2p_find_timeout);
 +              wifi->p2p_find_timeout = 0;
        }
  
 -      /*
 -       * Set the BSS expiration age to match the long scanning
 -       * interval to avoid the loss of unconnected networks between
 -       * two scans.
 -       */
 -      bgscan_range_max = strrchr(BGSCAN_DEFAULT, ':');
 -      if (!bgscan_range_max || strlen(bgscan_range_max) < 1)
 -              return;
 +      if (result)
 +              goto error;
  
 -      value = strtol(bgscan_range_max + 1, NULL, 10);
 -      if (value <= 0 || errno == ERANGE)
 -              return;
 +      wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
 +                                                      p2p_find_stop, device);
 +      if (!wifi->p2p_find_timeout)
 +              goto error;
  
 -      if (g_supplicant_interface_set_bss_expiration_age(interface,
 -                                      value + SCAN_MAX_DURATION) < 0) {
 -              connman_warn("Failed to set bss expiration age");
 -      }
 +      return;
 +error:
 +      p2p_find_stop(device);
  }
  
 -static int wifi_enable(struct connman_device *device)
 +static int p2p_find(struct connman_device *device)
  {
 -      struct wifi_data *wifi = connman_device_get_data(device);
 -      int index;
 -      char *interface;
 -      const char *driver = connman_setting_get_string("wifi");
 +      struct wifi_data *wifi;
        int ret;
  
 -      DBG("device %p %p", device, wifi);
 +      DBG("");
  
 -      index = connman_device_get_index(device);
 -      if (!wifi || index < 0)
 -              return -ENODEV;
 +      if (!p2p_technology)
 +              return -ENOTSUP;
  
 -      if (is_p2p_connecting())
 -              return -EINPROGRESS;
 +      wifi = connman_device_get_data(device);
  
 -      interface = connman_inet_ifname(index);
 -      ret = g_supplicant_interface_create(interface, driver, NULL,
 -                                              interface_create_callback,
 -                                                      wifi);
 -      g_free(interface);
 +      if (g_supplicant_interface_is_p2p_finding(wifi->interface))
 +              return -EALREADY;
  
 -      if (ret < 0)
 -              return ret;
 +      reset_autoscan(device);
 +      connman_device_ref(device);
  
 -      return -EINPROGRESS;
 +      ret = g_supplicant_interface_p2p_find(wifi->interface,
 +                                              p2p_find_callback, device);
 +      if (ret) {
 +              connman_device_unref(device);
 +              start_autoscan(device);
 +      } else {
 +              connman_device_set_scanning(device,
 +                              CONNMAN_SERVICE_TYPE_P2P, true);
 +      }
 +
 +      return ret;
  }
  
 -static int wifi_disable(struct connman_device *device)
 +#if defined TIZEN_EXT
 +static void specific_scan_callback(int result, GSupplicantInterface *interface,
 +                                              void *user_data)
  {
 +      struct connman_device *device = user_data;
        struct wifi_data *wifi = connman_device_get_data(device);
 -      int ret;
 +      bool scanning;
  
 -      DBG("device %p wifi %p", device, wifi);
 +      DBG("result %d wifi %p", result, wifi);
 +
 +      if (wifi && wifi->scan_params) {
 +              g_supplicant_free_scan_params(wifi->scan_params);
 +              wifi->scan_params = NULL;
 +      }
 +
 +      scanning = connman_device_get_scanning(device,
 +                                             CONNMAN_SERVICE_TYPE_WIFI);
 +      if (scanning) {
 +              connman_device_set_scanning(device,
 +                              CONNMAN_SERVICE_TYPE_WIFI, false);
 +              connman_device_unref(device);
 +      }
 +}
 +
 +static int wifi_specific_scan(enum connman_service_type type,
 +                      struct connman_device *device, int scan_type,
 +                      GSList *specific_scan_list, void *user_data)
 +{
 +      GSList *list = NULL;
 +      char *ssid = NULL;
 +      struct wifi_data *wifi = connman_device_get_data(device);
 +      GSupplicantScanParams *scan_params = NULL;
 +      struct scan_ssid *scan_ssid = NULL;
 +      bool scanning;
 +      int ret;
 +      int freq;
 +      int count = 0;
  
        if (!wifi)
                return -ENODEV;
@@@ -3937,50 -2258,35 +3974,63 @@@ static int network_connect(struct connm
  static void disconnect_callback(int result, GSupplicantInterface *interface,
                                                                void *user_data)
  {
 -      struct wifi_data *wifi = dd->wifi;
+       struct disconnect_data *dd = user_data;
+       struct connman_network *network = dd->network;
-       struct connman_network *network = user_data;
 +#if defined TIZEN_EXT
 +      GList *list;
 +      struct wifi_data *wifi;
 +
++      g_free(dd);
 +      DBG("network %p result %d", network, result);
 +
 +      for (list = iface_list; list; list = list->next) {
 +              wifi = list->data;
 +
 +              if (wifi->network == NULL && wifi->disconnecting == true)
 +                      wifi->disconnecting = false;
 +
 +              if (wifi->network == network)
 +                      goto found;
 +      }
 +
 +      /* wifi_data may be invalid because wifi is already disabled */
 +      return;
  
-       struct wifi_data *wifi = user_data;
 +found:
 +#else
++      struct wifi_data *wifi = dd->wifi;
+       g_free(dd);
 +#endif
  
-       DBG("result %d supplicant interface %p wifi %p",
-                       result, interface, wifi);
+       DBG("result %d supplicant interface %p wifi %p networks: current %p "
+               "pending %p disconnected %p", result, interface, wifi,
+               wifi->network, wifi->pending_network, network);
  
        if (result == -ECONNABORTED) {
                DBG("wifi interface no longer available");
                return;
        }
  
-       if (wifi->network && wifi->network != wifi->pending_network)
 +#if defined TIZEN_EXT
 +      if (wifi->network &&
 +                      (wifi->network != wifi->pending_network ||
 +                      connman_network_get_bool(wifi->network, "WiFi.Roaming")))
 +#else
-               connman_network_set_connected(wifi->network, false);
-       wifi->network = NULL;
+       if (g_slist_find(wifi->networks, network))
 +#endif
+               connman_network_set_connected(network, false);
  
        wifi->disconnecting = false;
+       if (network != wifi->network) {
+               if (network == wifi->pending_network)
+                       wifi->pending_network = NULL;
+               DBG("current wifi network has changed since disconnection");
+               return;
+       }
+       wifi->network = NULL;
        wifi->connected = false;
  
        if (wifi->pending_network) {
  static int network_disconnect(struct connman_network *network)
  {
        struct connman_device *device = connman_network_get_device(network);
+       struct disconnect_data *dd;
        struct wifi_data *wifi;
        int err;
 +#if defined TIZEN_EXT
 +      struct connman_service *service;
 +#endif
  
        DBG("network %p", network);
  
@@@ -4354,17 -2447,13 +4406,17 @@@ static bool handle_wps_completion(GSupp
  
                if (!wps_ssid || wps_ssid_len != ssid_len ||
                                memcmp(ssid, wps_ssid, ssid_len) != 0) {
+                       dd = g_malloc0(sizeof(*dd));
+                       dd->wifi = wifi;
+                       dd->network = network;
                        connman_network_set_associating(network, false);
- #if defined TIZEN_EXT
                        g_supplicant_interface_disconnect(wifi->interface,
-                                               disconnect_callback, wifi->network);
+                                               disconnect_callback, dd);
++#if defined TIZEN_EXT
 +                      connman_network_set_bool(network, "WiFi.UseWPS", false);
 +                      connman_network_set_string(network, "WiFi.PinWPS", NULL);
- #else
-                       g_supplicant_interface_disconnect(wifi->interface,
-                                               disconnect_callback, wifi);
 +#endif
                        return false;
                }
  
@@@ -4424,29 -2484,11 +4476,29 @@@ static bool handle_4way_handshake_failu
                                        struct connman_network *network,
                                        struct wifi_data *wifi)
  {
- #if defined TIZEN_EXT
-       const char *security;
        struct connman_service *service;
  
-       struct connman_service *service;
-       if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
++#if defined TIZEN_EXT
++      const char *security;
 +      if (wifi->connected)
 +              return false;
 +
 +      security = connman_network_get_string(network, "WiFi.Security");
 +
 +      if (security && g_str_equal(security, "ieee8021x") == true &&
 +                      wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
 +              wifi->retries = 0;
 +              connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
 +
 +              return false;
 +      }
 +
 +      if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
 +              return false;
 +#else
+       if ((wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE) &&
+                       !((wifi->state == G_SUPPLICANT_STATE_ASSOCIATING) &&
+                               (wifi->assoc_code == ASSOC_STATUS_AUTH_TIMEOUT)))
                return false;
  
        if (wifi->connected)
@@@ -4711,9 -2610,6 +4763,10 @@@ static void interface_state(GSupplicant
  
                /* See table 8-36 Reason codes in IEEE Std 802.11 */
                switch (wifi->disconnect_code) {
++#if defined TIZEN_EXT
 +              case 1: /* Unspecified reason */
 +                      /* Let's assume it's because we got blocked */
++#endif
                case 6: /* Class 2 frame received from nonauthenticated STA */
                        connman_network_set_error(network,
                                                CONNMAN_NETWORK_ERROR_BLOCKED);
@@@ -6404,33 -3602,6 +6457,33 @@@ static int tech_set_regdom(struct connm
        return g_supplicant_set_country(alpha2, regdom_callback, NULL);
  }
  
-       string = connman_option_get_string("INSPreferredFreqBSSID");
 +#if defined TIZEN_EXT && defined TIZEN_EXT_INS
 +static void supp_ins_init(void)
 +{
 +      const char *string;
 +      GSupplicantINSPreferredFreq preferred_freq;
 +
++      string = connman_setting_get_string("INSPreferredFreqBSSID");
 +      if (g_strcmp0(string, "5GHz") == 0)
 +              preferred_freq = G_SUPPLICANT_INS_PREFERRED_FREQ_5GHZ;
 +      else if (g_strcmp0(string, "2.4GHz") == 0)
 +              preferred_freq = G_SUPPLICANT_INS_PREFERRED_FREQ_24GHZ;
 +      else
 +              preferred_freq = G_SUPPLICANT_INS_PREFERRED_FREQ_UNKNOWN;
 +
 +      g_supplicant_set_ins_settings(preferred_freq,
 +              connman_setting_get_bool("INSLastConnectedBSSID"),
 +              connman_setting_get_bool("INSAssocReject"),
 +              connman_setting_get_bool("INSSignalBSSID"),
 +              connman_setting_get_uint("INSPreferredFreqBSSIDScore"),
 +              connman_setting_get_uint("INSLastConnectedBSSIDScore"),
 +              connman_setting_get_uint("INSAssocRejectScore"),
 +              connman_setting_get_int("INSSignalLevel3_5GHz"),
 +              connman_setting_get_int("INSSignalLevel3_24GHz")
 +      );
 +}
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
 +
  static struct connman_technology_driver tech_driver = {
        .name           = "wifi",
        .type           = CONNMAN_SERVICE_TYPE_WIFI,
diff --cc src/bridge.c
index cd2d9ce,df19a6a..df19a6a
mode 100755,100644..100755
diff --cc src/clock.c
index 40729b2,906538a..58a52c0
mode 100755,100644..100755
@@@ -176,11 -173,9 +176,12 @@@ static DBusMessage *get_properties(DBus
  {
        DBusMessage *reply;
        DBusMessageIter array, dict;
+       dbus_bool_t is_synced;
        struct timeval tv;
        const char *str;
 +#if defined TIZEN_EXT
 +      dbus_bool_t val = time_updated;
 +#endif
  
        DBG("conn %p", conn);
  
index 6036db3,9d2c696..33f6103
mode 100755,100644..100755
diff --cc src/connman.h
index e92f2b1,6817608..18c4fe0
mode 100755,100644..100755
@@@ -822,20 -748,8 +833,19 @@@ int __connman_service_indicate_default(
  int __connman_service_connect(struct connman_service *service,
                        enum connman_service_connect_reason reason);
  int __connman_service_disconnect(struct connman_service *service);
- int __connman_service_disconnect_all(void);
  void __connman_service_set_active_session(bool enable, GSList *list);
  void __connman_service_auto_connect(enum connman_service_connect_reason reason);
 +
 +#if defined TIZEN_EXT
 +bool __connman_service_get_auto_connect_mode(void);
 +void __connman_service_set_auto_connect_mode(bool enable);
 +#endif
 +
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +int __connman_service_get_use_eapol(struct connman_service *service);
 +int __connman_service_get_connect_reason(struct connman_service *service);
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
  bool __connman_service_remove(struct connman_service *service);
  bool __connman_service_is_provider_pending(struct connman_service *service);
  void __connman_service_set_provider_pending(struct connman_service *service,
diff --cc src/dbus.c
index d80a46c,c454a58..c454a58
mode 100755,100644..100755
diff --cc src/device.c
index 0c3eea9,264c5e2..5116900
mode 100755,100644..100755
@@@ -232,16 -180,6 +232,14 @@@ static gboolean device_pending_reset(gp
  
        DBG("device %p", device);
  
-       DBusMessage *reply;
 +#if defined TIZEN_EXT
 +      /* Power request timed out, send ETIMEDOUT. */
 +      if (device->pending_reply_list) {
 +              g_list_foreach(device->pending_reply_list, __device_pending_reset, NULL);
 +              g_list_free(device->pending_reply_list);
 +              device->pending_reply_list = NULL;
 +      }
 +#endif
        /* Power request timedout, reset power pending state. */
        device->pending_timeout = 0;
        device->powered_pending = PENDING_NONE;
diff --cc src/dhcp.c
Simple merge
diff --cc src/dhcpv6.c
index 4c07c76,8b68359..ba54b89
mode 100755,100644..100755
diff --cc src/dnsproxy.c
index 7956e7f,38dbdd7..18dc648
mode 100755,100644..100755
diff --cc src/inet.c
@@@ -189,78 -196,41 +196,113 @@@ done
        return err;
  }
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +char *connman_inet_ifaddr(const char *name)
 +{
 +      struct ifreq ifr;
 +      struct ether_addr eth;
 +      char *str;
 +      int sk, err;
 +
 +      sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
 +      if (sk < 0)
 +              return NULL;
 +
 +      strncpy(ifr.ifr_name, name, IFNAMSIZ-1);
 +
 +      err = ioctl(sk, SIOCGIFHWADDR, &ifr);
 +      close(sk);
 +
 +      if (err < 0)
 +              return NULL;
 +
 +      str = g_malloc(18);
 +      if (!str)
 +              return NULL;
 +
 +      memcpy(&eth, &ifr.ifr_hwaddr.sa_data, sizeof(eth));
 +      snprintf(str, 13, "%02x%02x%02x%02x%02x%02x",
 +                                              eth.ether_addr_octet[0],
 +                                              eth.ether_addr_octet[1],
 +                                              eth.ether_addr_octet[2],
 +                                              eth.ether_addr_octet[3],
 +                                              eth.ether_addr_octet[4],
 +                                              eth.ether_addr_octet[5]);
 +
 +      return str;
 +}
 +
 +char *connman_inet_ifname2addr(const char *name)
 +{
 +      struct ifreq ifr;
 +      struct ether_addr eth;
 +      char *str;
 +      int sk, err;
 +
 +      sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
 +      if (sk < 0)
 +              return NULL;
 +
 +      strncpy(ifr.ifr_name, name, IFNAMSIZ-1);
 +
 +      err = ioctl(sk, SIOCGIFHWADDR, &ifr);
 +      close(sk);
 +
 +      if (err < 0)
 +              return NULL;
 +
 +      str = g_malloc(18);
 +      if (!str)
 +              return NULL;
 +
 +      memcpy(&eth, &ifr.ifr_hwaddr.sa_data, sizeof(eth));
 +      snprintf(str, 18, "%02x:%02x:%02x:%02x:%02x:%02x",
 +                                              eth.ether_addr_octet[0],
 +                                              eth.ether_addr_octet[1],
 +                                              eth.ether_addr_octet[2],
 +                                              eth.ether_addr_octet[3],
 +                                              eth.ether_addr_octet[4],
 +                                              eth.ether_addr_octet[5]);
 +
 +      return str;
 +}
 +#endif
 +
+ static bool is_addr_unspec(int family, struct sockaddr *addr)
+ {
+       struct sockaddr_in *in4;
+       struct sockaddr_in6 *in6;
+       switch (family) {
+       case AF_INET:
+               in4 = (struct sockaddr_in*) addr;
+               return in4->sin_addr.s_addr == INADDR_ANY;
+       case AF_INET6:
+               in6 = (struct sockaddr_in6*) addr;
+               return IN6_IS_ADDR_UNSPECIFIED(&in6->sin6_addr);
+       default:
+               return false;
+       }
+ }
+ static bool is_addr_ll(int family, struct sockaddr *addr)
+ {
+       struct sockaddr_in *in4;
+       struct sockaddr_in6 *in6;
+       switch (family) {
+       case AF_INET:
+               in4 = (struct sockaddr_in*) addr;
+               return (in4->sin_addr.s_addr & IN_CLASSB_NET) ==
+                                       ((in_addr_t) htonl(0xa9fe0000));
+       case AF_INET6:
+               in6 = (struct sockaddr_in6*) addr;
+               return IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr);
+       default:
+               return false;
+       }
+ }
  bool __connman_inet_is_any_addr(const char *address, int family)
  {
        bool ret = false;
diff --cc src/ipaddress.c
index d63d95c,201d834..201d834
mode 100755,100644..100755
diff --cc src/ipconfig.c
index 7d4be73,1551826..4a0e4ad
mode 100755,100644..100755
@@@ -1288,9 -1299,9 +1333,12 @@@ struct connman_ipconfig *__connman_ipco
        }
  
        ipconfig->system = connman_ipaddress_alloc(AF_INET);
+       ipconfig_set_p2p(index, ipconfig);
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        DBG("ipconfig %p index %d", ipconfig, index);
  
        return ipconfig;
diff --cc src/iptables.c
index 2ee9485,664b27f..90a296e
mode 100755,100644..100755
@@@ -3399,9 -3383,9 +3399,9 @@@ static int parse_rule_spec(struct connm
                                        break;
  
                                if (invert)
-                                       ctx->ip->invflags |= IP6T_INV_DSTIP;
+                                       ctx->ipv6->invflags |= IP6T_INV_DSTIP;
                        }
 -                      
 +
                        break;
                case 'i':
                        /* In interface specification */
diff --cc src/main.c
index 772f7b8,6480caa..13e26d4
mode 100755,100644..100755
  #define DEFAULT_INPUT_REQUEST_TIMEOUT (120 * 1000)
  #define DEFAULT_BROWSER_LAUNCH_TIMEOUT (300 * 1000)
  
+ /*
+  * We set the integer to 1 sec so that we have a chance to get
+  * necessary IPv6 router advertisement messages that might have
+  * DNS data etc.
+  */
+ #define DEFAULT_ONLINE_CHECK_INITIAL_INTERVAL 1
+ #define DEFAULT_ONLINE_CHECK_MAX_INTERVAL 12
 +#if defined TIZEN_EXT
 +#define DEFAULT_WIFI_INTERFACE "wlan0"
 +#define CONTAINER_FILE "/run/systemd/container"
 +#endif
 +
  #define MAINFILE "main.conf"
  #define CONFIGMAINFILE CONFIGDIR "/" MAINFILE
  
@@@ -1187,103 -753,20 +1245,108 @@@ bool connman_setting_get_bool(const cha
        if (g_str_equal(key, CONF_USE_GATEWAYS_AS_TIMESERVERS))
                return connman_settings.use_gateways_as_timeservers;
  
- #endif
 +#if defined TIZEN_EXT
 +      if (g_str_equal(key, CONF_ENABLE_AUTO_IP))
 +              return connman_settings.auto_ip;
 +
 +      if (g_str_equal(key, CONF_CONNMAN_SUPPLICANT_DEBUG))
 +              return connman_settings.supplicant_debug;
 +
 +      if (g_str_equal(key, CONF_CONNMAN_FILE_LOG))
 +              return connman_settings.file_log;
 +
 +      if (g_str_equal(key, CONF_CONNMAN_DLOG_LOG))
 +              return connman_settings.dlog_log;
 +
 +      if (g_str_equal(key, CONF_CONNMAN_SIMPLIFIED_LOG))
 +              return connman_settings.simple_log;
 +
 +      if (g_str_equal(key, CONF_CONNMAN_WIFI_ROAM_SCAN))
 +              return connman_settings.wifi_roam_scan;
 +
 +      if (g_str_equal(key, CONF_CONNMAN_WIFI_ROAM))
 +              return connman_settings.wifi_roam;
- #if defined TIZEN_EXT
 +
 +      if (g_str_equal(key, CONF_INS_LAST_CONNECTED_BSSID))
 +              return connman_ins_settings.ins_last_connected_bssid;
 +
 +      if (g_str_equal(key, CONF_INS_ASSOC_REJECT))
 +              return connman_ins_settings.ins_assoc_reject;
 +
 +      if (g_str_equal(key, CONF_INS_SIGNAL_BSSID))
 +              return connman_ins_settings.ins_signal_bssid;
 +
 +      if (g_str_equal(key, CONF_INS_LAST_USER_SELECTION))
 +              return connman_ins_settings.ins_last_user_selection;
 +
 +      if (g_str_equal(key, CONF_INS_LAST_CONNECTED))
 +              return connman_ins_settings.ins_last_connected;
 +
 +      if (g_str_equal(key, CONF_INS_SIGNAL))
 +              return connman_ins_settings.ins_signal;
 +
 +      if (g_str_equal(key, CONF_INS_INTERNET))
 +              return connman_ins_settings.ins_internet;
 +#endif
 +
        return false;
  }
  
- #if defined TIZEN_EXT
  unsigned int connman_setting_get_uint(const char *key)
  {
+       if (g_str_equal(key, CONF_ONLINE_CHECK_INITIAL_INTERVAL))
+               return connman_settings.online_check_initial_interval;
+       if (g_str_equal(key, CONF_ONLINE_CHECK_MAX_INTERVAL))
+               return connman_settings.online_check_max_interval;
++#if defined TIZEN_EXT
 +      if (g_str_equal(key, CONF_INS_PREFERRED_FREQ_BSSID_SCORE))
 +              return connman_ins_settings.ins_preferred_freq_bssid_score;
 +
 +      if (g_str_equal(key, CONF_INS_LAST_CONNECTED_BSSID_SCORE))
 +              return connman_ins_settings.ins_last_connected_bssid_score;
 +
 +      if (g_str_equal(key, CONF_INS_ASSOC_REJECT_SCORE))
 +              return connman_ins_settings.ins_assoc_reject_score;
 +
 +      if (g_str_equal(key, CONF_INS_LAST_USER_SELECTION_TIME))
 +              return connman_ins_settings.ins_last_user_selection_time;
 +
 +      if (g_str_equal(key, CONF_INS_SECURITY_PRIORITY_COUNT))
 +              return connman_ins_settings.ins_security_priority_count;
 +
 +      if (g_str_equal(key, CONF_INS_LAST_USER_SELECTION_SCORE))
 +              return connman_ins_settings.ins_last_user_selection_score;
 +
 +      if (g_str_equal(key, CONF_INS_LAST_CONNECTED_SCORE))
 +              return connman_ins_settings.ins_last_connected_score;
 +
 +      if (g_str_equal(key, CONF_INS_PREFERRED_FREQ_SCORE))
 +              return connman_ins_settings.ins_preferred_freq_score;
 +
 +      if (g_str_equal(key, CONF_INS_SECURITY_PRIORITY_SCORE))
 +              return connman_ins_settings.ins_security_priority_score;
 +
 +      if (g_str_equal(key, CONF_INS_INTERNET_SCORE))
 +              return connman_ins_settings.ins_internet_score;
++#endif
        return 0;
  }
  
++#if defined TIZEN_EXT
 +int connman_setting_get_int(const char *key)
 +{
 +      if (g_str_equal(key, CONF_INS_SIGNAL_LEVEL3_5GHZ))
 +              return connman_ins_settings.ins_signal_level3_5ghz;
 +
 +      if (g_str_equal(key, CONF_INS_SIGNAL_LEVEL3_24GHZ))
 +              return connman_ins_settings.ins_signal_level3_24ghz;
 +
 +      return 0;
 +}
 +#endif
 +
  char **connman_setting_get_string_list(const char *key)
  {
        if (g_str_equal(key, CONF_PREF_TIMESERVERS))
@@@ -1544,14 -988,8 +1607,15 @@@ int main(int argc, char *argv[]
        g_strfreev(connman_settings.fallback_nameservers);
        g_strfreev(connman_settings.blacklisted_interfaces);
        g_strfreev(connman_settings.tethering_technologies);
+       g_free(connman_settings.vendor_class_id);
  
 +#if defined TIZEN_EXT
 +      g_free(connman_ins_settings.ins_preferred_freq_bssid);
 +      g_free(connman_ins_settings.ins_preferred_freq);
 +      if (connman_ins_settings.ins_security_priority)
 +              g_strfreev(connman_ins_settings.ins_security_priority);
 +#endif
 +
        g_free(option_debug);
        g_free(option_wifi);
  
diff --cc src/main.conf
index f761da7,df70e17..e734ecf
mode 100755,100644..100755
diff --cc src/manager.c
index 4f8306a,3bf8f4e..0000f78
mode 100755,100644..100755
@@@ -216,80 -195,6 +216,80 @@@ static DBusMessage *get_services(DBusCo
        return reply;
  }
  
-       const char *default_interface = connman_option_get_string("DefaultWifiInterface");
 +#if defined TIZEN_EXT
 +static DBusMessage *get_interfaces(DBusConnection *conn, DBusMessage *msg, void *data)
 +{
 +      DBusMessage *reply;
 +      DBusMessageIter iter, array;
++      const char *default_interface = connman_setting_get_string("DefaultWifiInterface");
 +
 +      DBG("DefaultWifiInterface %s", default_interface);
 +
 +      reply = dbus_message_new_method_return(msg);
 +      if (!reply)
 +              return NULL;
 +
 +      dbus_message_iter_init_append(reply, &iter);
 +      dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
 +                                      DBUS_TYPE_STRING_AS_STRING, &array);
 +
 +      dbus_message_iter_append_basic(&array,
 +                              DBUS_TYPE_STRING, &default_interface);
 +
 +      __connman_technology_append_interfaces(&array,
 +                      CONNMAN_SERVICE_TYPE_WIFI, default_interface);
 +
 +      dbus_message_iter_close_container(&iter, &array);
 +      return reply;
 +}
 +
 +static DBusMessage *get_default_service(DBusConnection *conn,
 +                                      DBusMessage *msg, void *data)
 +{
 +      struct connman_service *service = connman_service_get_default_connection();
 +      DBG("service %p", service);
 +
 +      return connman_service_create_dbus_service_reply(msg, service);
 +}
 +
 +static DBusMessage *get_connected_service(DBusConnection *conn,
 +                                      DBusMessage *msg, void *data)
 +{
 +      const char *ifname;
 +      struct connman_service *service;
 +
 +      dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &ifname,
 +                                                      DBUS_TYPE_INVALID);
 +
 +      service = connman_service_get_connected_service(ifname);
 +      DBG("Interface Name %s, service %p", ifname, service);
 +
 +      return connman_service_create_dbus_service_reply(msg, service);
 +}
 +#endif
 +
 +#if defined TIZEN_EXT_INS
 +static void append_ins_structs(DBusMessageIter *iter, void *user_data)
 +{
 +      __connman_ins_list_struct(iter);
 +}
 +
 +static DBusMessage *get_ins(DBusConnection *conn,
 +                                      DBusMessage *msg, void *data)
 +{
 +      DBusMessage *reply;
 +
 +      reply = dbus_message_new_method_return(msg);
 +      if (!reply)
 +              return NULL;
 +
 +      __connman_dbus_append_objpath_dict_array(reply,
 +                      append_ins_structs, NULL);
 +
 +      return reply;
 +}
 +#endif
 +
  static void append_peer_structs(DBusMessageIter *iter, void *user_data)
  {
        __connman_peer_list_struct(iter);
diff --cc src/network.c
index 6849c1b,b12bbc0..7046137
mode 100755,100644..100755
@@@ -3135,13 -2351,8 +3150,14 @@@ const void *connman_network_get_blob(st
                if (size)
                        *size = network->wifi.ssid_len;
                return network->wifi.ssid;
 +#ifdef TIZEN_EXT
 +      } else if (g_str_equal(key, "WiFi.TRANSITION_MODE_SSID")) {
 +              if (size)
 +                      *size = network->wifi.transition_mode_ssid_len;
 +              return network->wifi.transition_mode_ssid;
 +#endif
        }
        return NULL;
  }
  
diff --cc src/peer.c
index 2102f11,bad5c84..bad5c84
mode 100755,100644..100755
diff --cc src/provider.c
index c437c91,e209184..195ae22
mode 100755,100644..100755
diff --cc src/rtnl.c
Simple merge
diff --cc src/service.c
index 19056a8,20917a8..411b617
mode 100755,100644..100755
@@@ -66,48 -54,10 +66,51 @@@ static unsigned int autoconnect_id = 0
  static unsigned int vpn_autoconnect_id = 0;
  static struct connman_service *current_default = NULL;
  static bool services_dirty = false;
+ static bool enable_online_to_ready_transition = false;
+ static unsigned int online_check_initial_interval = 0;
+ static unsigned int online_check_max_interval = 0;
  
 +#if defined TIZEN_EXT
 +static bool auto_connect_mode = TRUE;
 +
 +struct saved_profiles {
 +      GTimeVal modified;
 +      gchar *profile_name;
 +};
 +
 +static unsigned char invalid_bssid[WIFI_BSSID_LEN_MAX] = {
 +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 +};
 +#endif
 +
 +#if defined TIZEN_EXT && defined TIZEN_EXT_INS
 +enum connman_ins_preferred_freq {
 +      CONNMAN_INS_PREFERRED_FREQ_UNKNOWN,
 +      CONNMAN_INS_PREFERRED_FREQ_24GHZ,
 +      CONNMAN_INS_PREFERRED_FREQ_5GHZ,
 +};
 +
 +struct connman_ins_settings {
 +      bool last_user_selection;
 +      unsigned int last_user_selection_time;
 +      unsigned int last_user_selection_score;
 +      bool last_connected;
 +      unsigned int last_connected_score;
 +      enum connman_ins_preferred_freq preferred_freq;
 +      unsigned int preferred_freq_score;
 +      unsigned int security_priority[CONNMAN_SERVICE_SECURITY_MAX];
 +      unsigned int security_priority_count;
 +      unsigned int security_priority_score;
 +      bool signal;
 +      bool internet;
 +      unsigned int internet_score;
 +      int signal_level3_5ghz;
 +      int signal_level3_24ghz;
 +};
 +
 +static struct connman_ins_settings ins_settings;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
 +
  struct connman_stats {
        bool valid;
        bool enabled;
@@@ -557,34 -372,26 +562,53 @@@ static enum connman_service_proxy_metho
                return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
  }
  
- static void set_split_routing(struct connman_service *service, bool value)
 +#ifdef TIZEN_EXT
 +static const char *__connman_dnsconfig_method2string(enum connman_dnsconfig_method method)
 +{
 +      switch (method) {
 +      case CONNMAN_DNSCONFIG_METHOD_UNKNOWN:
 +              return "unknown";
 +      case CONNMAN_DNSCONFIG_METHOD_MANUAL:
 +              return "manual";
 +      case CONNMAN_DNSCONFIG_METHOD_DHCP:
 +              return "dhcp";
 +      }
 +
 +      return NULL;
 +}
 +
 +static enum connman_dnsconfig_method __connman_dnsconfig_string2method(
 +              const char *method)
 +{
 +      if (g_strcmp0(method, "manual") == 0)
 +              return CONNMAN_DNSCONFIG_METHOD_MANUAL;
 +      else if (g_strcmp0(method, "dhcp") == 0)
 +              return CONNMAN_DNSCONFIG_METHOD_DHCP;
 +      else
 +              return CONNMAN_DNSCONFIG_METHOD_UNKNOWN;
 +}
 +#endif
 +
+ void __connman_service_split_routing_changed(struct connman_service *service)
+ {
+       dbus_bool_t split_routing;
+       if (!service->path)
+               return;
+       if (!allow_property_changed(service))
+               return;
+       split_routing = service->do_split_routing;
+       if (!connman_dbus_property_changed_basic(service->path,
+                               CONNMAN_SERVICE_INTERFACE, "SplitRouting",
+                                       DBUS_TYPE_BOOLEAN, &split_routing))
+               connman_warn("cannot send SplitRouting property change on %s",
+                                       service->identifier);
+ }
+ void __connman_service_set_split_routing(struct connman_service *service,
+                                                               bool value)
  {
        if (service->type != CONNMAN_SERVICE_TYPE_VPN)
                return;
@@@ -615,14 -428,12 +645,15 @@@ int __connman_service_load_modifiable(s
        case CONNMAN_SERVICE_TYPE_SYSTEM:
        case CONNMAN_SERVICE_TYPE_GPS:
        case CONNMAN_SERVICE_TYPE_P2P:
 +#if defined TIZEN_EXT_WIFI_MESH
 +      case CONNMAN_SERVICE_TYPE_MESH:
 +#endif
                break;
        case CONNMAN_SERVICE_TYPE_VPN:
-               set_split_routing(service, g_key_file_get_boolean(keyfile,
-                                                       service->identifier,
-                                                       "SplitRouting", NULL));
+               __connman_service_set_split_routing(service,
+                                               g_key_file_get_boolean(keyfile,
+                                               service->identifier,
+                                               "SplitRouting", NULL));
  
                /* fall through */
        case CONNMAN_SERVICE_TYPE_WIFI:
@@@ -1058,14 -485,12 +1089,15 @@@ static int service_load(struct connman_
        case CONNMAN_SERVICE_TYPE_SYSTEM:
        case CONNMAN_SERVICE_TYPE_GPS:
        case CONNMAN_SERVICE_TYPE_P2P:
 +#if defined TIZEN_EXT_WIFI_MESH
 +      case CONNMAN_SERVICE_TYPE_MESH:
 +#endif
                break;
        case CONNMAN_SERVICE_TYPE_VPN:
-               set_split_routing(service, g_key_file_get_boolean(keyfile,
-                                                       service->identifier,
-                                                       "SplitRouting", NULL));
+               __connman_service_set_split_routing(service,
+                                               g_key_file_get_boolean(keyfile,
+                                               service->identifier,
+                                               "SplitRouting", NULL));
  
                autoconnect = g_key_file_get_boolean(keyfile,
                                service->identifier, "AutoConnect", &error);
@@@ -2266,12 -1118,6 +2302,12 @@@ static int nameserver_add_all(struct co
        if (!i)
                __connman_resolver_append_fallback_nameservers();
  
-       const char *global_dns = connman_option_get_string("GlobalNameserver");
 +#if defined TIZEN_EXT
++      const char *global_dns = connman_setting_get_string("GlobalNameserver");
 +      if (global_dns)
 +              nameserver_add(service, type, global_dns);
 +#endif
 +
        searchdomain_add_all(service);
  
        return 0;
@@@ -2441,11 -1165,6 +2477,11 @@@ static int nameserver_remove_all(struc
                i++;
        }
  
-       const char *global_dns = connman_option_get_string("GlobalNameserver");
 +#if defined TIZEN_EXT
++      const char *global_dns = connman_setting_get_string("GlobalNameserver");
 +      if (global_dns)
 +              nameserver_remove(service, type, global_dns);
 +#endif
        searchdomain_remove_all(service);
  
        return 0;
@@@ -6511,6 -4171,6 +6568,7 @@@ static void set_always_connecting_techn
                always_connect[always_connected_techs[i]] = 1;
  }
  
++#if !defined TIZEN_EXT
  static bool autoconnect_no_session_active(struct connman_service *service)
  {
        /*
  
        return false;
  }
++#endif
  
  static bool autoconnect_already_connecting(struct connman_service *service,
                                           bool autoconnecting)
@@@ -6580,20 -4224,12 +6639,26 @@@ static bool auto_connect_service(GList 
                        continue;
                }
  
 +#if defined TIZEN_EXT
 +              DBG("service %p %s %s %s, favorite(%d), ignore(%d), hidden(%d, %d)",
 +                              service, service->name,
 +                              state2string(service->state),
 +                              __connman_service_type2string(service->type),
 +                              service->favorite, is_ignore(service),
 +                              service->hidden, service->hidden_service);
 +
 +              /* Tizen takes Wi-Fi as the highest priority into consideration. */
 +              if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
 +                      if (is_connecting(service->state) == TRUE || is_connected(service->state) == TRUE)
 +                              continue;
 +#endif
 +
+               if (service->connect_reason ==
+                               CONNMAN_SERVICE_CONNECT_REASON_NATIVE) {
+                       DBG("service %p uses native autonnect, skip", service);
+                       continue;
+               }
                if (service->pending ||
                                is_connecting(service->state) ||
                                is_connected(service->state)) {
@@@ -7018,12 -4558,8 +7083,12 @@@ static DBusMessage *connect_service(DBu
        for (list = service_list; list; list = list->next) {
                struct connman_service *temp = list->data;
  
 +#if defined TIZEN_EXT
 +              if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
 +                      break;
 +#endif
                if (!is_connecting(temp->state) && !is_connected(temp->state))
-                       break;
+                       continue;
  
                if (service == temp)
                        continue;
@@@ -7796,23 -5194,6 +7889,22 @@@ static void service_initialize(struct c
  
        service->wps = false;
        service->wps_advertizing = false;
- #endif
- #if defined TIZEN_EXT
 +#if defined TIZEN_EXT
 +      memset(service->last_connected_bssid, 0, WIFI_BSSID_LEN_MAX);
 +      service->is_internet_connection = false;
 +      service->assoc_reject_count = 0;
++
 +      service->disconnection_requested = false;
 +      service->storage_reload = false;
 +      /*
 +       * Description: TIZEN implements system global connection management.
 +       */
 +      service->user_pdn_connection_refcount = 0;
 +      __sync_synchronize();
 +#endif
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      service->use_eapol = false;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
  }
  
  /**
@@@ -7901,186 -5282,40 +7993,220 @@@ void connman_service_unref_debug(struc
        g_hash_table_remove(service_hash, service->identifier);
  }
  
 +#if defined TIZEN_EXT && defined TIZEN_EXT_INS
 +static int calculate_score_last_user_selection(struct connman_service *service)
 +{
 +      int score = 0;
 +      struct connman_device *device;
 +      const char *last_user_selection_ident;
 +      time_t last_user_selection_time;
 +      unsigned int frequency;
 +      time_t curr_time;
 +      time_t ref_time;
 +      struct tm* ref_timeinfo;
 +
 +      device = connman_network_get_device(service->network);
 +      if (!device)
 +              return 0;
 +
 +      last_user_selection_time = connman_device_get_last_user_selection_time(device);
 +      last_user_selection_ident = connman_device_get_last_user_selection_ident(device);
 +      frequency = connman_network_get_frequency(service->network);
 +
 +      if (ins_settings.last_user_selection) {
 +              if (g_strcmp0(last_user_selection_ident, service->identifier) == 0 &&
 +                      (((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
 +                      frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
 +                      service->strength >= ins_settings.signal_level3_24ghz) ||
 +                      ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
 +                      frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
 +                      service->strength >= ins_settings.signal_level3_5ghz))) {
 +
 +                      /* Only events that occur within 8 hours are counted. */
 +                      curr_time = time(NULL);
 +                      ref_timeinfo = localtime(&curr_time);
 +                      ref_timeinfo->tm_hour -= 8;
 +                      ref_time = mktime(ref_timeinfo);
 +
 +                      if (last_user_selection_time > ref_time) {
 +                              int time_diff = (curr_time - last_user_selection_time) / 60;
 +                              int denominator = ins_settings.last_user_selection_time - time_diff;
 +                              int numerator = ins_settings.last_user_selection_time /
 +                                                                      ins_settings.last_user_selection_score;
 +                              int last_user_score = denominator / numerator;
 +
 +                              score += (last_user_score > ins_settings.last_user_selection_score ?
 +                                      ins_settings.last_user_selection_score : last_user_score);
 +                      }
 +              }
 +      }
 +
 +      return score;
 +}
 +
 +static int calculate_score_last_connected(struct connman_service *service)
 +{
 +      int score = 0;
 +      struct connman_device *device;
 +      const char *last_connected_ident;
 +      unsigned int frequency;
 +
 +      device = connman_network_get_device(service->network);
 +      if (!device)
 +              return 0;
 +
 +      last_connected_ident = connman_device_get_last_connected_ident(device);
 +      frequency = connman_network_get_frequency(service->network);
 +
 +      if (ins_settings.last_connected) {
 +              if (g_strcmp0(last_connected_ident, service->identifier) == 0 &&
 +                              (((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
 +                              frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
 +                              service->strength >= ins_settings.signal_level3_24ghz) ||
 +                              ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
 +                              frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
 +                              service->strength >= ins_settings.signal_level3_5ghz))) {
 +                      score += ins_settings.last_connected_score;
 +              }
 +      }
 +
 +      return score;
 +}
 +
 +static int calculate_score_frequency(struct connman_service *service)
 +{
 +      int score = 0;
 +      unsigned int frequency;
 +
 +      frequency = connman_network_get_frequency(service->network);
 +
 +      switch (ins_settings.preferred_freq) {
 +      case CONNMAN_INS_PREFERRED_FREQ_24GHZ:
 +              if ((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
 +                      frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
 +                      (service->strength >= ins_settings.signal_level3_24ghz))
 +                      score += ins_settings.preferred_freq_score;
 +
 +              break;
 +      case CONNMAN_INS_PREFERRED_FREQ_5GHZ:
 +              if ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
 +                      frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
 +                      (service->strength >= ins_settings.signal_level3_5ghz))
 +                      score += ins_settings.preferred_freq_score;
 +
 +              break;
 +      default:
 +              break;
 +      }
 +
 +      return score;
 +}
 +
 +static int calculate_score_security_priority(struct connman_service *service)
 +{
 +      int score = 0;
 +
 +      if (ins_settings.security_priority_count)
 +              score += ins_settings.security_priority[service->security];
 +
 +      return score;
 +}
 +
 +static int calculate_score_internet_connection(struct connman_service *service)
 +{
 +      int score = 0;
 +
 +      if (ins_settings.internet) {
 +              if (service->is_internet_connection)
 +                      score += ins_settings.internet_score;
 +      }
 +
 +      return score;
 +}
 +
 +static int calculate_score_strength(struct connman_service *service)
 +{
 +      int score = 0;
 +
 +      if (ins_settings.signal)
 +              score += (((service->strength > 60) ? 60 : service->strength) - 35);
 +
 +      return score;
 +}
 +
 +static int calculate_score(struct connman_service *service)
 +{
 +      int score_last_user_selection;
 +      int score_last_connected;
 +      int score_frequency;
 +      int score_security_priority;
 +      int score_internet_connection;
 +      int score_strength;
 +      int score = 0;
 +
 +      if (service->type != CONNMAN_SERVICE_TYPE_WIFI) {
 +              score += calculate_score_internet_connection(service);
 +              service->ins_score = score;
 +              return score;
 +      }
 +
 +      score_last_user_selection = calculate_score_last_user_selection(service);
 +      score_last_connected = calculate_score_last_connected(service);
 +      score_frequency = calculate_score_frequency(service);
 +      score_security_priority = calculate_score_security_priority(service);
 +      score_internet_connection = calculate_score_internet_connection(service);
 +      score_strength = calculate_score_strength(service);
 +
 +      score = score_last_user_selection + score_last_connected +
 +              score_frequency + score_security_priority +
 +              score_internet_connection + score_strength;
 +
 +      service->score_last_user_selection = score_last_user_selection;
 +      service->score_last_connected = score_last_connected;
 +      service->score_frequency = score_frequency;
 +      service->score_security_priority = score_security_priority;
 +      service->score_internet_connection = score_internet_connection;
 +      service->score_strength = score_strength;
 +
 +      service->ins_score = score;
 +      return score;
 +}
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
 +
+ static gint service_compare(gconstpointer a, gconstpointer b);
+ static gint service_compare_vpn(struct connman_service *a,
+                                               struct connman_service *b)
+ {
+       struct connman_provider *provider;
+       struct connman_service *service;
+       struct connman_service *transport;
+       const char *ident;
+       bool reverse;
+       if (a->provider) {
+               provider = a->provider;
+               service = b;
+               reverse = false;
+       } else if (b->provider) {
+               provider = b->provider;
+               service = a;
+               reverse = true;
+       } else {
+               return 0;
+       }
+       ident = __connman_provider_get_transport_ident(provider);
+       transport = connman_service_lookup_from_identifier(ident);
+       if (!transport)
+               return 0;
+       if (reverse)
+               return service_compare(service, transport);
+       return service_compare(transport, service);
+ }
  static gint service_compare(gconstpointer a, gconstpointer b)
  {
        struct connman_service *service_a = (void *) a;
        a_connected = is_connected(state_a);
        b_connected = is_connected(state_b);
  
-                               connman_option_get_string("DefaultWifiInterface");
 +#if defined TIZEN_EXT
 +      if ((a_connected && b_connected) &&
 +                      state_a == state_b &&
 +                      service_a->type == CONNMAN_SERVICE_TYPE_WIFI &&
 +                      service_b->type == CONNMAN_SERVICE_TYPE_WIFI) {
 +              const char *default_interface =
++                              connman_setting_get_string("DefaultWifiInterface");
 +              const char *ifname_a = connman_device_get_string(
 +                              connman_network_get_device(service_a->network), "Interface");
 +              const char *ifname_b = connman_device_get_string(
 +                              connman_network_get_device(service_b->network), "Interface");
 +
 +              if (g_strcmp0(default_interface, ifname_a) == 0)
 +                      return -1;
 +              else if (g_strcmp0(default_interface, ifname_b) == 0)
 +                      return 1;
 +      }
 +#endif
 +
        if (a_connected && b_connected) {
+               int rval;
+               /* Compare the VPN transport and the service */
+               if ((service_a->type == CONNMAN_SERVICE_TYPE_VPN ||
+                               service_b->type == CONNMAN_SERVICE_TYPE_VPN) &&
+                               service_b->type != service_a->type) {
+                       rval = service_compare_vpn(service_a, service_b);
+                       if (rval)
+                               return rval;
+               }
                if (service_a->order > service_b->order)
                        return -1;
  
@@@ -8609,16 -5731,9 +8746,17 @@@ static void report_error_cb(void *user_
                /* It is not relevant to stay on Failure state
                 * when failing is due to wrong user input */
                __connman_service_clear_error(service);
 +#if defined TIZEN_EXT
 +              /* Reseting the state back in case of failure state */
 +              service->state_ipv4 = service->state_ipv6 =
 +                              CONNMAN_SERVICE_STATE_IDLE;
  
 +              if (service->error != CONNMAN_SERVICE_ERROR_AUTH_FAILED &&
 +                              service->error != CONNMAN_SERVICE_ERROR_ASSOC_FAILED)
 +                      set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN);
 +#endif
                service_complete(service);
+               service_list_sort();
                __connman_connection_update_gateway();
        }
  }
@@@ -9242,65 -6139,9 +9385,66 @@@ static int service_indicate_state(struc
  
        service_list_sort();
  
 +#if defined TIZEN_EXT
 +#if defined TIZEN_MAINTAIN_ONLINE
 +      __connman_service_connect_default(service, old_state);
 +#else
 +      __connman_service_connect_default(service);
 +#endif
 +      /* Update Wi-Fi Roaming result */
 +      if (connman_setting_get_bool("WifiRoaming") &&
 +                      connman_network_get_bool(service->network, "WiFi.Roaming")) {
 +              const char *cur_bssid;
 +              const char *dst_bssid;
 +              const char *ifname;
 +              struct connman_device *device;
 +
 +              device = connman_network_get_device(service->network);
 +              if (device) {
 +                      ifname = connman_device_get_string(device, "Interface");
 +                      cur_bssid = connman_network_get_string(service->network,
 +                                              "WiFi.RoamingCurBSSID");
 +                      dst_bssid = connman_network_get_string(service->network,
 +                                              "WiFi.RoamingDstBSSID");
 +              }
 +
 +              if (device && ifname && cur_bssid && dst_bssid) {
 +                      switch(new_state) {
 +                      case CONNMAN_SERVICE_STATE_UNKNOWN:
 +                      case CONNMAN_SERVICE_STATE_ASSOCIATION:
 +                      case CONNMAN_SERVICE_STATE_CONFIGURATION:
 +                              break;
 +                      case CONNMAN_SERVICE_STATE_READY:
 +                      case CONNMAN_SERVICE_STATE_ONLINE:
 +                              __connman_technology_notify_roaming_state(ifname,
 +                                              "success", cur_bssid, dst_bssid);
 +                              connman_network_set_bool(service->network,
 +                                              "WiFi.Roaming", false);
 +                              connman_network_set_string(service->network,
 +                                              "WiFi.RoamingCurBSSID", NULL);
 +                              connman_network_set_string(service->network,
 +                                              "WiFi.RoamingDstBSSID", NULL);
 +                              break;
 +                      case CONNMAN_SERVICE_STATE_DISCONNECT:
 +                      case CONNMAN_SERVICE_STATE_FAILURE:
 +                      case CONNMAN_SERVICE_STATE_IDLE:
 +                              __connman_technology_notify_roaming_state(ifname,
 +                                              "failure", cur_bssid, dst_bssid);
 +                              connman_network_set_bool(service->network,
 +                                              "WiFi.Roaming", false);
 +                              connman_network_set_string(service->network,
 +                                              "WiFi.RoamingCurBSSID", NULL);
 +                              connman_network_set_string(service->network,
 +                                              "WiFi.RoamingDstBSSID", NULL);
 +                              break;
 +                      }
 +              }
 +      }
 +#endif
 +
        __connman_connection_update_gateway();
  
+ notifier:
        if ((old_state == CONNMAN_SERVICE_STATE_ONLINE &&
                        new_state != CONNMAN_SERVICE_STATE_READY) ||
                (old_state == CONNMAN_SERVICE_STATE_READY &&
@@@ -9794,42 -6566,8 +9954,42 @@@ static void prepare_8021x(struct connma
        if (service->phase2)
                connman_network_set_string(service->network, "WiFi.Phase2",
                                                        service->phase2);
- #if defined TIZEN_EXT
 +
 +#if defined TIZEN_EXT
 +      if (service->keymgmt_type)
 +              connman_network_set_string(service->network, "WiFi.KeymgmtType",
 +                                                      service->keymgmt_type);
 +
 +      DBG("service->phase1 : %s", service->phase1);
 +      if (service->phase1)
 +              connman_network_set_string(service->network, "WiFi.Phase1",
 +                                                      service->phase1);
 +#endif
 +}
 +
++#if defined TIZEN_EXT
 +static bool has_valid_configuration_object(struct connman_service *service)
 +{
 +      return service->connector && service->c_sign_key && service->net_access_key;
  }
  
 +static void prepare_dpp(struct connman_service *service)
 +{
 +      DBG("prepare dpp");
 +      if (service->connector)
 +              connman_network_set_string(service->network, "WiFi.Connector",
 +                                                              service->connector);
 +
 +      if (service->c_sign_key)
 +              connman_network_set_string(service->network, "WiFi.CSignKey",
 +                                                      service->c_sign_key);
 +
 +      if (service->net_access_key)
 +              connman_network_set_string(service->network, "WiFi.NetAccessKey",
 +                                                      service->net_access_key);
 +}
 +#endif
 +
  static int service_connect(struct connman_service *service)
  {
        int err;
@@@ -10781,6 -7358,50 +10950,75 @@@ static void update_from_network(struct 
        service_list_sort();
  }
  
+ static void trigger_autoconnect(struct connman_service *service)
+ {
+       struct connman_device *device;
+       bool native;
+       if (!service->favorite)
+               return;
+       native = __connman_network_native_autoconnect(service->network);
+       if (native && service->autoconnect) {
+               DBG("trigger native autoconnect");
+               connman_network_set_autoconnect(service->network, true);
+               return;
+       }
+       device = connman_network_get_device(service->network);
+       if (device && connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_UNKNOWN))
+               return;
+       switch (service->type) {
+       case CONNMAN_SERVICE_TYPE_UNKNOWN:
+       case CONNMAN_SERVICE_TYPE_SYSTEM:
+       case CONNMAN_SERVICE_TYPE_P2P:
++#if defined TIZEN_EXT_WIFI_MESH
++                      case CONNMAN_SERVICE_TYPE_MESH:
++#endif
+               break;
+       case CONNMAN_SERVICE_TYPE_GADGET:
+       case CONNMAN_SERVICE_TYPE_ETHERNET:
+               if (service->autoconnect) {
+                       __connman_service_connect(service,
+                                               CONNMAN_SERVICE_CONNECT_REASON_AUTO);
+                       break;
+               }
+               /* fall through */
+       case CONNMAN_SERVICE_TYPE_BLUETOOTH:
+       case CONNMAN_SERVICE_TYPE_GPS:
+       case CONNMAN_SERVICE_TYPE_VPN:
+       case CONNMAN_SERVICE_TYPE_WIFI:
+       case CONNMAN_SERVICE_TYPE_CELLULAR:
+               do_auto_connect(service, CONNMAN_SERVICE_CONNECT_REASON_AUTO);
+               break;
+       }
++
++#if defined TIZEN_EXT
++      /* TIZEN synchronizes below information when the service creates */
++      if (service->eap != NULL)
++              connman_network_set_string(service->network, "WiFi.EAP",
++                              service->eap);
++      if (service->identity != NULL)
++              connman_network_set_string(service->network, "WiFi.Identity",
++                              service->identity);
++      if (service->phase2 != NULL)
++              connman_network_set_string(service->network, "WiFi.Phase2",
++                              service->phase2);
++      if (service->eap != NULL)
++              connman_network_set_string(service->network, "WiFi.Connector",
++                              service->connector);
++      if (service->identity != NULL)
++              connman_network_set_string(service->network, "WiFi.CSignKey",
++                              service->c_sign_key);
++      if (service->phase2 != NULL)
++              connman_network_set_string(service->network, "WiFi.NetAccessKey",
++                              service->net_access_key);
++#endif
+ }
  /**
   * __connman_service_create_from_network:
   * @network: network structure
@@@ -11210,99 -7730,6 +11392,99 @@@ static struct connman_agent_driver agen
        .context_unref  = agent_context_unref,
  };
  
-       string = connman_option_get_string("INSPreferredFreq");
 +#if defined TIZEN_EXT && defined TIZEN_EXT_INS
 +static void ins_setting_init(void)
 +{
 +      int i;
 +      const char *string;
 +      char **string_list;
 +      unsigned int string_count;
 +
 +      ins_settings.last_user_selection = connman_setting_get_bool("INSLastUserSelection");
 +      ins_settings.last_user_selection_time = connman_setting_get_uint("INSLastUserSelectionTime");
 +      ins_settings.last_connected = connman_setting_get_bool("INSLastConnected");
 +
++      string = connman_setting_get_string("INSPreferredFreq");
 +      if (g_strcmp0(string, "5GHz") == 0)
 +              ins_settings.preferred_freq = CONNMAN_INS_PREFERRED_FREQ_5GHZ;
 +      else if (g_strcmp0(string, "2.4GHz") == 0)
 +              ins_settings.preferred_freq = CONNMAN_INS_PREFERRED_FREQ_24GHZ;
 +      else
 +              ins_settings.preferred_freq = CONNMAN_INS_PREFERRED_FREQ_UNKNOWN;
 +
 +      ins_settings.security_priority_count = connman_setting_get_uint("INSSecurityPriorityCount");
 +      ins_settings.security_priority_score = connman_setting_get_uint("INSSecurityPriorityScore");
 +      string_count = ins_settings.security_priority_count;
 +
 +      memset(ins_settings.security_priority, 0, sizeof(ins_settings.security_priority));
 +      string_list = connman_setting_get_string_list("INSSecurityPriority");
 +      for (i = 0; string_list && string_list[i]; i++) {
 +              unsigned int security_score = string_count * ins_settings.security_priority_score;
 +
 +              if (g_strcmp0(string_list[i], "WEP") == 0)
 +                      ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_WEP] = security_score;
 +              else if (g_strcmp0(string_list[i], "PSK") == 0)
 +                      ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_PSK] = security_score;
 +              else if (g_strcmp0(string_list[i], "8021X") == 0)
 +                      ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_8021X] = security_score;
 +              else if (g_strcmp0(string_list[i], "WPA") == 0)
 +                      ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_WPA] = security_score;
 +              else if (g_strcmp0(string_list[i], "RSN") == 0)
 +                      ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_RSN] = security_score;
 +              else if (g_strcmp0(string_list[i], "SAE") == 0)
 +                      ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_SAE] = security_score;
 +              else if (g_strcmp0(string_list[i], "OWE") == 0)
 +                      ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_OWE] = security_score;
 +              else if (g_strcmp0(string_list[i], "DPP") == 0)
 +                      ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_DPP] = security_score;
 +
 +              string_count--;
 +      }
 +
 +      ins_settings.signal = connman_setting_get_bool("INSSignal");
 +      ins_settings.internet = connman_setting_get_bool("INSInternet");
 +
 +      ins_settings.last_user_selection_score = connman_setting_get_uint("INSLastUserSelectionScore");
 +      ins_settings.last_connected_score = connman_setting_get_uint("INSLastConnectedScore");
 +      ins_settings.preferred_freq_score = connman_setting_get_uint("INSPreferredFreqScore");
 +      ins_settings.internet_score = connman_setting_get_uint("INSInternetScore");
 +
 +      /*
 +       * In ConnMan, signal strength is used after being converted
 +       * to positive value(signal strength + 120).
 +       * So the value for comparison should also be converted to the same.
 +       */
 +      ins_settings.signal_level3_5ghz = connman_setting_get_int("INSSignalLevel3_5GHz") + 120;
 +      ins_settings.signal_level3_24ghz = connman_setting_get_int("INSSignalLevel3_24GHz") + 120;
 +
 +      DBG("last_user_selection [%s]", ins_settings.last_user_selection ? "true" : "false");
 +      DBG("last_user_selection_time [%d]", ins_settings.last_user_selection_time);
 +      DBG("last_user_selection_score [%d]", ins_settings.last_user_selection_score);
 +
 +      DBG("last_connected [%s]", ins_settings.last_connected ? "true" : "false");
 +      DBG("last_connected_score [%d]", ins_settings.last_connected_score);
 +
 +      DBG("preferred_freq [%s]", ins_settings.preferred_freq ? "true" : "false");
 +      DBG("preferred_freq_score [%d]", ins_settings.preferred_freq_score);
 +
 +      DBG("security_priority_count [%d]", ins_settings.security_priority_count);
 +      for (i = 0; i < CONNMAN_SERVICE_SECURITY_MAX; i++) {
 +              if (ins_settings.security_priority[i])
 +                      DBG("security_priority %s [%d]", security2string(i),
 +                                      ins_settings.security_priority[i]);
 +      }
 +      DBG("security_priority_score [%d]", ins_settings.security_priority_score);
 +
 +      DBG("signal [%s]", ins_settings.signal ? "true" : "false");
 +
 +      DBG("internet [%s]", ins_settings.internet ? "true" : "false");
 +      DBG("internet_score [%d]", ins_settings.internet_score);
 +
 +      DBG("signal_level3_5ghz [%d]", ins_settings.signal_level3_5ghz);
 +      DBG("signal_level3_24ghz [%d]", ins_settings.signal_level3_24ghz);
 +}
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
 +
  int __connman_service_init(void)
  {
        int err;
diff --cc src/session.c
Simple merge
index 73c24ae,bda2d2b..bda2d2b
mode 100755,100644..100755
@@@ -216,24 -185,13 +216,26 @@@ static void technology_save(struct conn
                                        "Tethering.Identifier",
                                        technology->tethering_ident);
  
-       if (technology->tethering_passphrase)
+       if (technology->tethering_passphrase) {
+               char *enc = g_strescape(technology->tethering_passphrase, NULL);
                g_key_file_set_string(keyfile, identifier,
-                                       "Tethering.Passphrase",
-                                       technology->tethering_passphrase);
+                                       "Tethering.Passphrase", enc);
+               g_free(enc);
+       }
  
 +#ifdef TIZEN_EXT
 +      if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
 +              g_key_file_set_uint64(keyfile, identifier, "MacPolicy",
 +                                      technology->mac_policy);
 +
 +              g_key_file_set_uint64(keyfile, identifier, "PreassocMacPolicy",
 +                                      technology->preassoc_mac_policy);
 +
 +              g_key_file_set_uint64(keyfile, identifier, "RandomMacLifetime",
 +                                      technology->random_mac_lifetime);
 +      }
 +#endif /* TIZEN_EXT */
 +
  done:
        g_free(identifier);
  
@@@ -502,36 -439,10 +505,37 @@@ static void technology_load(struct conn
        technology->tethering_ident = g_key_file_get_string(keyfile,
                                identifier, "Tethering.Identifier", NULL);
  
-       technology->tethering_passphrase = g_key_file_get_string(keyfile,
+       enc = g_key_file_get_string(keyfile,
                                identifier, "Tethering.Passphrase", NULL);
+       if (enc)
+               technology->tethering_passphrase = g_strcompress(enc);
 +#ifdef TIZEN_EXT
 +      if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
 +              unsigned int val = 0;
 +
 +              val = g_key_file_get_uint64(keyfile,
 +                              identifier, "MacPolicy", NULL);
 +              if (val <= 2)
 +                      technology->mac_policy = val;
 +              else
 +                      technology->mac_policy = 0;
 +
 +              val = g_key_file_get_uint64(keyfile,
 +                              identifier, "PreassocMacPolicy", NULL);
 +              if (val <= 2)
 +                      technology->preassoc_mac_policy = val;
 +              else
 +                      technology->preassoc_mac_policy = 0;
 +
 +              val = g_key_file_get_uint64(keyfile,
 +                              identifier, "RandomMacLifetime", NULL);
 +              if (val > 0)
 +                      technology->random_mac_lifetime = val;
 +              else
 +                      technology->random_mac_lifetime = 60;
 +      }
 +#endif /* TIZEN_EXT */
 +
  done:
        g_free(identifier);
  
diff --cc src/tethering.c
index e2687b6,f930a26..f930a26
mode 100755,100644..100755
index a9a73a2,feef8e8..b2707fa
mode 100755,100644..100755
diff --cc src/wispr.c
index 3b203fb,c63dc81..fb101a1
mode 100755,100644..100755
@@@ -783,26 -784,9 +794,21 @@@ static bool wispr_portal_web_result(GWe
                goto done;
        case 400:
        case 404:
-               if (__connman_service_online_check_failed(wp_context->service,
-                                               wp_context->type) == 0) {
+               __connman_service_online_check(wp_context->service,
+                                               wp_context->type, false);
 -
 +#if defined TIZEN_MAINTAIN_ONLINE
 +                      if (wp_context->type == CONNMAN_IPCONFIG_TYPE_IPV4) {
 +                              if (retried == 0) {
 +                                      connman_agent_report_error(wp_context->service,
 +                                              __connman_service_get_path(wp_context->service),
 +                                              "internet-unreachable",
 +                                              NULL, NULL, NULL);
 +
 +                                      retried = 1;
 +                              }
 +                              break;
 +                      }
 +#endif
-                       wispr_portal_error(wp_context);
-                       free_connman_wispr_portal_context(wp_context);
-                       return false;
-               }
                break;
        case 505:
                __connman_agent_request_browser(wp_context->service,
diff --cc vpn/main.c
index ae9c945,92c63e2..e4f4a10
mode 100755,100644..100755
@@@ -227,33 -160,6 +160,43 @@@ static GOptionEntry options[] = 
        { NULL },
  };
  
- #if defined TIZEN_EXT
++#if defined TIZEN_EXT
 +bool connman_setting_get_bool(const char *key)
 +{
 +      return false;
 +}
 +
- #endif
 +unsigned int connman_setting_get_uint(const char *key)
 +{
 +      return 0;
 +}
 +
 +int connman_setting_get_int(const char *key)
 +{
 +      return 0;
 +}
++
++char *connman_setting_get_string(const char *key)
++{
++        return NULL;
++}
 +
 +char **connman_setting_get_string_list(const char *key)
 +{
 +      return NULL;
 +}
 +
 +unsigned int *connman_setting_get_uint_list(const char *key)
 +{
 +      return NULL;
 +}
 +
++unsigned int connman_timeout_browser_launch(void)
++{
++      return 0;
++}
++#endif
++
  /*
   * This function will be called from generic src/agent.c code so we have
   * to use connman_ prefix instead of vpn_ one.
index 48894aa,1e4fcd1..1e4fcd1
mode 100755,100644..100755
index ef0bf78,daf66cd..8c8d316
mode 100755,100644..100755
@@@ -500,14 -496,12 +503,14 @@@ static int run_connect(struct ov_privat
  
        connman_task_add_argument(task, "--persist-tun", NULL);
  
 +#if !defined TIZEN_EXT
        connman_task_add_argument(task, "--route-noexec", NULL);
        connman_task_add_argument(task, "--ifconfig-noexec", NULL);
 +#endif
  
        /*
-        * Disable client restarts because we can't handle this at the
-        * moment. The problem is that when OpenVPN decides to switch
+        * Disable client restarts with TCP because we can't handle this at
+        * the moment. The problem is that when OpenVPN decides to switch
         * from CONNECTED state to RECONNECTING and then to RESOLVE,
         * it is not possible to do a DNS lookup. The DNS server is
         * not accessible through the tunnel anymore and so we end up
index 5fc861e,4a704bb..4a704bb
mode 100755,100644..100755
index c0b2977,cb0d304..b89c222
mode 100755,100644..100755
@@@ -717,12 -632,6 +682,11 @@@ static int vpn_connect(struct vpn_provi
                goto exist_err;
        }
  
 +#if defined TIZEN_EXT
 +      if(vpn_driver_data->vpn_driver->set_event_cb)
 +              vpn_driver_data->vpn_driver->set_event_cb(vpn_event, provider);
 +#endif
 +
        ret = vpn_driver_data->vpn_driver->connect(provider, data->task,
                                                data->if_name, cb, dbus_sender,
                                                user_data);
index 893e9a1,fd10add..7956ffa
mode 100755,100644..100755
index 8350fc3,d11b911..d11b911
mode 100755,100644..100755
Simple merge
index 97e072c,8c6b068..e412b89
mode 100755,100644..100755
@@@ -262,11 -252,7 +262,11 @@@ static int load_provider(GKeyFile *keyf
  
                DBG("provider identifier %s", id);
        } else {
-               DBG("invalid values host %s domain %s name %s", host, domain, name);
 +#if !defined TIZEN_EXT
 +              DBG("invalid values host %s domain %s", host, domain);
 +#else
+               DBG("invalid configuration: no host specified");
 +#endif
                err = -EINVAL;
                goto err;
        }
index 476be1c,0f0c8da..db3d49e
mode 100755,100644..100755
@@@ -1,16 -1,15 +1,20 @@@
  <!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
   "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
  <busconfig>
 -    <policy user="root">
 -        <allow own="net.connman.vpn"/>
 -        <allow send_destination="net.connman.vpn"/>
 +      <policy user="root">
 +              <allow own="net.connman.vpn"/>
 +              <allow send_destination="net.connman.vpn"/>
+         <allow send_interface="net.connman.vpn.Agent"/>
 -    </policy>
 +      </policy>
+     <policy at_console="true">
+         <allow send_destination="net.connman.vpn"/>
+     </policy>
 -    <policy context="default">
 -        <deny send_destination="net.connman.vpn"/>
 -    </policy>
 +      <policy user="network_fw">
 +              <allow own="net.connman.vpn"/>
 +              <allow send_destination="net.connman.vpn"/>
 +      </policy>
 +      <policy context="default">
 +              <deny own="net.connman.vpn"/>
 +              <deny send_destination="net.connman.vpn"/>
 +      </policy>
  </busconfig>
index c4fa548,825b43c..825b43c
mode 100755,100644..100755
index 6a6b661,59c805c..8092b5d
mode 100755,100644..100755
index 0275d51,f7fa859..f7fa859
mode 100755,100644..100755
diff --cc vpn/vpn.h
index e68b8ad,477cb22..94cee25
mode 100755,100644..100755
+++ b/vpn/vpn.h