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 --combined AUTHORS
index e03a071,438d45f..438d45f
mode 100755,100644..100755
+++ b/AUTHORS
@@@ -159,3 -159,15 +159,15 @@@ Yasser <yasser.toor@gmail.com
  Matt Vogt <matthew.vogt@jollamobile.com>
  David Llewellyn-Jones <david.llewellyn-jones@jolla.com>
  David Weidenkopf <David.Weidenkopf@Arthrex.com>
+ Maxime Roussin-Bélanger <maxime.roussinbelanger@gmail.com>
+ Holesch, Simon (GED-SDD1) <Simon.Holesch@bshg.com>
+ Christoph Steiger <c.steiger@lemonage.de>
+ Markus Held <mjh42@gmx.de>
+ Sergey Matyukevich <geomatsi@gmail.com>
+ Pieter Cardoen <P.Cardoen@TELEVIC.com>
+ Emmanuel Vautrin <emmanuel.vautrin@cpexterne.org>
+ Boleslaw Tokarski <boleslaw.tokarski@jolla.com>
+ Gabriel FORTE <gforte@wyplay.com>
+ Colin Wee <cwee@tesla.com>
+ Valery Kashcheev <v.kascheev@omp.ru>
+ Alyssa Ross <hi@alyssa.is>
diff --combined Makefile.am
@@@ -14,14 -14,10 +14,14 @@@ include_HEADERS = include/log.h include
                        include/inotify.h include/peer.h include/machine.h \
                        include/acd.h include/tethering.h
  
 +if TIZEN_EXT_WIFI_MESH
 +include_HEADERS += include/mesh.h include/mesh-netlink.h
 +endif
 +
  nodist_include_HEADERS = include/version.h
  
  noinst_HEADERS = include/rtnl.h include/task.h \
-                       include/dbus.h include/option.h \
+                       include/dbus.h \
                        include/provider.h include/vpn-dbus.h \
                        include/utsname.h include/timeserver.h include/proxy.h \
                        include/technology.h include/setting.h \
@@@ -42,7 -38,7 +42,7 @@@ backtrace_sources = src/backtrace.
  endif
  
  gdhcp_sources = gdhcp/gdhcp.h gdhcp/common.h gdhcp/common.c gdhcp/client.c \
 -              gdhcp/server.c gdhcp/unaligned.h
 +              gdhcp/server.c gdhcp/ipv4ll.h gdhcp/ipv4ll.c gdhcp/unaligned.h
  
  gweb_sources = gweb/gweb.h gweb/gweb.c gweb/gresolv.h gweb/gresolv.c
  
@@@ -75,32 -71,29 +75,32 @@@ if VP
  dbusconf_DATA += vpn/connman-vpn-dbus.conf
  dbusservicedir = @DBUS_DATADIR@
  dbusservice_DATA = vpn/net.connman.vpn.service
 -endif
  
  if SYSTEMD
  systemdunitdir = @SYSTEMD_UNITDIR@
 -systemdunit_DATA = src/connman.service src/connman-wait-online.service
 -
 -tmpfilesdir = @SYSTEMD_TMPFILESDIR@
 -nodist_tmpfiles_DATA = scripts/connman_resolvconf.conf
 +systemdunit_DATA = src/connman.service vpn/connman-vpn.service
  
 -if VPN
 -systemdunit_DATA += vpn/connman-vpn.service
 -endif
 -endif
  endif
  
  service_files_sources = src/connman.service.in src/net.connman.service.in \
                                vpn/connman-vpn.service.in \
 -                              vpn/net.connman.vpn.service.in \
 -                              src/connman-wait-online.service.in
 +                              vpn/net.connman.vpn.service.in
  service_files = src/connman.service src/net.connman.service \
                                vpn/connman-vpn.service \
 -                              vpn/net.connman.vpn.service \
 -                              src/connman-wait-online.service
 +                              vpn/net.connman.vpn.service
 +
 +else
 +
 +if SYSTEMD
 +systemdunitdir = @SYSTEMD_UNITDIR@
 +systemdunit_DATA = src/connman.service
 +
 +endif
 +
 +service_files_sources = src/connman.service.in src/net.connman.service.in
 +service_files = src/connman.service src/net.connman.service
 +endif
 +endif
  
  plugin_LTLIBRARIES =
  
@@@ -112,21 -105,13 +112,21 @@@ builtin_libadd 
  builtin_cflags =
  
  noinst_PROGRAMS =
 +if TIZEN_EXT
 +bin_PROGRAMS = src/connmand
 +else
  bin_PROGRAMS =
 +endif
  
  unit_objects =
  
  MANUAL_PAGES =
  
 +if TIZEN_EXT
 +sbin_PROGRAMS =
 +else
  sbin_PROGRAMS = src/connmand src/connmand-wait-online
 +endif
  
  src_connmand_SOURCES = $(gdhcp_sources) $(gweb_sources) $(stats_sources) \
                        $(backtrace_sources) $(builtin_sources) $(shared_sources) \
@@@ -153,25 -138,18 +153,25 @@@ endi
  if SYSTEMD_RESOLVED_DNS_BACKEND
  src_connmand_SOURCES += src/dns-systemd-resolved.c
  endif
 +if TIZEN_EXT_WIFI_MESH
 +src_connmand_SOURCES += src/mesh.c src/mesh-netlink.c
 +endif
  
  src_connmand_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \
 -                      @GLIB_LIBS@ @DBUS_LIBS@ @GNUTLS_LIBS@ \
 +                      @DLOG_LIBS@ @GLIB_LIBS@ @DBUS_LIBS@ @GNUTLS_LIBS@ @LIBSYSTEMD_LIBS@ \
                        -lresolv -ldl -lrt
  
 -src_connmand_LDFLAGS = -Wl,--export-dynamic \
 +if TIZEN_EXT_WIFI_MESH
 +src_connmand_LDADD += @LIBNL_LIBS@ @LIBNL_GENL_LIBS@
 +endif
 +
 +src_connmand_LDFLAGS = -Wl,--export-dynamic -pie \
                                -Wl,--version-script=$(srcdir)/src/connman.ver
  
  src_connmand_wait_online_SOURCES = src/connmand-wait-online.c
  
  src_connmand_wait_online_LDADD = gdbus/libgdbus-internal.la \
 -                      @GLIB_LIBS@ @DBUS_LIBS@
 +                      @DLOG_LIBS@ @GLIB_LIBS@ @DBUS_LIBS@
  
  if XTABLES
  src_connmand_SOURCES += src/iptables.c src/firewall-iptables.c
@@@ -193,49 -171,22 +193,49 @@@ builtin_vpn_sources 
  builtin_vpn_libadd =
  builtin_vpn_cflags =
  
 +if TIZEN_EXT
 +bin_PROGRAMS += vpn/connman-vpnd
 +else
  sbin_PROGRAMS += vpn/connman-vpnd
 +endif
  
 -vpn_connman_vpnd_SOURCES = $(builtin_vpn_sources) $(backtrace_sources) \
 +vpn_connman_vpnd_SOURCES = $(gdhcp_sources) $(builtin_vpn_sources) \
 +                      $(shared_sources) \
                        $(gweb_sources) vpn/vpn.ver vpn/main.c vpn/vpn.h \
 -                      src/log.c src/error.c src/plugin.c src/task.c \
                        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
@@@ -283,7 -234,7 +283,7 @@@ build_vpn_plugindir = $(vpn_plugindir
  endif
  endif
  
 -AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ \
 +AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @LIBSYSTEMD_CFLAGS@ @DLOG_CFLAGS@ \
                                @GNUTLS_CFLAGS@ $(builtin_cflags) \
                                -DCONNMAN_PLUGIN_BUILTIN \
                                -DSTATEDIR=\""$(statedir)"\" \
                                -DSCRIPTDIR=\""$(build_scriptdir)"\" \
                                -DSTORAGEDIR=\""$(storagedir)\"" \
                                -DVPN_STORAGEDIR=\""$(vpn_storagedir)\"" \
 -                              -DCONFIGDIR=\""$(configdir)\""
 +                              -DCONFIGDIR=\""$(configdir)\"" \
 +                              -fPIE
  
  if VPN
  AM_CPPFLAGS = -I$(builddir)/include -I$(srcdir)/gdbus
@@@ -301,7 -251,7 +301,7 @@@ els
  AM_CPPFLAGS = -I$(builddir)/include -I$(builddir)/src -I$(srcdir)/gdbus
  endif
  
 -src_connmand_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ \
 +src_connmand_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @DLOG_CFLAGS@ \
                                @GNUTLS_CFLAGS@ $(builtin_cflags) \
                                -DCONNMAN_PLUGIN_BUILTIN \
                                -DSTATEDIR=\""$(statedir)"\" \
@@@ -317,7 -267,7 +317,7 @@@ EXTRA_DIST = src/genbuiltin src/connman
                                $(service_files_sources) scripts/connman.in
  
  if VPN
 -vpn_connman_vpnd_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ \
 +vpn_connman_vpnd_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @XTABLES_CFLAGS@ @DLOG_CFLAGS@ \
                                $(builtin_vpn_cflags) \
                                -DCONNMAN_PLUGIN_BUILTIN \
                                -DVPN_STATEDIR=\""$(vpn_statedir)"\" \
@@@ -340,14 -290,6 +340,14 @@@ AM_CFLAGS += @NFTABLES_CFLAGS@ @LIBMNL_
  src_connmand_CFLAGS += @NFTABLES_CFLAGS@ @LIBMNL_CFLAGS@
  endif
  
 +if TIZEN_EXT_WIFI_MESH
 +AM_CFLAGS += @LIBNL_CFLAGS@ @LIBNL_GENL_CFLAGS@
 +src_connmand_CFLAGS += @LIBNL_CFLAGS@ @LIBNL_GENL_CFLAGS@
 +if VPN
 +vpn_connman_vpnd_CFLAGS += @LIBNL_CFLAGS@ @LIBNL_GENL_CFLAGS@
 +endif
 +endif
 +
  EXTRA_DIST += vpn/vpn-dbus.conf vpn/vpn-polkit.conf
  
  script_DATA =
@@@ -369,16 -311,8 +369,16 @@@ client_connmanctl_SOURCES = client/dbus
                        client/vpnconnections.h client/vpnconnections.c \
                        client/main.c
  
 -client_connmanctl_LDADD = gdbus/libgdbus-internal.la @DBUS_LIBS@ @GLIB_LIBS@ \
 -                              -lreadline -ldl
 +if TIZEN_EXT_WIFI_MESH
 +client_connmanctl_SOURCES += client/mesh.c client/mesh.h
 +endif
 +
 +if TIZEN_EXT_INS
 +client_connmanctl_SOURCES += client/ins.c client/ins.h
 +endif
 +
 +client_connmanctl_LDADD = gdbus/libgdbus-internal.la @DBUS_LIBS@ @GLIB_LIBS@ @DLOG_LIBS@ \
 +                              -lreadline -ldl -lncurses
  endif
  
  noinst_PROGRAMS += unit/test-ippool
  unit_test_ippool_SOURCES = $(backtrace_sources) src/log.c src/dbus.c \
                                        src/error.c src/ippool.c unit/test-ippool.c
  unit_test_ippool_LDADD = gdbus/libgdbus-internal.la \
 -                              @GLIB_LIBS@ @DBUS_LIBS@ -ldl
 +                              @GLIB_LIBS@ @DBUS_LIBS@ @DLOG_LIBS@ -ldl
  
  TESTS = unit/test-ippool
  
@@@ -411,7 -345,7 +411,7 @@@ tools_supplicant_test_SOURCES = tools/s
                        tools/supplicant-dbus.h tools/supplicant-dbus.c \
                        tools/supplicant.h tools/supplicant.c
  tools_supplicant_test_LDADD = gdbus/libgdbus-internal.la \
 -                              @GLIB_LIBS@ @DBUS_LIBS@
 +                              @GLIB_LIBS@ @DBUS_LIBS@ @DLOG_LIBS@
  
  tools_web_test_SOURCES = $(gweb_sources) tools/web-test.c
  tools_web_test_LDADD = @GLIB_LIBS@ @GNUTLS_LIBS@ -lresolv
@@@ -433,17 -367,17 +433,17 @@@ tools_dhcp_server_test_SOURCES =  $(bac
  tools_dhcp_server_test_LDADD = @GLIB_LIBS@ -ldl
  
  tools_dbus_test_SOURCES = tools/dbus-test.c
 -tools_dbus_test_LDADD = gdbus/libgdbus-internal.la @GLIB_LIBS@ @DBUS_LIBS@
 +tools_dbus_test_LDADD = gdbus/libgdbus-internal.la @GLIB_LIBS@ @DBUS_LIBS@ @DLOG_LIBS@
  
 -tools_polkit_test_LDADD = @DBUS_LIBS@
 +tools_polkit_test_LDADD = @DBUS_LIBS@ @DLOG_LIBS@
  
 -tools_private_network_test_LDADD = @GLIB_LIBS@ @DBUS_LIBS@
 +tools_private_network_test_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ @DLOG_LIBS@
  
  tools_session_test_SOURCES = $(backtrace_sources) src/log.c src/dbus.c src/error.c \
                tools/session-test.c tools/session-utils.c tools/manager-api.c \
                tools/session-api.c tools/session-test.h
  tools_session_test_LDADD = gdbus/libgdbus-internal.la \
 -                              @GLIB_LIBS@ @DBUS_LIBS@ -ldl
 +                              @GLIB_LIBS@ @DBUS_LIBS@ @DLOG_LIBS@ -ldl
  
  if XTABLES
  noinst_PROGRAMS += tools/iptables-test tools/ip6tables-test tools/iptables-unit \
@@@ -457,14 -391,14 +457,14 @@@ tools_ip6tables_test_SOURCES = $(backtr
                                tools/ip6tables-test.c
  tools_ip6tables_test_LDADD = @GLIB_LIBS@ @XTABLES_LIBS@ -ldl
  
 -tools_iptables_unit_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @XTABLES_CFLAGS@ \
 +tools_iptables_unit_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @XTABLES_CFLAGS@ @DLOG_CFLAGS@ \
                -DIPTABLES_SAVE=\""${IPTABLES_SAVE}"\" \
                -DIP6TABLES_SAVE=\""${IP6TABLES_SAVE}"\"
  tools_iptables_unit_SOURCES = $(backtrace_sources) src/log.c \
                src/iptables.c src/firewall-iptables.c src/nat.c \
                tools/iptables-unit.c
  tools_iptables_unit_LDADD = gdbus/libgdbus-internal.la \
 -                              @GLIB_LIBS@ @DBUS_LIBS@ @XTABLES_LIBS@ -ldl
 +                              @GLIB_LIBS@ @DBUS_LIBS@ @XTABLES_LIBS@ @DLOG_LIBS@ -ldl
  
  TESTS += unit/test-iptables
  
@@@ -525,12 -459,13 +525,12 @@@ EXTRA_DIST += doc/overview-api.txt doc/
                                doc/connman.8.in doc/connman-vpn.8.in
  
  EXTRA_DIST += src/main.conf \
 -              src/eduroam.config \
 -              scripts/connman_resolvconf.conf.in
 +              src/eduroam.config
  
 -MANUAL_PAGES += doc/connmanctl.1 doc/connman.conf.5 \
 -              doc/connman-service.config.5 doc/connman-vpn.conf.5 \
 -              doc/connman-vpn-provider.config.5 \
 -              doc/connman.8 doc/connman-vpn.8
 +#MANUAL_PAGES += doc/connmanctl.1 doc/connman.conf.5 \
 +#             doc/connman-service.config.5 doc/connman-vpn.conf.5 \
 +#             doc/connman-vpn-provider.config.5 \
 +#             doc/connman.8 doc/connman-vpn.8
  
  nodist_man_MANS = $(MANUAL_PAGES)
  
@@@ -542,7 -477,6 +542,7 @@@ DISTCHECK_CONFIGURE_FLAGS = --disable-d
                                --enable-hh2serial-gps \
                                --enable-openconnect \
                                --enable-openvpn \
 +                              --enable-ipsec \
                                --enable-vpnc \
                                --enable-session-policy-local \
                                --enable-nmcompat \
diff --combined Makefile.plugins
index 004bbe9,8e32361..a0c17cf
mode 100755,100644..100755
@@@ -1,6 -1,6 +1,6 @@@
  
  plugin_cflags = -fvisibility=hidden -I$(srcdir)/gdbus \
 -                                      @DBUS_CFLAGS@ @GLIB_CFLAGS@
 +                                      @DLOG_CFLAGS@ @DBUS_CFLAGS@ @GLIB_CFLAGS@
  plugin_ldflags = -no-undefined -module -avoid-version
  
  if LOOPBACK
@@@ -58,18 -58,6 +58,18 @@@ builtin_modules += dunde
  builtin_sources += plugins/dundee.c
  endif
  
 +if TELEPHONY
 +if TELEPHONY_BUILTIN
 +builtin_modules += telephony
 +builtin_sources += plugins/telephony.c
 +else
 +plugin_LTLIBRARIES += plugins/telephony.la
 +plugin_objects += $(plugins_telephony_la_OBJECTS)
 +plugins_telephony_la_CFLAGS = $(plugin_cflags)
 +plugins_telephony_la_LDFLAGS = $(plugin_ldflags)
 +endif
 +endif
 +
  if VPN
  builtin_modules += vpn
  builtin_sources += plugins/vpn.c
@@@ -104,7 -92,9 +104,9 @@@ builtin_vpn_source = vpn/plugins/vpn.c 
  if OPENCONNECT_BUILTIN
  builtin_vpn_modules += openconnect
  builtin_vpn_sources += vpn/plugins/openconnect.c
- builtin_vpn_cflags += -DOPENCONNECT=\"@OPENCONNECT@\"
+ builtin_vpn_cflags += -DOPENCONNECT=\"@OPENCONNECT@\" \
+                                         @LIBOPENCONNECT_CFLAGS@
+ builtin_vpn_libadd += @LIBOPENCONNECT_LIBS@
  else
  vpn_plugin_LTLIBRARIES += vpn/plugins/openconnect.la
  vpn_plugin_objects += $(plugins_openconnect_la_OBJECTS)
@@@ -112,8 -102,10 +114,10 @@@ vpn_plugins_openconnect_la_SOURCES = vp
  vpn_plugins_openconnect_la_CFLAGS = $(plugin_cflags) \
                                        -DOPENCONNECT=\"@OPENCONNECT@\" \
                                        -DVPN_STATEDIR=\""$(vpn_statedir)"\" \
-                                       -DSCRIPTDIR=\""$(build_scriptdir)"\"
+                                       -DSCRIPTDIR=\""$(build_scriptdir)"\" \
+                                         @LIBOPENCONNECT_CFLAGS@
  vpn_plugins_openconnect_la_LDFLAGS = $(plugin_ldflags)
+ vpn_plugins_openconnect_la_LIBADD = @LIBOPENCONNECT_LIBS@
  endif
  endif
  
@@@ -134,25 -126,6 +138,25 @@@ vpn_plugins_openvpn_la_LDFLAGS = $(plug
  endif
  endif
  
 +if IPSEC
 +if IPSEC_BUILTIN
 +builtin_vpn_modules += ipsec
 +builtin_vpn_sources += vpn/plugins/ipsec.h vpn/plugins/ipsec.c
 +builtin_vpn_sources += vpn/plugins/vici-client.h vpn/plugins/vici-client.c
 +builtin_vpn_source = vpn/plugins/vpn.c vpn/plugins/vpn.h
 +builtin_vpn_cflags += -DIPSEC=\"@IPSEC@\"
 +else
 +vpn_plugin_LTLIBRARIES += vpn/plugins/ipsec.la
 +vpn_plugin_objects += $(plugins_ipsec_la_OBJECTS)
 +vpn_plugins_ipsec_la_SOURCES = vpn/plugins/vpn.h vpn/plugins/vpn.c \
 +                                              vpn/plugins/ipsec.c vpn/plugins/vici-client.c
 +vpn_plugins_ipsec_la_CFLAGS = $(plugin_cflags) -DIPSEC=\"@IPSEC@\" \
 +                                      -DVPN_STATEDIR=\""$(vpn_statedir)"\" \
 +                                      -DSCRIPTDIR=\""$(build_scriptdir)"\" @GIO_CFLAGS@
 +vpn_plugins_ipsec_la_LDFLAGS = $(plugin_ldflags) @GIO_LIBS@
 +endif
 +endif
 +
  if VPNC
  builtin_vpn_source = vpn/plugins/vpn.c vpn/plugins/vpn.h
  if VPNC_BUILTIN
@@@ -250,7 -223,9 +254,7 @@@ plugins_iospm_la_LDFLAGS = $(plugin_ldf
  endif
  
  if OPENCONNECT
 -script_PROGRAMS += scripts/vpn-script
 -
 -scripts_vpn_script_LDADD = @DBUS_LIBS@
 +scripts_openconnect_script_LDADD = @DBUS_LIBS@ @DLOG_LIBS@
  else
  if VPNC
  script_PROGRAMS += scripts/vpn-script
@@@ -262,13 -237,7 +266,13 @@@ endi
  if OPENVPN
  script_PROGRAMS += scripts/openvpn-script
  
 -scripts_openvpn_script_LDADD = @DBUS_LIBS@
 +scripts_openvpn_script_LDADD = @DBUS_LIBS@ @DLOG_LIBS@
 +endif
 +
 +if IPSEC
 +script_PROGRAMS += scripts/ipsec-script
 +
 +scripts_ipsec_script_LDADD = @DBUS_LIBS@ @DLOG_LIBS@
  endif
  
  if NMCOMPAT
diff --combined README
index e911bc2,b8154e6..b8154e6
mode 100755,100644..100755
--- 1/README
--- 2/README
+++ b/README
@@@ -444,10 -444,12 +444,12 @@@ Informatio
  ===========
  
  Mailing list:
-       connman@connman.net
+       connman@lists.linux.dev
  
- For additional information about the project visit ConnMan web site:
-       https://01.org/connman
-       http://www.connman.net
+ If you would like to subscribe to receive mail in your inbox, just
+ send a (empty) message from your email account to
  
- You can report bugs at https://01.org/jira/browse/CM
+       connman+subscribe@lists.linux.dev
+ Mailing list archive:
+       https://lore.kernel.org/connman
diff --combined configure.ac
@@@ -1,5 -1,5 +1,5 @@@
  AC_PREREQ(2.60)
- AC_INIT(connman, 1.38)
+ AC_INIT(connman, 1.40)
  
  AC_CONFIG_MACRO_DIR([m4])
  
@@@ -66,44 -66,6 +66,44 @@@ AC_ARG_ENABLE(hh2serial-gps
  AM_CONDITIONAL(HH2SERIAL_GPS, test "${enable_hh2serial_gps}" != "no")
  AM_CONDITIONAL(HH2SERIAL_GPS_BUILTIN, test "${enable_hh2serial_gps}" = "builtin")
  
 +AC_ARG_ENABLE(telephony,
 +      AC_HELP_STRING([--enable-telephony], [enable Telephony support]),
 +                      [enable_telephony=${enableval}], [enable_telephony="yes"])
 +AM_CONDITIONAL(TELEPHONY, test "${enable_telephony}" != "no")
 +AM_CONDITIONAL(TELEPHONY_BUILTIN, test "${enable_telephony}" = "builtin")
 +
 +AC_ARG_ENABLE(tizen-ext,
 +      AC_HELP_STRING([--enable-tizen-ext], [enable TIZEN extensions]),
 +                      [if (test "${enableval}" = "yes"); then
 +                              CFLAGS="$CFLAGS -DTIZEN_EXT"
 +                              LIBS="$LIBS -lsmack"
 +                      fi])
 +AM_CONDITIONAL(TIZEN_EXT, test "${enable-tizen-ext}" != "no")
 +
 +AC_ARG_ENABLE(tizen-ext-ins,
 +      AC_HELP_STRING([--enable-tizen-ext-ins], [enable TIZEN extensions for INS]),
 +                      [if (test "${enableval}" = "yes"); then
 +                              CFLAGS="$CFLAGS -DTIZEN_EXT_INS"
 +                      fi])
 +AM_CONDITIONAL(TIZEN_EXT_INS, test "${enable_tizen_ext_ins}" != "no")
 +
 +AC_ARG_ENABLE(tizen-ext-wifi-mesh,
 +      AC_HELP_STRING([--enable-tizen-ext-wifi-mesh], [enable TIZEN extensions for Wi-Fi Mesh]),
 +                      [CFLAGS="$CFLAGS -DTIZEN_EXT_WIFI_MESH"], [enable_tizen_ext_wifi_mesh="no"])
 +AM_CONDITIONAL(TIZEN_EXT_WIFI_MESH, test "${enable_tizen_ext_wifi_mesh}" != "no")
 +
 +AC_ARG_ENABLE(tizen-ext-eap-on-ethernet,
 +      AC_HELP_STRING([--enable-tizen-ext-eap-on-ethernet], [enable TIZEN extensions for EAP on Ethernet]),
 +                      [CFLAGS="$CFLAGS -DTIZEN_EXT_EAP_ON_ETHERNET"], [enable_tizen_ext_eap_on_ethernet="no"])
 +AM_CONDITIONAL(TIZEN_EXT_EAP_ON_ETHERNET, test "${enable_tizen_ext_eap_on_ethernet}" != "no")
 +
 +AC_ARG_ENABLE(tizen-maintain-online,
 +      AC_HELP_STRING([--enable-tizen-maintain-online], [enable TIZEN extensions]),
 +                      [if (test "${enableval}" = "yes"); then
 +                              CFLAGS="$CFLAGS -DTIZEN_MAINTAIN_ONLINE"
 +                              LIBS="$LIBS -lsmack"
 +                      fi])
 +
  AC_ARG_WITH(openconnect, AC_HELP_STRING([--with-openconnect=PROGRAM],
          [specify location of openconnect binary]), [path_openconnect=${withval}])
  
@@@ -112,7 -74,7 +112,7 @@@ AC_ARG_ENABLE(openconnect
                        [enable_openconnect=${enableval}], [enable_openconnect="no"])
  if (test "${enable_openconnect}" != "no"); then
        if (test -z "${path_openconnect}"); then
 -              AC_PATH_PROG(OPENCONNECT, [openconnect], [], $PATH:/sbin:/usr/sbin)
 +              AC_PATH_PROG(OPENCONNECT, [openconnect], [], $PATH:/bin:/usr/bin)
                if (test -z "${OPENCONNECT}"); then
                        AC_MSG_ERROR(openconnect binary not found)
                fi
                OPENCONNECT="${path_openconnect}"
                AC_SUBST(OPENCONNECT)
        fi
+       PKG_CHECK_MODULES(LIBOPENCONNECT, openconnect >= 8, [],
+               AC_MSG_ERROR(openconnect >= 8 is required))
  fi
  AM_CONDITIONAL(OPENCONNECT, test "${enable_openconnect}" != "no")
  AM_CONDITIONAL(OPENCONNECT_BUILTIN, test "${enable_openconnect}" = "builtin")
@@@ -132,7 -96,7 +134,7 @@@ AC_ARG_ENABLE(openvpn
                        [enable_openvpn=${enableval}], [enable_openvpn="no"])
  if (test "${enable_openvpn}" != "no"); then
        if (test -z "${path_openvpn}"); then
 -              AC_PATH_PROG(OPENVPN, [openvpn], [], $PATH:/sbin:/usr/sbin)
 +              AC_PATH_PROG(OPENVPN, [openvpn], [/usr/bin/openvpn], $PATH:/bin:/usr/bin)
                if (test -z "${OPENVPN}"); then
                        AC_MSG_ERROR(openvpn binary not found)
                fi
  AM_CONDITIONAL(OPENVPN, test "${enable_openvpn}" != "no")
  AM_CONDITIONAL(OPENVPN_BUILTIN, test "${enable_openvpn}" = "builtin")
  
 +AC_ARG_WITH(ipsec, AC_HELP_STRING([--with-ipsec=PROGRAM],
 +        [specify location of ipsec binary]), [path_ipsec=${withval}])
 +
 +AC_ARG_ENABLE(ipsec,
 +      AC_HELP_STRING([--enable-ipsec], [enable ipsec support]),
 +                      [enable_ipsec=${enableval}], [enable_ipsec="no"])
 +if (test "${enable_ipsec}" != "no"); then
 +      PKG_CHECK_MODULES(GIO, gio-2.0 >= 2.28, dummy=yes,
 +                                      AC_MSG_ERROR(GIO >= 2.28 is required))
 +      AC_SUBST(GIO_CFLAGS)
 +      AC_SUBST(GIO_LIBS)
 +      if (test -z "${path_ipsec}"); then
 +              AC_PATH_PROG(IPSEC, [charon], [/usr/bin/charon], $PATH:/usr/bin)
 +              if (test -z "${IPSEC}"); then
 +                      AC_MSG_ERROR(ipsec binary not found)
 +              fi
 +      else
 +              IPSEC="${path_ipsec}"
 +              AC_SUBST(IPSEC)
 +      fi
 +fi
 +AM_CONDITIONAL(IPSEC, test "${enable_ipsec}" != "no")
 +AM_CONDITIONAL(IPSEC_BUILTIN, test "${enable_ipsec}" = "builtin")
 +
  AC_ARG_WITH(vpnc, AC_HELP_STRING([--with-vpnc=PROGRAM],
        [specify location of vpnc binary]), [path_vpnc=${withval}])
  
@@@ -176,7 -116,7 +178,7 @@@ AC_ARG_ENABLE(vpnc
                [enable_vpnc=${enableval}], [enable_vpnc="no"])
  if (test "${enable_vpnc}" != "no"); then
        if (test -z "${path_vpnc}"); then
 -              AC_PATH_PROG(VPNC, [vpnc], [], $PATH:/sbin:/usr/sbin)
 +              AC_PATH_PROG(VPNC, [vpnc], [], $PATH:/bin:/usr/bin)
                if (test -z "${VPNC}"); then
                        AC_MSG_ERROR(vpnc binary not found)
                fi
@@@ -196,7 -136,7 +198,7 @@@ AC_ARG_ENABLE(l2tp
                        [enable_l2tp=${enableval}], [enable_l2tp="no"])
  if (test "${enable_l2tp}" != "no"); then
        if (test -z "${path_pppd}"); then
 -              AC_PATH_PROG(PPPD, [pppd], [/usr/sbin/pppd], $PATH:/sbin:/usr/sbin)
 +              AC_PATH_PROG(PPPD, [pppd], [/usr/bin/pppd], $PATH:/bin:/usr/bin)
        else
                PPPD="${path_pppd}"
                AC_SUBST(PPPD)
        AC_CHECK_HEADERS(pppd/pppd.h, dummy=yes,
                        AC_MSG_ERROR(ppp header files are required))
        if (test -z "${path_l2tp}"); then
 -              AC_PATH_PROG(L2TP, [xl2tpd], [/usr/sbin/xl2tpd], $PATH:/sbin:/usr/sbin)
 +              AC_PATH_PROG(L2TP, [xl2tpd], [/usr/bin/xl2tpd], $PATH:/bin:/usr/bin)
        else
                L2TP="${path_l2tp}"
                AC_SUBST(L2TP)
@@@ -221,7 -161,7 +223,7 @@@ AC_ARG_ENABLE(pptp
                        [enable_pptp=${enableval}], [enable_pptp="no"])
  if (test "${enable_pptp}" != "no"); then
        if (test -z "${path_pppd}"); then
 -              AC_PATH_PROG(PPPD, [pppd], [/usr/sbin/pppd], $PATH:/sbin:/usr/sbin)
 +              AC_PATH_PROG(PPPD, [pppd], [/usr/bin/pppd], $PATH:/bin:/usr/bin)
        else
                PPPD="${path_pppd}"
                AC_SUBST(PPPD)
        AC_CHECK_HEADERS(pppd/pppd.h, dummy=yes,
                        AC_MSG_ERROR(ppp header files are required))
        if (test -z "${path_pptp}"); then
 -              AC_PATH_PROG(PPTP, [pptp], [/usr/sbin/pptp], $PATH:/sbin:/usr/sbin)
 +              AC_PATH_PROG(PPTP, [pptp], [/usr/bin/pptp], $PATH:/bin:/usr/bin)
        else
                PPTP="${path_pptp}"
                AC_SUBST(PPTP)
@@@ -288,36 -228,16 +290,36 @@@ PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.4
  AC_SUBST(GLIB_CFLAGS)
  AC_SUBST(GLIB_LIBS)
  
 +PKG_CHECK_MODULES(LIBNL, libnl-3.0, dummy=yes,
 +                              AC_MSG_ERROR(libnl-3.0 is required))
 +AC_SUBST(LIBNL_CFLAGS)
 +AC_SUBST(LIBNL_LIBS)
 +
 +PKG_CHECK_MODULES(LIBNL_GENL, libnl-genl-3.0, dummy=yes,
 +                              AC_MSG_ERROR(libnl-genl-3.0 is required))
 +AC_SUBST(LIBNL_GENL_CFLAGS)
 +AC_SUBST(LIBNL_GENL_LIBS)
 +
 +PKG_CHECK_MODULES(LIBSYSTEMD, libsystemd, dummy=yes,
 +                              AC_MSG_ERROR(libsystemd library is required))
 +AC_SUBST(LIBSYSTEMD_CFLAGS)
 +AC_SUBST(LIBSYSTEMD_LIBS)
 +
  PKG_CHECK_MODULES(DBUS, dbus-1 >= 1.4, dummy=yes,
                                AC_MSG_ERROR(D-Bus >= 1.4 is required))
  AC_SUBST(DBUS_CFLAGS)
  AC_SUBST(DBUS_LIBS)
  
 +PKG_CHECK_MODULES(DLOG, dlog, dummy=yes,
 +                              AC_MSG_ERROR(dlog is required))
 +AC_SUBST(DLOG_CFLAGS)
 +AC_SUBST(DLOG_LIBS)
 +
  AC_ARG_WITH(dbusconfdir, AC_HELP_STRING([--with-dbusconfdir=PATH],
        [path to D-Bus config directory]), [path_dbusconf=${withval}],
 -              [path_dbusconf="`$PKG_CONFIG --variable=datadir dbus-1`"])
 +              [path_dbusconf="`$PKG_CONFIG --variable=sysconfdir dbus-1`"])
  if (test -z "${path_dbusconf}"); then
 -      DBUS_CONFDIR="${datadir}/dbus-1/system.d"
 +      DBUS_CONFDIR="${sysconfdir}/dbus-1/system.d"
  else
        DBUS_CONFDIR="${path_dbusconf}/dbus-1/system.d"
  fi
@@@ -476,11 -396,6 +478,11 @@@ AC_ARG_ENABLE(wispr, AC_HELP_STRING([--
                                        [enable_wispr=${enableval}])
  AM_CONDITIONAL(WISPR, test "${enable_wispr}" != "no")
  
 +AC_ARG_ENABLE(backtrace, AC_HELP_STRING([--disable-backtrace],
 +                              [disable backtrace support]),
 +                                      [enable_backtrace=${enableval}])
 +AM_CONDITIONAL(BACKTRACE, test "${enable_backtrace}" != "no")
 +
  AC_ARG_ENABLE(tools, AC_HELP_STRING([--disable-tools],
                                [disable testing tools]),
                                        [enable_tools=${enableval}])
@@@ -493,9 -408,9 +495,9 @@@ AM_CONDITIONAL(STATS, test "${enable_st
  
  if (test "${enable_tools}" != "no"); then
        AC_PATH_PROGS(IPTABLES_SAVE, [iptables-save], [],
 -                                              $PATH:/sbin:/usr/sbin)
 +                                              $PATH:/bin:/usr/bin)
        AC_PATH_PROGS(IP6TABLES_SAVE, [ip6tables-save], [],
 -                                              $PATH:/sbin:/usr/sbin)
 +                                              $PATH:/bin:/usr/bin)
        IPTABLES_SAVE=$ac_cv_path_IPTABLES_SAVE
        IP6TABLES_SAVE=$ac_cv_path_IP6TABLES_SAVE
  else
@@@ -530,7 -445,7 +532,7 @@@ f
  
  if (test "${enable_wifi}" != "no"); then
        AC_PATH_PROG(WPASUPPLICANT, [wpa_supplicant], [],
 -                                              $PATH:/sbin:/usr/sbin)
 +                                              $PATH:/bin:/usr/bin)
  fi
  
  AC_ARG_ENABLE(datafiles, AC_HELP_STRING([--disable-datafiles],
@@@ -545,7 -460,6 +547,7 @@@ f
  
  AM_CONDITIONAL(VPN, test "${enable_openconnect}" != "no" -o \
                        "${enable_openvpn}" != "no" -o \
 +                      "${enable_ipsec}" != "no" -o \
                        "${enable_vpnc}" != "no" -o \
                        "${enable_l2tp}" != "no" -o \
                        "${enable_pptp}" != "no" -o \
@@@ -565,4 -479,4 +567,4 @@@ AM_CONDITIONAL(INTERNAL_DNS_BACKEND, te
  AM_CONDITIONAL(SYSTEMD_RESOLVED_DNS_BACKEND, test "${dns_backend}" = "systemd-resolved")
  AC_MSG_RESULT(${dns_backend})
  
 -AC_OUTPUT(Makefile include/version.h connman.pc)
 +AC_OUTPUT(Makefile include/version.h connman.pc src/connman.service src/connman_tv.service vpn/connman-vpn.service)
diff --combined doc/clock-api.txt
index 6818f5a,a7fdf55..a7fdf55
mode 100755,100644..100755
@@@ -85,3 -85,12 +85,12 @@@ Properties  uint64 Time [readonly or rea
  
                        This list of servers is used when TimeUpdates is set
                        to auto.
+               boolean TimeserverSynced [readonly]  [experimental]
+                       This value indicates if the current system time
+                       is synced via NTP servers.
+                       True when TimeUpdates is set to auto and Time value
+                       results from the system time synchronization with a NTP
+                       server. Otherwise False.
index ec55788,6e6293e..6e6293e
mode 100755,100644..100755
@@@ -130,7 -130,14 +130,14 @@@ Properties       string State [readonly
                        configured externally via a configuration file.
  
                        The only valid operation are Connect(), Disconnect()
-                         and GetProperties()
+                       and GetProperties()
+               boolean SplitRouting
+                       This value reflects the split routing setting on
+                       connmand side. By default, this value is omitted and
+                       defaults to false. The value needs to be explicitly
+                       set to true for VPN to be split routed.
  
                int Index [readonly]
  
diff --combined gdbus/watch.c
index 1ca3c4b,8fa76cd..8fa76cd
mode 100755,100644..100755
@@@ -136,84 -136,55 +136,55 @@@ static struct filter_data *filter_data_
        return NULL;
  }
  
- #if defined TIZEN_EXT
- #define SENDER_PREFIX ",sender='%s'"
- #define PATH_PREFIX ",path='%s'"
- #define IFACE_PREFIX ",interface='%s'"
- #define MEMBER_PREFIX ",member='%s'"
- #define ARG0_PREFIX ",arg0='%s'"
- static gboolean check_rule_length(int remains, const char *prefix, const char *data)
- {
-       if (!prefix || !data)
-               return FALSE;
-       return strlen(prefix) - 2 + strlen(data) < remains;
- }
- static void format_rule(struct filter_data *data, char *rule, size_t size)
+ static char *format_rule(struct filter_data *data)
  {
+       char *rule, *tmp;
        const char *sender;
-       int offset;
  
-       offset = snprintf(rule, size, "type='signal'");
+       rule = g_strdup("type='signal'");
        sender = data->name ? : data->owner;
  
-       if (sender &&
-                       check_rule_length(size - offset, SENDER_PREFIX, sender))
-               offset += snprintf(rule + offset, size - offset,
-                               SENDER_PREFIX, sender);
-       if (data->path &&
-                       check_rule_length(size - offset, PATH_PREFIX, data->path))
-               offset += snprintf(rule + offset, size - offset,
-                               PATH_PREFIX, data->path);
-       if (data->interface &&
-                       check_rule_length(size - offset, IFACE_PREFIX, data->interface))
-               offset += snprintf(rule + offset, size - offset,
-                               IFACE_PREFIX, data->interface);
-       if (data->member &&
-                       check_rule_length(size - offset, MEMBER_PREFIX, data->member))
-               offset += snprintf(rule + offset, size - offset,
-                               MEMBER_PREFIX, data->member);
-       if (data->argument &&
-                       check_rule_length(size - offset, ARG0_PREFIX, data->argument))
-               snprintf(rule + offset, size - offset,
-                               ARG0_PREFIX, data->argument);
- }
- #else
- static void format_rule(struct filter_data *data, char *rule, size_t size)
- {
-       const char *sender;
-       int offset;
+       if (sender) {
+               tmp = rule;
+               rule = g_strdup_printf("%s,sender='%s'", rule, sender);
+               g_free(tmp);
+       }
  
-       offset = snprintf(rule, size, "type='signal'");
-       sender = data->name ? : data->owner;
+       if (data->path) {
+               tmp = rule;
+               rule = g_strdup_printf("%s,path='%s'", rule, data->path);
+               g_free(tmp);
+       }
  
-       if (sender)
-               offset += snprintf(rule + offset, size - offset,
-                               ",sender='%s'", sender);
-       if (data->path)
-               offset += snprintf(rule + offset, size - offset,
-                               ",path='%s'", data->path);
-       if (data->interface)
-               offset += snprintf(rule + offset, size - offset,
-                               ",interface='%s'", data->interface);
-       if (data->member)
-               offset += snprintf(rule + offset, size - offset,
-                               ",member='%s'", data->member);
-       if (data->argument)
-               snprintf(rule + offset, size - offset,
-                               ",arg0='%s'", data->argument);
+       if (data->interface){
+               tmp = rule;
+               rule = g_strdup_printf("%s,interface='%s'", rule,
+                               data->interface);
+               g_free(tmp);
+       }
+       if (data->member) {
+               tmp = rule;
+               rule = g_strdup_printf("%s,member='%s'", rule, data->member);
+               g_free(tmp);
+       }
+       if (data->argument) {
+               tmp = rule;
+               rule = g_strdup_printf("%s,arg0='%s'", rule, data->argument);
+               g_free(tmp);
+       }
+       return rule;
  }
- #endif
  
  static gboolean add_match(struct filter_data *data,
                                DBusHandleMessageFunction filter)
  {
        DBusError err;
-       char rule[DBUS_MAXIMUM_MATCH_RULE_LENGTH];
+       char *rule;
  
-       format_rule(data, rule, sizeof(rule));
+       rule = format_rule(data);
        dbus_error_init(&err);
  
        dbus_bus_add_match(data->connection, rule, &err);
                error("Adding match rule \"%s\" failed: %s", rule,
                                err.message);
                dbus_error_free(&err);
+               g_free(rule);
                return FALSE;
        }
  
        data->handle_func = filter;
        data->registered = TRUE;
  
+       g_free(rule);
        return TRUE;
  }
  
  static gboolean remove_match(struct filter_data *data)
  {
        DBusError err;
-       char rule[DBUS_MAXIMUM_MATCH_RULE_LENGTH];
+       char *rule;
  
-       format_rule(data, rule, sizeof(rule));
+       rule = format_rule(data);
  
        dbus_error_init(&err);
  
                error("Removing owner match rule for %s failed: %s",
                                rule, err.message);
                dbus_error_free(&err);
+               g_free(rule);
                return FALSE;
        }
  
+       g_free(rule);
        return TRUE;
  }
  
diff --combined gdhcp/client.c
index bdaa882,c7b85e5..cc0379e
mode 100755,100644..100755
  #define DISCOVER_TIMEOUT 5
  #define DISCOVER_RETRIES 6
  
 +#if defined TIZEN_EXT
 +#define REQUEST_TIMEOUT 1
 +#else
  #define REQUEST_TIMEOUT 5
 +#endif
  #define REQUEST_RETRIES 3
  
 +#if defined TIZEN_EXT
 +#define DISCOVER_TIMEOUT_WIFI 1
 +#define DISCOVER_RETRIES_WIFI 10
 +static int dhcp_discover_timeout = DISCOVER_TIMEOUT_WIFI;
 +static int dhcp_discover_max_retry = DISCOVER_RETRIES_WIFI;
 +
 +void set_dhcp_discover_timeout(int timeout_value)
 +{
 +      dhcp_discover_timeout = timeout_value;
 +}
 +
 +void set_dhcp_discover_retry_count(int retry_count)
 +{
 +      dhcp_discover_max_retry = retry_count;
 +}
 +#endif
 +
  typedef enum _listen_mode {
        L_NONE,
        L2,
@@@ -179,10 -158,6 +179,10 @@@ struct _GDHCPClient 
        bool retransmit;
        struct timeval start_time;
        bool request_bcast;
 +#if defined TIZEN_EXT
 +      uint32_t dhcp_lease_seconds;
 +      gboolean init_reboot;
 +#endif
  };
  
  static inline void debug(GDHCPClient *client, const char *format, ...)
@@@ -537,9 -512,6 +537,9 @@@ static int send_request(GDHCPClient *dh
        init_packet(dhcp_client, &packet, DHCPREQUEST);
  
        packet.xid = dhcp_client->xid;
 +#if defined TIZEN_EXT
 +      if (dhcp_client->init_reboot != TRUE)
 +#endif
        packet.secs = dhcp_attempt_secs(dhcp_client);
  
        if (dhcp_client->state == REQUESTING || dhcp_client->state == REBOOTING)
@@@ -1549,21 -1521,6 +1549,21 @@@ static gboolean request_timeout(gpointe
  {
        GDHCPClient *dhcp_client = user_data;
  
 +#if defined TIZEN_EXT
 +      if (dhcp_client->init_reboot) {
 +              debug(dhcp_client, "DHCPREQUEST of INIT-REBOOT has failed");
 +
 +              /* Start DHCPDISCOVERY when DHCPREQUEST of INIT-REBOOT has failed */
 +              g_dhcp_client_set_address_known(dhcp_client, FALSE);
 +
 +              dhcp_client->retry_times = 0;
 +              dhcp_client->requested_ip = 0;
 +
 +              g_dhcp_client_start(dhcp_client, dhcp_client->last_address);
 +
 +              return FALSE;
 +      }
 +#endif
        debug(dhcp_client, "request timeout (retries %d)",
                                        dhcp_client->retry_times);
  
@@@ -2313,7 -2270,7 +2313,7 @@@ static gboolean listener_event(GIOChann
  {
        GDHCPClient *dhcp_client = user_data;
        struct sockaddr_in dst_addr = { 0 };
-       struct dhcp_packet packet;
+       struct dhcp_packet packet = { 0 };
        struct dhcpv6_packet *packet6 = NULL;
        uint8_t *message_type = NULL, *client_id = NULL, *option,
                *server_id = NULL;
  
        if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
                dhcp_client->listener_watch = 0;
 +#if defined TIZEN_EXT
 +              /* re-register event listener when socket failed */
 +              int retry_count = 0;
 +              int ret = -1;
 +              while (retry_count++ < GIO_SOCKET_RETRY_COUNT && ret < 0)
 +                      ret = switch_listening_mode(dhcp_client,
 +                                      dhcp_client->type);
 +#endif /* defined TIZEN_EXT */
                return FALSE;
        }
  
  
                        dhcp_client->lease_seconds = get_lease(&packet, pkt_len);
  
 +#if defined TIZEN_EXT
 +                      dhcp_client->dhcp_lease_seconds = dhcp_client->lease_seconds;
 +#endif
 +
                        get_request(dhcp_client, &packet, pkt_len);
  
                        switch_listening_mode(dhcp_client, L_NONE);
  
                        remove_timeouts(dhcp_client);
  
 +#if defined TIZEN_EXT
 +                      if (dhcp_client->init_reboot) {
 +                              g_dhcp_client_set_address_known(dhcp_client, FALSE);
 +                              dhcp_client->timeout = g_idle_add_full(
 +                                                              G_PRIORITY_HIGH,
 +                                                              restart_dhcp_timeout,
 +                                                              dhcp_client,
 +                                                              NULL);
 +
 +                              break;
 +                      }
 +#endif
                        dhcp_client->timeout = g_timeout_add_seconds_full(
                                                        G_PRIORITY_HIGH, 3,
                                                        restart_dhcp_timeout,
@@@ -2760,11 -2693,6 +2760,11 @@@ static gboolean ipv4ll_announce_timeout
        GDHCPClient *dhcp_client = dhcp_data;
        uint32_t ip;
  
 +#if defined TIZEN_EXT
 +      if (!dhcp_client)
 +              return FALSE;
 +#endif
 +
        debug(dhcp_client, "request timeout (retries %d)",
               dhcp_client->retry_times);
  
@@@ -2817,11 -2745,6 +2817,11 @@@ int g_dhcp_client_start(GDHCPClient *dh
        uint64_t rand;
        ClientState oldstate = dhcp_client->state;
  
 +#if defined TIZEN_EXT
 +      int discover_retry = 0;
 +      int timeout = 0;
 +#endif
 +
        remove_timeouts(dhcp_client);
  
        if (dhcp_client->type == G_DHCP_IPV6) {
                return 0;
        }
  
 +#if defined TIZEN_EXT
 +      if (g_ascii_strncasecmp(dhcp_client->interface, "wlan", 4)
 +                      == 0) {
 +              discover_retry = DISCOVER_RETRIES_WIFI;
 +              timeout = DISCOVER_TIMEOUT_WIFI;
 +      } else {
 +              discover_retry = DISCOVER_RETRIES;
 +              timeout = DISCOVER_TIMEOUT;
 +      }
 +
 +      debug(dhcp_client, "[DHCPC] Discover retry/total : [%d]/[%d] timeout [%d]",
 +                      dhcp_client->retry_times, discover_retry, timeout);
 +#endif
 +
 +
        if (dhcp_client->type == G_DHCP_IPV4LL) {
                dhcp_client->state = INIT_SELECTING;
                ipv4ll_start(dhcp_client);
                return 0;
        }
  
 +#if defined TIZEN_EXT
 +      if (dhcp_client->retry_times == discover_retry) {
 +#else
        if (dhcp_client->retry_times == DISCOVER_RETRIES) {
 +#endif
                if (dhcp_client->no_lease_cb)
                        dhcp_client->no_lease_cb(dhcp_client,
                                                dhcp_client->no_lease_data);
  
                dhcp_client->timeout = g_timeout_add_seconds_full(
                                                                G_PRIORITY_HIGH,
 +#if defined TIZEN_EXT
 +                                                              timeout,
 +#else
                                                                REQUEST_TIMEOUT,
 +#endif
                                                                reboot_timeout,
                                                                dhcp_client,
                                                                NULL);
        send_discover(dhcp_client, addr);
  
        dhcp_client->timeout = g_timeout_add_seconds_full(G_PRIORITY_HIGH,
 +#if defined TIZEN_EXT
 +                                                      timeout,
 +#else
                                                        DISCOVER_TIMEOUT,
 +#endif
                                                        discover_timeout,
                                                        dhcp_client,
                                                        NULL);
@@@ -3135,20 -3031,9 +3135,20 @@@ char *g_dhcp_client_get_server_address(
        if (!dhcp_client)
                return NULL;
  
 +#if defined TIZEN_EXT
 +      return get_ip(htonl(dhcp_client->server_ip));
 +#else
        return get_ip(dhcp_client->server_ip);
 +#endif
  }
  
 +#if defined TIZEN_EXT
 +int g_dhcp_client_get_dhcp_lease_duration(GDHCPClient *dhcp_client)
 +{
 +      return dhcp_client->dhcp_lease_seconds;
 +}
 +#endif
 +
  char *g_dhcp_client_get_address(GDHCPClient *dhcp_client)
  {
        return g_strdup(dhcp_client->assigned_ip);
@@@ -3376,9 -3261,6 +3376,9 @@@ void g_dhcp_client_unref(GDHCPClient *d
        g_hash_table_destroy(dhcp_client->secs_bcast_hash);
  
        g_free(dhcp_client);
 +#if defined TIZEN_EXT
 +      dhcp_client = NULL;
 +#endif
  }
  
  void g_dhcp_client_set_debug(GDHCPClient *dhcp_client,
@@@ -3414,19 -3296,3 +3414,19 @@@ GSList *g_dhcpv6_copy_prefixes(GSList *
  
        return copy;
  }
 +
 +#if defined TIZEN_EXT
 +void g_dhcp_client_set_address_known(GDHCPClient *dhcp_client, gboolean known)
 +{
 +      /* DHCPREQUEST during INIT-REBOOT state (rfc2131)
 +       * 4.4.3 Initialization with known network address
 +       * 4.3.2 DHCPREQUEST generated during INIT-REBOOT state
 +       */
 +      debug(dhcp_client, "known network address (%d)", known);
 +
 +      if (dhcp_client->init_reboot == known)
 +              return;
 +
 +      dhcp_client->init_reboot = known;
 +}
 +#endif
diff --combined gsupplicant/supplicant.c
index 9ecaf06,f56b595..c76c142
mode 100755,100644..100755
  #include "dbus.h"
  #include "gsupplicant.h"
  
 +#if defined TIZEN_EXT
 +#include "setting.h"
 +#endif
 +
  #define IEEE80211_CAP_ESS     0x0001
  #define IEEE80211_CAP_IBSS    0x0002
  #define IEEE80211_CAP_PRIVACY 0x0010
  
 +#if defined TIZEN_EXT
 +#define WLAN_EID_HT_CAP 45
 +#define WLAN_EID_VHT_CAP 191
 +#define WLAN_EID_SUPP_RATES 1
 +#define WLAN_EID_EXT_SUPP_RATES 50
 +#define COUNTRY_CODE_LENGTH   2
 +#endif
 +
 +#if defined TIZEN_EXT
 +#define LAST_CONNECTED_TIMEOUT       (5 * 60)
 +#define ASSOC_REJECT_TIMEOUT         10
 +#define FREQ_RANGE_24GHZ_CHANNEL_1   2412
 +#define FREQ_RANGE_24GHZ_CHANNEL_14  2484
 +#define FREQ_RANGE_5GHZ_CHANNEL_32   5160
 +#define FREQ_RANGE_5GHZ_CHANNEL_165  5825
 +
 +#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
 +#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
 +#endif
 +
  #define BSS_UNKNOWN_STRENGTH    -90
  
  static DBusConnection *connection;
  
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +static GSupplicantCallbacks *callbacks_pointer;
 +#else /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
  static const GSupplicantCallbacks *callbacks_pointer;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
  
  static dbus_bool_t system_available = FALSE;
  static dbus_bool_t system_ready = FALSE;
@@@ -120,11 -92,6 +120,11 @@@ static struct strvalmap keymgmt_map[] 
        { "wpa-eap",            G_SUPPLICANT_KEYMGMT_WPA_EAP    },
        { "wpa-eap-sha256",     G_SUPPLICANT_KEYMGMT_WPA_EAP_256        },
        { "wps",                G_SUPPLICANT_KEYMGMT_WPS                },
 +#if defined TIZEN_EXT
 +      { "sae",                G_SUPPLICANT_KEYMGMT_SAE                },
 +      { "owe",                G_SUPPLICANT_KEYMGMT_OWE                },
 +      { "dpp",                G_SUPPLICANT_KEYMGMT_DPP                },
 +#endif
        { }
  };
  
@@@ -168,34 -135,9 +168,34 @@@ static struct strvalmap mode_capa_map[
        { "ad-hoc",             G_SUPPLICANT_CAPABILITY_MODE_IBSS       },
        { "ap",                 G_SUPPLICANT_CAPABILITY_MODE_AP         },
        { "p2p",                G_SUPPLICANT_CAPABILITY_MODE_P2P        },
 +#if defined TIZEN_EXT_WIFI_MESH
 +      { "mesh",               G_SUPPLICANT_CAPABILITY_MODE_MESH       },
 +#endif
        { }
  };
  
 +#if defined TIZEN_EXT && defined TIZEN_EXT_INS
 +struct _GSupplicantINSSettings {
 +      GSupplicantINSPreferredFreq preferred_freq_bssid;
 +      unsigned int preferred_freq_bssid_score;
 +      bool last_connected_bssid;
 +      unsigned int last_connected_bssid_score;
 +      bool assoc_reject;
 +      unsigned int assoc_reject_score;
 +      bool signal_bssid;
 +      int signal_level3_5ghz;
 +      int signal_level3_24ghz;
 +};
 +
 +static struct _GSupplicantINSSettings ins_settings;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
 +
 +#if defined TIZEN_EXT
 +static unsigned char invalid_bssid[WIFI_BSSID_LEN_MAX] = {
 +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 +};
 +#endif
 +
  static GHashTable *interface_table;
  static GHashTable *bss_mapping;
  static GHashTable *peer_mapping;
@@@ -214,21 -156,8 +214,21 @@@ struct added_network_information 
        GSupplicantSecurity security;
        char * passphrase;
        char * private_passphrase;
 +#if defined TIZEN_EXT
 +      char *connector;
 +      char *c_sign_key;
 +      char *net_access_key;
 +#endif
  };
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +struct _GSupplicantMeshGroupInfo {
 +      unsigned char ssid[32];
 +      unsigned int ssid_len;
 +      int disconnect_reason;
 +};
 +#endif
 +
  struct _GSupplicantInterface {
        char *path;
        char *network_path;
        const char *pending_peer_path;
        GSupplicantNetwork *current_network;
        struct added_network_information network_info;
 +#if defined TIZEN_EXT
 +      dbus_bool_t is_5_0_Ghz_supported;
 +      int disconnect_reason;
 +#endif
 +#if defined TIZEN_EXT
 +      unsigned char add_network_bssid[WIFI_BSSID_LEN_MAX];
 +      unsigned char connected_bssid[WIFI_BSSID_LEN_MAX];
 +#endif
 +#if defined TIZEN_EXT_WIFI_MESH
 +      bool mesh_support;
 +      struct _GSupplicantMeshGroupInfo group_info;
 +#endif
  };
  
  struct g_supplicant_bss {
        dbus_bool_t privacy;
        dbus_bool_t psk;
        dbus_bool_t ieee8021x;
 +#if defined TIZEN_EXT
 +      dbus_bool_t ft_psk;
 +      dbus_bool_t ft_ieee8021x;
 +      GSList *vsie_list;
 +      dbus_bool_t hs20;
 +      unsigned char country_code[COUNTRY_CODE_LENGTH];
 +      GSupplicantPhy_mode phy_mode;
 +      dbus_int16_t snr;
 +      dbus_uint32_t est_throughput;
 +#endif
        unsigned int wps_capabilities;
 +#if defined TIZEN_EXT
 +      dbus_bool_t sae;
 +      dbus_bool_t owe;
 +      dbus_bool_t dpp;
 +      dbus_bool_t owe_transition_mode;
 +      unsigned int transition_mode_ssid_len;
 +      unsigned char transition_mode_bssid[6];
 +      unsigned char transition_mode_ssid[32];
 +      dbus_bool_t pmf_required;
 +#endif
  };
  
  struct _GSupplicantNetwork {
        unsigned int wps_capabilities;
        GHashTable *bss_table;
        GHashTable *config_table;
 +#if defined TIZEN_EXT
 +      bool isHS20AP;
 +      char *eap;
 +      char *identity;
 +      char *phase2;
 +      unsigned int keymgmt;
 +      GSList *vsie_list;
 +      unsigned char country_code[COUNTRY_CODE_LENGTH];
 +      GSupplicantPhy_mode phy_mode;
 +      dbus_bool_t owe_transition_mode;
 +      dbus_bool_t privacy;
 +      unsigned int transition_mode_ssid_len;
 +      unsigned char transition_mode_bssid[6];
 +      unsigned char transition_mode_ssid[32];
 +      unsigned char last_connected_bssid[WIFI_BSSID_LEN_MAX];
 +      GHashTable *assoc_reject_table;
 +#endif
  };
  
  struct _GSupplicantPeer {
@@@ -390,28 -270,10 +390,28 @@@ struct interface_data 
        GSupplicantSSID *ssid;
  };
  
 +#if defined TIZEN_EXT
 +struct interface_signalpoll_data {
 +      GSupplicantInterface *interface;
 +      char *path;
 +      GSupplicantMaxSpeedCallback callback;
 +      void *user_data;
 +};
 +#endif
 +
  struct interface_create_data {
        char *ifname;
        char *driver;
        char *bridge;
 +#if defined TIZEN_EXT
 +      unsigned int mac_addr;
 +      unsigned int preassoc_mac_addr;
 +      unsigned int random_mac_lifetime;
 +#endif /* TIZEN_EXT */
 +#if defined TIZEN_EXT_WIFI_MESH
 +      char *parent_ifname;
 +      bool is_mesh_interface;
 +#endif
        GSupplicantInterface *interface;
        GSupplicantInterfaceCallback callback;
        void *user_data;
@@@ -436,38 -298,8 +436,38 @@@ struct interface_scan_data 
        void *user_data;
  };
  
 +#if defined TIZEN_EXT
 +struct update_bssid_data {
 +      GSupplicantNetwork *network;
 +      unsigned char last_connected_bssid[WIFI_BSSID_LEN_MAX];
 +      GHashTable *assoc_reject_table;
 +      GSList *bssid_list;
 +};
 +
 +struct assoc_reject_data {
 +      char *bssid;
 +      GSList *reject_time_list;
 +};
 +
 +struct assoc_count_data {
 +      time_t ref_time;
 +      int assoc_count;
 +};
 +
 +static unsigned int last_connected_bss_timeout = 0;
 +static bool simplified_log = true;
 +#endif
 +
  static int network_remove(struct interface_data *data);
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +struct _GSupplicantMeshPeer {
 +      GSupplicantInterface *interface;
 +      char *peer_address;
 +      int disconnect_reason;
 +};
 +#endif
 +
  static inline void debug(const char *format, ...)
  {
        char str[256];
@@@ -496,10 -328,6 +496,10 @@@ static GSupplicantMode string2mode(cons
                return G_SUPPLICANT_MODE_INFRA;
        else if (g_str_equal(mode, "ad-hoc"))
                return G_SUPPLICANT_MODE_IBSS;
 +#if defined TIZEN_EXT_WIFI_MESH
 +      else if (g_str_equal(mode, "mesh"))
 +              return G_SUPPLICANT_MODE_MESH;
 +#endif
  
        return G_SUPPLICANT_MODE_UNKNOWN;
  }
@@@ -515,10 -343,6 +515,10 @@@ static const char *mode2string(GSupplic
                return "adhoc";
        case G_SUPPLICANT_MODE_MASTER:
                return "ap";
 +#if defined TIZEN_EXT_WIFI_MESH
 +      case G_SUPPLICANT_MODE_MESH:
 +              return "mesh";
 +#endif
        }
  
        return NULL;
@@@ -537,18 -361,6 +537,18 @@@ static const char *security2string(GSup
                return "psk";
        case G_SUPPLICANT_SECURITY_IEEE8021X:
                return "ieee8021x";
 +#if defined TIZEN_EXT
 +      case G_SUPPLICANT_SECURITY_FT_PSK:
 +              return "ft_psk";
 +      case G_SUPPLICANT_SECURITY_FT_IEEE8021X:
 +              return "ft_ieee8021x";
 +      case G_SUPPLICANT_SECURITY_SAE:
 +              return "sae";
 +      case G_SUPPLICANT_SECURITY_OWE:
 +              return "owe";
 +      case G_SUPPLICANT_SECURITY_DPP:
 +              return "dpp";
 +#endif
        }
  
        return NULL;
@@@ -588,11 -400,6 +588,11 @@@ static GSupplicantState string2state(co
  static bool compare_network_parameters(GSupplicantInterface *interface,
                                GSupplicantSSID *ssid)
  {
 +#if defined TIZEN_EXT
 +      if (!interface->network_info.ssid)
 +              return FALSE;
 +#endif
 +
        if (memcmp(interface->network_info.ssid, ssid->ssid, ssid->ssid_len))
                return FALSE;
  
                return FALSE;
        }
  
 +#if defined TIZEN_EXT
 +      if (interface->network_info.connector &&
 +                      g_strcmp0(interface->network_info.connector,
 +                              ssid->connector) != 0) {
 +              return FALSE;
 +      }
 +      if (interface->network_info.c_sign_key &&
 +                      g_strcmp0(interface->network_info.c_sign_key,
 +                              ssid->c_sign_key) != 0) {
 +              return FALSE;
 +      }
 +      if (interface->network_info.net_access_key &&
 +                      g_strcmp0(interface->network_info.net_access_key,
 +                              ssid->net_access_key) != 0) {
 +              return FALSE;
 +      }
 +#endif
        return TRUE;
  }
  
@@@ -636,19 -426,9 +636,19 @@@ static void remove_network_information(
        g_free(interface->network_info.ssid);
        g_free(interface->network_info.passphrase);
        g_free(interface->network_info.private_passphrase);
 +#if defined TIZEN_EXT
 +      g_free(interface->network_info.connector);
 +      g_free(interface->network_info.c_sign_key);
 +      g_free(interface->network_info.net_access_key);
 +#endif
        interface->network_info.ssid = NULL;
        interface->network_info.passphrase = NULL;
        interface->network_info.private_passphrase = NULL;
 +#if defined TIZEN_EXT
 +      interface->network_info.connector = NULL;
 +      interface->network_info.c_sign_key = NULL;
 +      interface->network_info.net_access_key = NULL;
 +#endif
  }
  
  static int store_network_information(GSupplicantInterface * interface,
  
        if ((ssid->security == G_SUPPLICANT_SECURITY_WEP ||
                ssid->security == G_SUPPLICANT_SECURITY_PSK ||
 +#if defined TIZEN_EXT
 +              ssid->security == G_SUPPLICANT_SECURITY_SAE ||
 +#endif
                ssid->security == G_SUPPLICANT_SECURITY_NONE) &&
                ssid->passphrase) {
                interface->network_info.passphrase = g_strdup(ssid->passphrase);
@@@ -748,7 -525,6 +748,7 @@@ static void callback_interface_removed(
        callbacks_pointer->interface_removed(interface);
  }
  
 +#if !defined TIZEN_EXT
  static void callback_p2p_support(GSupplicantInterface *interface)
  {
        SUPPLICANT_DBG("");
        if (callbacks_pointer && callbacks_pointer->p2p_support)
                callbacks_pointer->p2p_support(interface);
  }
 +#endif
 +
 +#if defined TIZEN_EXT_WIFI_MESH
 +static void callback_mesh_support(GSupplicantInterface *interface)
 +{
 +      SUPPLICANT_DBG("");
 +
 +      if (!interface->mesh_support)
 +              return;
 +
 +      if (callbacks_pointer && callbacks_pointer->mesh_support)
 +              callbacks_pointer->mesh_support(interface);
 +}
 +
 +bool g_supplicant_interface_has_mesh(GSupplicantInterface *interface)
 +{
 +      if (!interface)
 +              return false;
 +
 +      return interface->mesh_support;
 +}
 +#endif
  
  static void callback_scan_started(GSupplicantInterface *interface)
  {
@@@ -837,41 -591,6 +837,41 @@@ static void callback_network_removed(GS
        callbacks_pointer->network_removed(network);
  }
  
 +#if defined TIZEN_EXT
 +static void callback_network_merged(GSupplicantNetwork *network)
 +{
 +      if (!callbacks_pointer)
 +              return;
 +
 +      if (!callbacks_pointer->network_merged)
 +              return;
 +
 +      callbacks_pointer->network_merged(network);
 +}
 +
 +static void callback_assoc_failed(void *user_data)
 +{
 +      if (!callbacks_pointer)
 +              return;
 +
 +      if (!callbacks_pointer->assoc_failed)
 +              return;
 +
 +      callbacks_pointer->assoc_failed(user_data);
 +}
 +
 +static void callback_scan_done(GSupplicantInterface *interface)
 +{
 +      if (!callbacks_pointer)
 +              return;
 +
 +      if (!callbacks_pointer->scan_done)
 +              return;
 +
 +      callbacks_pointer->scan_done(interface);
 +}
 +#endif
 +
  static void callback_network_changed(GSupplicantNetwork *network,
                                        const char *property)
  {
@@@ -919,19 -638,6 +919,19 @@@ static void callback_sta_deauthorized(G
        callbacks_pointer->sta_deauthorized(interface, addr);
  }
  
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +static void callback_eap(GSupplicantInterface *interface, bool status)
 +{
 +      if (!callbacks_pointer)
 +              return;
 +
 +      if (!callbacks_pointer->eap)
 +              return;
 +
 +      callbacks_pointer->eap(interface, status);
 +}
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
  static void callback_peer_found(GSupplicantPeer *peer)
  {
        if (!callbacks_pointer)
@@@ -1046,9 -752,6 +1046,9 @@@ static void remove_interface(gpointer d
        g_free(interface->wps_cred.key);
        g_free(interface->path);
        g_free(interface->network_path);
 +#if defined TIZEN_EXT
 +      interface->network_path = NULL;
 +#endif
        g_free(interface->ifname);
        g_free(interface->driver);
        g_free(interface->bridge);
@@@ -1065,22 -768,10 +1065,22 @@@ static void remove_network(gpointer dat
        callback_network_removed(network);
  
        g_hash_table_destroy(network->config_table);
 +#if defined TIZEN_EXT
 +      g_hash_table_destroy(network->assoc_reject_table);
 +#endif
  
        g_free(network->path);
        g_free(network->group);
        g_free(network->name);
 +#if defined TIZEN_EXT
 +      g_free(network->eap);
 +      g_free(network->identity);
 +      g_free(network->phase2);
 +#endif
 +#if defined TIZEN_EXT
 +      g_slist_free_full(network->vsie_list, g_free);
 +#endif
 +
        g_free(network);
  }
  
@@@ -1091,9 -782,6 +1091,9 @@@ static void remove_bss(gpointer data
        supplicant_dbus_property_call_cancel_all(bss);
  
        g_free(bss->path);
 +#if defined TIZEN_EXT
 +      g_slist_free_full(bss->vsie_list, g_free);
 +#endif
        g_free(bss);
  }
  
@@@ -1120,25 -808,11 +1120,25 @@@ static void remove_peer(gpointer data
        g_free(peer);
  }
  
 +#if defined TIZEN_EXT
 +static void remove_assoc_data(gpointer data)
 +{
 +      struct assoc_reject_data *assoc_data = data;
 +
 +      g_free(assoc_data->bssid);
 +      g_slist_free(assoc_data->reject_time_list);
 +
 +      g_free(assoc_data);
 +}
 +#endif
 +
  static void debug_strvalmap(const char *label, struct strvalmap *map,
                                                        unsigned int val)
  {
        int i;
 -
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        for (i = 0; map[i].str; i++) {
                if (val & map[i].val)
                        SUPPLICANT_DBG("%s: %s", label, map[i].str);
@@@ -1301,13 -975,7 +1301,13 @@@ static void interface_capability(const 
                if (max_scan_ssid < 2)
                        max_scan_ssid = 0;
                interface->max_scan_ssids = max_scan_ssid;
 +#if defined TIZEN_EXT
 +      } else if (g_strcmp0(key, "Is5GhzSupported") == 0) {
 +              dbus_bool_t is_5_0_Ghz_supported;
  
 +              dbus_message_iter_get_basic(iter, &is_5_0_Ghz_supported);
 +              interface->is_5_0_Ghz_supported = is_5_0_Ghz_supported;
 +#endif
        } else
                SUPPLICANT_DBG("key %s type %c",
                                key, dbus_message_iter_get_arg_type(iter));
@@@ -1414,24 -1082,6 +1414,24 @@@ const char *g_supplicant_interface_get_
        return interface->ifname;
  }
  
 +#if defined TIZEN_EXT
 +bool g_supplicant_interface_get_is_5_0_ghz_supported(GSupplicantInterface *interface)
 +{
 +      if (!interface)
 +              return NULL;
 +
 +      return interface->is_5_0_Ghz_supported;
 +}
 +
 +unsigned char *g_supplicant_interface_get_add_network_bssid(GSupplicantInterface *interface)
 +{
 +      if (!interface)
 +              return NULL;
 +
 +      return (unsigned char *)interface->add_network_bssid;
 +}
 +#endif
 +
  const char *g_supplicant_interface_get_driver(GSupplicantInterface *interface)
  {
        if (!interface)
@@@ -1495,9 -1145,6 +1495,9 @@@ unsigned int g_supplicant_interface_get
        if (!interface)
                return 0;
  
 +      if (interface->max_scan_ssids == 0)
 +              return WPAS_MAX_SCAN_SSIDS;
 +
        return interface->max_scan_ssids;
  }
  
@@@ -1650,16 -1297,6 +1650,16 @@@ dbus_bool_t g_supplicant_network_is_wps
        return FALSE;
  }
  
 +#ifdef TIZEN_EXT
 +GSupplicantPhy_mode g_supplicant_network_get_phy_mode(GSupplicantNetwork *network)
 +{
 +      if (!network)
 +              return G_SUPPLICANT_MODE_IEEE80211_UNKNOWN;
 +
 +      return network->phy_mode;
 +}
 +#endif
 +
  GSupplicantInterface *g_supplicant_peer_get_interface(GSupplicantPeer *peer)
  {
        if (!peer)
@@@ -1708,73 -1345,6 +1708,73 @@@ const char *g_supplicant_peer_get_name(
        return peer->name;
  }
  
 +#if defined TIZEN_EXT
 +bool g_supplicant_network_is_hs20AP(GSupplicantNetwork *network)
 +{
 +      if (!network)
 +              return 0;
 +
 +      return network->isHS20AP;
 +}
 +
 +const char *g_supplicant_network_get_eap(GSupplicantNetwork *network)
 +{
 +      if (!network || !network->eap)
 +              return NULL;
 +
 +      return network->eap;
 +}
 +
 +const char *g_supplicant_network_get_identity(GSupplicantNetwork *network)
 +{
 +      if (!network || !network->identity)
 +              return NULL;
 +
 +      return network->identity;
 +}
 +
 +const char *g_supplicant_network_get_phase2(GSupplicantNetwork *network)
 +{
 +      if (!network || !network->phase2)
 +              return NULL;
 +
 +      return network->phase2;
 +}
 +
 +unsigned int g_supplicant_network_get_keymgmt(GSupplicantNetwork *network)
 +{
 +      if (!network)
 +              return 0;
 +
 +      return network->keymgmt;
 +}
 +
 +dbus_bool_t g_supplicant_network_get_privacy(GSupplicantNetwork *network)
 +{
 +      if (!network)
 +              return FALSE;
 +
 +      return network->privacy;
 +}
 +
 +const unsigned char *g_supplicant_network_get_countrycode(GSupplicantNetwork
 +                                                        *network)
 +{
 +      if (!network)
 +              return NULL;
 +
 +      return network->country_code;
 +}
 +
 +dbus_bool_t g_supplicant_network_is_pmf_required(GSupplicantNetwork *network)
 +{
 +      if (!network)
 +              return 0;
 +
 +      return network->best_bss->pmf_required;
 +}
 +#endif
 +
  const unsigned char *g_supplicant_peer_get_widi_ies(GSupplicantPeer *peer,
                                                                int *length)
  {
@@@ -1857,570 -1427,61 +1857,570 @@@ bool g_supplicant_peer_has_requested_co
        return peer->connection_requested;
  }
  
 -static void merge_network(GSupplicantNetwork *network)
 +#if defined TIZEN_EXT
 +/*
 + * Description: Network client requires additional wifi specific info
 + */
 +const unsigned char *g_supplicant_network_get_bssid(GSupplicantNetwork *network)
  {
 -      GString *str;
 -      const char *ssid, *mode, *key_mgmt;
 -      unsigned int i, ssid_len;
 -      char *group;
 +      if (network == NULL || network->best_bss == NULL)
 +              return NULL;
  
 -      ssid = g_hash_table_lookup(network->config_table, "ssid");
 -      mode = g_hash_table_lookup(network->config_table, "mode");
 -      key_mgmt = g_hash_table_lookup(network->config_table, "key_mgmt");
 +      return (const unsigned char *)network->best_bss->bssid;
 +}
  
 -      SUPPLICANT_DBG("ssid %s mode %s", ssid, mode);
 +dbus_bool_t g_supplicant_network_get_transition_mode(GSupplicantNetwork *network)
 +{
 +      if (network == NULL)
 +              return FALSE;
  
 -      if (ssid)
 -              ssid_len = strlen(ssid);
 -      else
 -              ssid_len = 0;
 +      return network->owe_transition_mode;
 +}
  
 -      str = g_string_sized_new((ssid_len * 2) + 24);
 -      if (!str)
 -              return;
 +const unsigned char *g_supplicant_network_get_transition_mode_bssid(GSupplicantNetwork *network)
 +{
 +      if (network == NULL)
 +              return NULL;
  
 -      for (i = 0; i < ssid_len; i++)
 -              g_string_append_printf(str, "%02x", ssid[i]);
 +      return (const unsigned char *)network->transition_mode_bssid;
 +}
  
 -      if (g_strcmp0(mode, "0") == 0)
 -              g_string_append_printf(str, "_managed");
 -      else if (g_strcmp0(mode, "1") == 0)
 -              g_string_append_printf(str, "_adhoc");
 +const void *g_supplicant_network_get_transition_mode_ssid(GSupplicantNetwork *network,
 +                                              unsigned int *transition_mode_ssid_len)
 +{
 +      if (!network) {
 +              *transition_mode_ssid_len = 0;
 +              return NULL;
 +      }
  
 -      if (g_strcmp0(key_mgmt, "WPA-PSK") == 0)
 -              g_string_append_printf(str, "_psk");
 +      *transition_mode_ssid_len = network->transition_mode_ssid_len;
 +      return network->transition_mode_ssid;
 +}
  
 -      group = g_string_free(str, FALSE);
 +unsigned int g_supplicant_network_get_maxrate(GSupplicantNetwork *network)
 +{
 +      if (network == NULL || network->best_bss == NULL)
 +              return 0;
  
 -      SUPPLICANT_DBG("%s", group);
 +      return network->best_bss->maxrate;
 +}
  
 -      g_free(group);
 +const char *g_supplicant_network_get_enc_mode(GSupplicantNetwork *network)
 +{
 +      if (network == NULL || network->best_bss == NULL)
 +              return NULL;
  
 -      g_hash_table_destroy(network->config_table);
 +      if (network->best_bss->security == G_SUPPLICANT_SECURITY_PSK ||
 +                      network->best_bss->security == G_SUPPLICANT_SECURITY_SAE ||
 +                      network->best_bss->security == G_SUPPLICANT_SECURITY_OWE ||
 +                      network->best_bss->security == G_SUPPLICANT_SECURITY_DPP ||
 +                      network->best_bss->security == G_SUPPLICANT_SECURITY_IEEE8021X) {
 +              unsigned int pairwise;
 +
 +              pairwise = network->best_bss->rsn_pairwise |
 +                              network->best_bss->wpa_pairwise;
 +
 +              if ((pairwise & G_SUPPLICANT_PAIRWISE_CCMP) &&
 +                  (pairwise & G_SUPPLICANT_PAIRWISE_TKIP))
 +                      return "mixed";
 +              else if (pairwise & G_SUPPLICANT_PAIRWISE_CCMP)
 +                      return "aes";
 +              else if (pairwise & G_SUPPLICANT_PAIRWISE_TKIP)
 +                      return "tkip";
 +
 +      } else if (network->best_bss->security == G_SUPPLICANT_SECURITY_WEP)
 +              return "wep";
 +      else if (network->best_bss->security == G_SUPPLICANT_SECURITY_NONE)
 +              return "none";
  
 -      g_free(network->path);
 -      g_free(network);
 +      return NULL;
  }
  
 -static void network_property(const char *key, DBusMessageIter *iter,
 -                                                      void *user_data)
 +bool g_supplicant_network_get_rsn_mode(GSupplicantNetwork *network)
  {
 -      GSupplicantNetwork *network = user_data;
 +      if (network == NULL || network->best_bss == NULL)
 +              return 0;
  
 -      if (!network->interface)
 -              return;
 +      if (network->best_bss->security == G_SUPPLICANT_SECURITY_OWE ||
 +                      network->best_bss->security == G_SUPPLICANT_SECURITY_DPP)
 +              return false;
  
 -      if (!key) {
 -              merge_network(network);
 +      if (network->best_bss->rsn_selected) {
 +              const char *mode = g_supplicant_network_get_enc_mode(network);
 +              if (g_strcmp0(mode, "aes") == 0 ||
 +                              g_strcmp0(mode, "mixed") == 0)
 +                      return true;
 +              else
 +                      return false;
 +      } else
 +              return false;
 +}
 +
 +void *g_supplicant_network_get_wifi_vsie(GSupplicantNetwork *network)
 +{
 +      GSList *vsie_list = NULL;
 +
 +      if (!network)
 +              return NULL;
 +
 +      if (g_slist_length(network->vsie_list) > 0) {
 +              GSList *list = NULL;
 +              unsigned char *vsie = NULL;
 +              for (list = network->vsie_list; list; list = list->next) {
 +                      unsigned char *ie = (unsigned char *)list->data;
 +                      if (ie == NULL)
 +                              continue;
 +                      vsie = (unsigned char *)g_try_malloc0(ie[1]+2); // tag number size(1), tag length size(1)
 +
 +                      if (vsie) {
 +                              memcpy(vsie, ie, ie[1]+2);
 +                              vsie_list = g_slist_append(vsie_list, vsie);
 +                      } else
 +                              SUPPLICANT_DBG("Failed to allocate memory");
 +              }
 +      }
 +
 +      return vsie_list;
 +}
 +
 +static bool compare_bssid(unsigned char *bssid_a, unsigned char *bssid_b)
 +{
 +      if (!memcmp(bssid_a, bssid_b, WIFI_BSSID_LEN_MAX))
 +              return true;
 +
 +      return false;
 +}
 +
 +static gchar *convert_bssid_to_str(unsigned char *bssid)
 +{
 +      GString *bssid_str;
 +      unsigned int i;
 +
 +      bssid_str = g_string_sized_new(18);
 +      if (!bssid_str)
 +              return NULL;
 +
 +      for (i = 0; i < WIFI_BSSID_LEN_MAX; i++) {
 +              g_string_append_printf(bssid_str, "%02x", bssid[i]);
 +              if (i < WIFI_BSSID_LEN_MAX - 1)
 +                      g_string_append(bssid_str, ":");
 +      }
 +
 +      return g_string_free(bssid_str, FALSE);
 +}
 +
 +#if defined TIZEN_EXT_INS
 +static void count_assoc_reject(gpointer data, gpointer user_data)
 +{
 +      time_t assoc_reject_time = GPOINTER_TO_INT(data);
 +      struct assoc_count_data *assoc_count = user_data;
 +
 +      if (assoc_reject_time > assoc_count->ref_time)
 +              assoc_count->assoc_count++;
 +}
 +
 +static uint16_t get_assoc_reject_cnt(GHashTable *assoc_reject_table, unsigned char *bssid)
 +{
 +      gchar *bssid_str;
 +      struct assoc_reject_data *assoc_data;
 +      struct assoc_count_data assoc_count;
 +      time_t curr_time;
 +      struct tm* timeinfo;
 +
 +      if (g_hash_table_size(assoc_reject_table) < 1)
 +              return 0;
 +
 +      if (!bssid)
 +              return 0;
 +
 +      if (!memcmp(bssid, invalid_bssid, WIFI_BSSID_LEN_MAX))
 +              return 0;
 +
 +      bssid_str = convert_bssid_to_str(bssid);
 +      if (!bssid_str)
 +              return 0;
 +
 +      assoc_data = g_hash_table_lookup(assoc_reject_table, bssid_str);
 +      if (!assoc_data) {
 +              g_free(bssid_str);
 +              return 0;
 +      }
 +
 +      if (g_slist_length(assoc_data->reject_time_list) < 1) {
 +              g_free(bssid_str);
 +              return 0;
 +      }
 +
 +      /* Only events that occur within one hour are appened. */
 +      curr_time = time(NULL);
 +      timeinfo = localtime(&curr_time);
 +      timeinfo->tm_hour -= 1;
 +
 +      assoc_count.ref_time = mktime(timeinfo);
 +      assoc_count.assoc_count = 0;
 +
 +      g_slist_foreach(assoc_data->reject_time_list, count_assoc_reject, &assoc_count);
 +
 +      g_free(bssid_str);
 +      return assoc_count.assoc_count;
 +}
 +
 +static int calculate_score_last_connected_bssid(bool is_last_connected)
 +{
 +      int score = 0;
 +
 +      if (ins_settings.last_connected_bssid) {
 +              if (is_last_connected)
 +                      score += ins_settings.last_connected_bssid_score;
 +      }
 +
 +      return score;
 +}
 +
 +static int calculate_score_assoc_reject(uint16_t assoc_reject_cnt)
 +{
 +      int score = 0;
 +
 +      if (ins_settings.assoc_reject)
 +              score -= (assoc_reject_cnt * ins_settings.assoc_reject_score);
 +
 +      return score;
 +}
 +
 +static int calculate_score_frequency(dbus_int16_t strength, dbus_uint16_t frequency)
 +{
 +      int score = 0;
 +
 +      switch (ins_settings.preferred_freq_bssid) {
 +      case G_SUPPLICANT_INS_PREFERRED_FREQ_24GHZ:
 +              if ((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
 +                      frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
 +                      (strength > ins_settings.signal_level3_24ghz))
 +                      score += ins_settings.preferred_freq_bssid_score;
 +
 +              break;
 +      case G_SUPPLICANT_INS_PREFERRED_FREQ_5GHZ:
 +              if ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
 +                      frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
 +                      (strength > ins_settings.signal_level3_5ghz))
 +                      score += ins_settings.preferred_freq_bssid_score;
 +
 +              break;
 +      default:
 +              break;
 +      }
 +
 +      return score;
 +}
 +
 +static int calculate_score_strength(dbus_int16_t strength)
 +{
 +      int score = 0;
 +
 +      if (ins_settings.signal_bssid)
 +              score += (((strength > -60) ? -60 : strength) + 85);
 +
 +      return score;
 +}
 +
 +static int calculate_score_est_throughput(dbus_uint32_t est_throughput)
 +{
 +      int score = 0;
 +
 +      if (est_throughput >= 10000)
 +              score = est_throughput / 10000;
 +
 +      if (score > 40)
 +              score = 40;
 +
 +      return score;
 +}
 +
 +static int calculate_score(bool is_last_connected, uint16_t assoc_reject_cnt,
 +              dbus_uint16_t frequency, dbus_int16_t strength,
 +              dbus_int16_t snr, dbus_uint32_t est_throughput)
 +{
 +      int score = 0;
 +
 +      score += calculate_score_last_connected_bssid(is_last_connected);
 +      score += calculate_score_assoc_reject(assoc_reject_cnt);
 +      score += calculate_score_frequency(strength, frequency);
 +      score += calculate_score_strength(strength);
 +      score += (int)snr;
 +      score += calculate_score_est_throughput(est_throughput);
 +
 +      return score;
 +}
 +#endif
 +
 +static void update_bssid_list(gpointer key, gpointer value, gpointer user_data)
 +{
 +      struct g_supplicant_bss *bss = value;
 +      struct g_connman_bssids *bssids = NULL;
 +      struct update_bssid_data *bssid_data = (struct update_bssid_data *)user_data;
 +
 +      bssids = (struct g_connman_bssids *)g_try_malloc0(sizeof(struct g_connman_bssids));
 +
 +      if (bssids) {
 +              memcpy(bssids->bssid, bss->bssid, WIFI_BSSID_LEN_MAX);
 +
 +              bssids->strength = bss->signal;
 +              bssids->strength += 120;
 +
 +              if (bssids->strength > 100)
 +                      bssids->strength = 100;
 +
 +              bssids->frequency = bss->frequency;
 +              bssids->score_snr = (int)bss->snr;
 +
 +#if defined TIZEN_EXT_INS
 +              bssids->assoc_reject_cnt = get_assoc_reject_cnt(bssid_data->assoc_reject_table, bssids->bssid);
 +              bssids->is_last_connected = compare_bssid(bssids->bssid, bssid_data->last_connected_bssid);
 +
 +              bssids->score_last_connected_bssid = calculate_score_last_connected_bssid(bssids->is_last_connected);
 +              bssids->score_assoc_reject = calculate_score_assoc_reject(bssids->assoc_reject_cnt);
 +              bssids->score_frequency = calculate_score_frequency(bss->signal, bssids->frequency);
 +              bssids->score_strength = calculate_score_strength(bss->signal);
 +              bssids->score_est_throughput = calculate_score_est_throughput(bss->est_throughput);
 +
 +              bssids->ins_score = calculate_score(bssids->is_last_connected,
 +                      bssids->assoc_reject_cnt, bssids->frequency, bss->signal,
 +                      bss->snr, bss->est_throughput);
 +#else
 +              bssids->ins_score = bss->signal;
 +#endif
 +              bssid_data->bssid_list = g_slist_append(bssid_data->bssid_list, bssids);
 +      } else
 +              SUPPLICANT_DBG("Failed to allocate memory");
 +}
 +
 +static gint cmp_bss(gconstpointer a, gconstpointer b)
 +{
 +      struct g_connman_bssids *entry_a = (struct g_connman_bssids *)a;
 +      struct g_connman_bssids *entry_b = (struct g_connman_bssids *)b;
 +
 +      if (entry_a->ins_score > entry_b->ins_score)
 +              return -1;
 +
 +      if (entry_a->ins_score < entry_b->ins_score)
 +              return 1;
 +
 +      return 0;
 +}
 +
 +#if defined TIZEN_EXT_INS
 +static void print_bssid_sort(gpointer data, gpointer user_data)
 +{
 +      struct g_connman_bssids *bssids = data;
 +
 +      SUPPLICANT_DBG("bssid[" MACSTR "] total[%2d] freq[%2d] "
 +                      "last_conn[%2d] assoc_reject[%2d] strength[%2d]",
 +                      MAC2STR(bssids->bssid), bssids->ins_score,
 +                      bssids->score_frequency, bssids->score_last_connected_bssid,
 +                      bssids->score_assoc_reject, bssids->score_strength);
 +}
 +#endif
 +
 +void *g_supplicant_network_get_bssid_list(GSupplicantNetwork *network)
 +{
 +      struct update_bssid_data bssid_data;
 +
 +      if (g_hash_table_size(network->bss_table) < 1)
 +              return NULL;
 +
 +      bssid_data.network = network;
 +      memset(&bssid_data, 0, sizeof(bssid_data));
 +      memcpy(bssid_data.last_connected_bssid, network->last_connected_bssid, WIFI_BSSID_LEN_MAX);
 +      bssid_data.assoc_reject_table = network->assoc_reject_table;
 +
 +      g_hash_table_foreach(network->bss_table, update_bssid_list, &bssid_data);
 +      bssid_data.bssid_list = g_slist_sort(bssid_data.bssid_list, cmp_bss);
 +#if defined TIZEN_EXT_INS
 +      g_slist_foreach(bssid_data.bssid_list, print_bssid_sort, NULL);
 +#endif
 +
 +      return bssid_data.bssid_list;
 +}
 +
 +void g_supplicant_network_set_last_connected_bssid(GSupplicantNetwork *network, const unsigned char *bssid)
 +{
 +      if (!bssid)
 +              return;
 +
 +      if (!memcmp(bssid, invalid_bssid, WIFI_BSSID_LEN_MAX))
 +              return;
 +
 +      memcpy(network->last_connected_bssid, bssid, WIFI_BSSID_LEN_MAX);
 +
 +      SUPPLICANT_DBG("last connected bssid [" MACSTR "]", MAC2STR(bssid));
 +}
 +
 +const unsigned char *g_supplicant_network_get_last_connected_bssid(GSupplicantNetwork *network)
 +{
 +      if (network == NULL)
 +              return NULL;
 +
 +      return (const unsigned char *)network->last_connected_bssid;
 +}
 +
 +void g_supplicant_network_update_assoc_reject(GSupplicantInterface *interface,
 +              GSupplicantNetwork *network)
 +{
 +      struct assoc_reject_data *assoc_data;
 +      gchar *bssid_str;
 +      time_t curr_time;
 +
 +      if (!network)
 +              return;
 +
 +      bssid_str = convert_bssid_to_str(interface->add_network_bssid);
 +      if (!bssid_str)
 +              return;
 +
 +      assoc_data = g_hash_table_lookup(network->assoc_reject_table, bssid_str);
 +      if (!assoc_data) {
 +              assoc_data = g_try_new0(struct assoc_reject_data, 1);
 +              if (!assoc_data) {
 +                      g_free(bssid_str);
 +                      return;
 +              }
 +
 +              assoc_data->bssid = g_strdup(bssid_str);
 +              g_hash_table_insert(network->assoc_reject_table, assoc_data->bssid, assoc_data);
 +      }
 +
 +      curr_time = time(NULL);
 +      assoc_data->reject_time_list = g_slist_append(assoc_data->reject_time_list, GINT_TO_POINTER(curr_time));
 +
 +      SUPPLICANT_DBG("bssid [%s] time [%u]", bssid_str, curr_time);
 +
 +      g_free(bssid_str);
 +
 +      callback_network_changed(network, "UpdateAssocReject");
 +}
 +
 +GHashTable *g_supplicant_network_get_assoc_reject_table(GSupplicantNetwork *network)
 +{
 +      if (!network)
 +              return NULL;
 +
 +      return network->assoc_reject_table;
 +}
 +
 +GSupplicantNetwork *g_supplicant_interface_get_network(GSupplicantInterface *interface,
 +              const char *group)
 +{
 +      if (!interface)
 +              return NULL;
 +
 +      return g_hash_table_lookup(interface->network_table, group);
 +}
 +#endif
 +
 +static void merge_network(GSupplicantNetwork *network)
 +{
 +      GString *str;
 +      const char *ssid, *mode, *key_mgmt;
 +#if defined TIZEN_EXT
 +      const char *isHS20AP;
 +      const char *eap, *identity, *phase2;
 +#endif
 +      unsigned int i, ssid_len;
 +      char *group;
 +
 +      ssid = g_hash_table_lookup(network->config_table, "ssid");
 +      mode = g_hash_table_lookup(network->config_table, "mode");
 +      key_mgmt = g_hash_table_lookup(network->config_table, "key_mgmt");
 +#if defined TIZEN_EXT
 +      isHS20AP = g_hash_table_lookup(network->config_table, "isHS20AP");
 +      eap = g_hash_table_lookup(network->config_table, "eap");
 +      identity = g_hash_table_lookup(network->config_table, "identity");
 +      phase2 = g_hash_table_lookup(network->config_table, "phase2");
 +#endif
 +
 +      SUPPLICANT_DBG("ssid %s mode %s", ssid, mode);
 +
 +      if (ssid)
 +              ssid_len = strlen(ssid);
 +      else
 +              ssid_len = 0;
 +
 +      str = g_string_sized_new((ssid_len * 2) + 24);
 +      if (!str)
 +              return;
 +
 +      for (i = 0; i < ssid_len; i++)
 +#if defined TIZEN_EXT
 +      {
 +              if (ssid[i] != '"')
 +#endif
 +              g_string_append_printf(str, "%02x", ssid[i]);
 +#if defined TIZEN_EXT
 +      }
 +#endif
 +
 +      if (g_strcmp0(mode, "0") == 0)
 +              g_string_append_printf(str, "_managed");
 +      else if (g_strcmp0(mode, "1") == 0)
 +              g_string_append_printf(str, "_adhoc");
 +#if defined TIZEN_EXT_WIFI_MESH
 +      else if (g_strcmp0(mode, "5") == 0)
 +              g_string_append_printf(str, "_mesh");
 +#endif
 +
 +      if (g_strcmp0(key_mgmt, "WPA-PSK") == 0)
 +              g_string_append_printf(str, "_psk");
 +#if defined TIZEN_EXT
 +      else if (g_strcmp0(key_mgmt, "WPA-EAP") == 0)
 +              g_string_append_printf(str, "_ieee8021x");
 +      else
 +              g_string_append_printf(str, "_none");
 +#endif
 +
 +      group = g_string_free(str, FALSE);
 +
 +      SUPPLICANT_DBG("%s", group);
 +
 +#if defined TIZEN_EXT
 +      if (g_strcmp0(isHS20AP, "1") == 0) {
 +              network->isHS20AP = 1;
 +              if (network->eap)
 +                      g_free(network->eap);
 +              network->eap = g_strdup(eap);
 +
 +              if (network->identity)
 +                      g_free(network->identity);
 +              network->identity = g_strdup(identity);
 +
 +              if (network->phase2)
 +                      g_free(network->phase2);
 +              network->phase2 = g_strdup(phase2);
 +      } else
 +              network->isHS20AP = 0;
 +
 +      network->group = g_strdup(group);
 +      callback_network_merged(network);
 +      g_free(network->group);
 +#endif
 +
 +      g_free(group);
 +
 +      g_hash_table_destroy(network->config_table);
 +
 +      g_free(network->path);
 +      g_free(network);
 +}
 +
 +static void network_property(const char *key, DBusMessageIter *iter,
 +                                                      void *user_data)
 +{
 +      GSupplicantNetwork *network = user_data;
 +
 +      if (!network->interface)
 +              return;
 +
 +      if (!key) {
 +              merge_network(network);
                return;
        }
  
@@@ -2551,63 -1612,7 +2551,63 @@@ static char *create_group(struct g_supp
  
        return g_string_free(str, FALSE);
  }
 +#if defined TIZEN_EXT
 +static void update_network_with_best_bss(GSupplicantNetwork *network,
 +              struct g_supplicant_bss *best_bss)
 +{
 +      /*
 +       * Do not change best BSS if we are connected.
 +       */
 +      if (network->interface->state == G_SUPPLICANT_STATE_COMPLETED)
 +              return;
 +
 +      network->signal = best_bss->signal;
 +      network->frequency = best_bss->frequency;
 +      network->best_bss = best_bss;
 +}
 +
 +static bool update_best_bss(GSupplicantNetwork *network,
 +              struct g_supplicant_bss *bss, struct g_supplicant_bss *best_bss)
 +{
 +      int score_new;
 +      int score_best;
 +
 +      if (network->best_bss == NULL) {
 +              update_network_with_best_bss(network, bss);
 +              return true;
 +      }
  
 +#if defined TIZEN_EXT_INS
 +      score_new = calculate_score(
 +              compare_bssid(bss->bssid, network->last_connected_bssid),
 +              get_assoc_reject_cnt(network->assoc_reject_table, bss->bssid),
 +              bss->frequency, bss->signal, bss->snr, bss->est_throughput);
 +
 +      score_best = calculate_score(
 +              compare_bssid(network->best_bss->bssid, network->last_connected_bssid),
 +              get_assoc_reject_cnt(network->assoc_reject_table, network->best_bss->bssid),
 +              network->best_bss->frequency, network->best_bss->signal,
 +              network->best_bss->snr, network->best_bss->est_throughput);
 +#else
 +      score_new = bss->signal;
 +      score_best = network->best_bss->signal;
 +#endif
 +
 +      if (score_new > score_best) {
 +              SUPPLICANT_DBG("new[" MACSTR "][%u] : best[" MACSTR "][%u]",
 +                      MAC2STR(bss->bssid), score_new,
 +                      MAC2STR(network->best_bss->bssid), score_best);
 +
 +              update_network_with_best_bss(network, bss);
 +
 +              SUPPLICANT_DBG("Update best BSS for %s", network->name);
 +
 +              return true;
 +      }
 +
 +      return false;
 +}
 +#endif
  static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
  {
        GSupplicantInterface *interface = bss->interface;
                network->wps_capabilities = bss->wps_capabilities;
        }
  
 +#if defined TIZEN_EXT
 +      network->owe_transition_mode = bss->owe_transition_mode;
 +      network->privacy = bss->privacy;
 +      memcpy(network->transition_mode_ssid, bss->transition_mode_ssid, bss->transition_mode_ssid_len);
 +      memcpy(network->transition_mode_bssid, bss->transition_mode_bssid, WIFI_BSSID_LEN_MAX);
 +
 +      network->keymgmt = bss->keymgmt;
 +
 +      if (g_slist_length(bss->vsie_list) > 0) {
 +              GSList *list = NULL;
 +              unsigned char *vsie = NULL;
 +              for (list = bss->vsie_list; list; list = list->next) {
 +                      unsigned char *ie = (unsigned char *)list->data;
 +                      vsie = (unsigned char *)g_try_malloc0(ie[1]+2); // tag number size(1), tag length size(1)
 +
 +                      if (vsie) {
 +                              memcpy(vsie, ie, ie[1]+2);
 +                              network->vsie_list = g_slist_append(network->vsie_list, vsie);
 +                      } else
 +                              SUPPLICANT_DBG("Failed to allocate memory.");
 +              }
 +      }
 +
 +      network->isHS20AP = bss->hs20;
 +      memcpy(network->country_code, bss->country_code, COUNTRY_CODE_LENGTH);
 +      network->phy_mode = bss->phy_mode;
 +#endif
 +
        SUPPLICANT_DBG("New network %s created", network->name);
  
        network->bss_table = g_hash_table_new_full(g_str_hash, g_str_equal,
        network->config_table = g_hash_table_new_full(g_str_hash, g_str_equal,
                                                        g_free, g_free);
  
 +#if defined TIZEN_EXT
 +      network->assoc_reject_table = g_hash_table_new_full(g_str_hash, g_str_equal,
 +                                                      NULL, remove_assoc_data);
 +#endif
 +
        g_hash_table_replace(interface->network_table,
                                                network->group, network);
  
@@@ -2716,19 -1688,12 +2716,19 @@@ done
         * Do not change best BSS if we are connected. It will be done through
         * CurrentBSS property in case of misalignment with wpa_s or roaming.
         */
 +#if defined TIZEN_EXT
 +      if (network != interface->current_network) {
 +              if (update_best_bss(network, bss, network->best_bss))
 +                      callback_network_changed(network, "Signal");
 +      }
 +#else
        if (network != interface->current_network &&
                                bss->signal > network->signal) {
                network->signal = bss->signal;
                network->best_bss = bss;
                callback_network_changed(network, "Signal");
        }
 +#endif
  
        g_hash_table_replace(interface->bss_mapping, bss->path, network);
        g_hash_table_replace(network->bss_table, bss->path, bss);
@@@ -2879,50 -1844,6 +2879,50 @@@ static unsigned int get_tlv(unsigned ch
        return 0;
  }
  
 +#if defined TIZEN_EXT
 +static void get_bss_phy_mode(unsigned int max_rate,
 +              unsigned int max_ext_rate, bool ht, bool vht, void *data)
 +{
 +      struct g_supplicant_bss *bss = data;
 +      unsigned int freq = bss->frequency;
 +
 +      /* Following conditions are used to determine
 +       * IEEE 802.11 Protocol Modes:-
 +       *
 +       * 1. If “Supported rates” is only till 11 Mbps,
 +       *    and frequency is in 2.4GHz band, then protocol is 11B.
 +       * 2. If “Supported rates” is till 54Mbps or
 +       *    “Extended supported rates” are present,
 +       *    and frequency is in 2.4GHz band, then protocol is 11G.
 +       * 3. If “Supported rates” is only till 54 Mbps,
 +       *    frequency is in 5GHz band , then protocol is 11A.
 +       * 4. If “HT capabilities” is supported , then protocol is 11N.
 +       * 5. If “HT capabilities” & “VHT” is supported and
 +       *    frequency is in 5 GHz band, then protocol is 11AC.
 +       * */
 +
 +      if (freq >= 2412 && freq <= 2484) { /* 2.4 Ghz Band */
 +              if (max_rate <= 11 && max_ext_rate <= 0 && !ht)
 +                      bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211B;
 +              else if ((max_rate <= 54 || max_ext_rate > 0) && !ht)
 +                      bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211BG;
 +              else if ((max_rate >= 54 || max_ext_rate > 0) && ht)
 +                      bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211BGN;
 +              else
 +                      bss->phy_mode = G_SUPPLICANT_MODE_UNKNOWN;
 +      } else if (freq >= 5180 && freq <= 5825) { /* 5 Ghz Band */
 +              if (max_rate <= 54 && !ht)
 +                      bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211A;
 +              else if ((max_rate >= 54 || max_ext_rate > 0) && ht && !vht)
 +                      bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211AN;
 +              else if ((max_rate >= 54 || max_ext_rate > 0) && ht && vht)
 +                      bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211ANAC;
 +              else
 +                      bss->phy_mode = G_SUPPLICANT_MODE_UNKNOWN;
 +      }
 +}
 +#endif
 +
  static void bss_process_ies(DBusMessageIter *iter, void *user_data)
  {
        struct g_supplicant_bss *bss = user_data;
        DBusMessageIter array;
        unsigned int value;
        int ie_len;
 +#if defined TIZEN_EXT
 +      const unsigned char OWE_WFA_OUI[] = { 0x50, 0x6f, 0x9a, 0x1c };
 +      int r_len, j;
 +      unsigned char *rates = NULL;
 +      unsigned char *ext_rates = NULL;
 +      unsigned int max_rate = 0;
 +      unsigned int max_ext_rate = 0;
 +      unsigned int offset = 0;
 +      bool ht = false;
 +      bool vht = false;
 +#endif
  
  #define WMM_WPA1_WPS_INFO 221
  #define WPS_INFO_MIN_LEN  6
  #define WPS_PBC           0x04
  #define WPS_PIN           0x00
  #define WPS_CONFIGURED    0x02
 +#if defined TIZEN_EXT
 +#define VENDOR_SPECIFIC_INFO 0xDD
 +#define WLAN_EID_COUNTRY 7
 +#define WLAN_EID_RSN_INFO 48
 +#define RSN_CAPABILITY_MFP_REQ (1 << 6)
 +#endif
  
        dbus_message_iter_recurse(iter, &array);
        dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
  
        for (ie_end = ie + ie_len; ie < ie_end && ie + ie[1] + 1 <= ie_end;
                                                        ie += ie[1] + 2) {
 +#if defined TIZEN_EXT
 +              unsigned char *vsie;
 +              int vsie_len = 0;
 +
 +              if (ie[0] == VENDOR_SPECIFIC_INFO && memcmp(ie+2, OWE_WFA_OUI, sizeof(OWE_WFA_OUI)) == 0) {
 +                      SUPPLICANT_DBG("IE: match vendor specific data : OWE Transition Mode");
 +
 +/*
 +              Tag: Vendor Specific: Wi-Fi Alliance: OWE Transition Mode
 +                      Tag Number: Vendor Specific (221)    -> ie[0]
 +                      Tag length: 26                       -> ie[1]
 +                      OUI: 50:6f:9a (Wi-Fi Alliance)       -> ie[2]
 +                      Vendor Specific OUI Type: 28         -> ie[5]
 +                      BSSID: 92:fd:f0:20:2b:09             -> ie[6]
 +                      SSID length: 15                      -> ie[12]
 +                      SSID: Wi-Fi-5.2.3-owe                -> ie[13]
 +
 +0000   dd 1a 50 6f 9a 1c 92 fd f0 20 2b 09 0f 57 69 2d   ..Po..... +..Wi-
 +0010   46 69 2d 35 2e 32 2e 33 2d 6f 77 65               Fi-5.2.3-owe
 +
 +*/
 +                      bss->owe_transition_mode = TRUE;
 +                      if (ie[1] >= 11) { // Tag length is at least up to ssid length position.
 +                              memcpy(bss->transition_mode_bssid, ie+6, WIFI_BSSID_LEN_MAX);
 +                              if (ie[12] > 0 && ie[12] < 32) {
 +                                      memcpy(bss->transition_mode_ssid, ie+13, ie[12]);
 +                                      bss->transition_mode_ssid_len = ie[12];
 +                              } else
 +                                      bss->transition_mode_ssid_len = 0;
 +                      } else
 +                              bss->owe_transition_mode = FALSE;
 +                      continue;
 +              }
 +
 +              if (ie[0] == VENDOR_SPECIFIC_INFO && memcmp(ie+2, WPS_OUI, sizeof(WPS_OUI)) != 0) {
  
 +                      if (!simplified_log)
 +                              SUPPLICANT_DBG("IE: match vendor specific data");
 +
 +                      vsie_len = ie[1]+2;     // tag number size(1), tag length size(1)
 +                      vsie = (unsigned char *)g_try_malloc0(vsie_len);
 +
 +                      if (vsie) {
 +                              memcpy(vsie, ie, vsie_len);
 +                              bss->vsie_list = g_slist_append(bss->vsie_list, vsie);
 +                      } else
 +                              SUPPLICANT_DBG("Failed to allocate memory");
 +                      continue;
 +              }
 +
 +              if (ie[0] == WLAN_EID_COUNTRY && ie[1] >= 2) {
 +                      /* Add country code only if it is a valid alphabet */
 +                      if (ie[2] >= 65 && ie[2] <= 90 && ie[3] >= 65 && ie[3] <= 90) {
 +                              memcpy(bss->country_code, ie+2, COUNTRY_CODE_LENGTH);
 +                              continue;
 +                      }
 +              }
 +
 +              if (ie[0] == WLAN_EID_HT_CAP && ie[1]) {
 +                      ht = true;
 +                      continue;
 +              }
 +
 +              if (ie[0] == WLAN_EID_VHT_CAP && ie[1]) {
 +                      vht = true;
 +                      continue;
 +              }
 +
 +              if (ie[0] == WLAN_EID_SUPP_RATES && ie[1]) {
 +                      r_len = ie[1];
 +                      rates = g_malloc0(r_len);
 +                      if (!rates)
 +                              continue;
 +
 +                      for (j = 0; ie && j < r_len; j++) {
 +                              rates[j] = ((ie[j + 2] & 0x7f) * 500000)/1000000;
 +                              if (max_rate < rates[j])
 +                                      max_rate = rates[j];
 +                      }
 +                      continue;
 +              }
 +
 +              if (ie[0] == WLAN_EID_EXT_SUPP_RATES && ie[1] > 0) {
 +                      r_len = ie[1];
 +                      ext_rates = g_malloc0(r_len);
 +                      if (!ext_rates)
 +                              continue;
 +
 +                      for (j = 0; ie && j < r_len; j++) {
 +                              ext_rates[j] = ((ie[j + 2] & 0x7f) * 500000)/1000000;
 +                              if (max_ext_rate < ext_rates[j])
 +                                      max_ext_rate = ext_rates[j];
 +                      }
 +                      continue;
 +              }
 +
 +              if (ie[0] == WLAN_EID_RSN_INFO && ie[1] >= 20) {
 +                      r_len = ie[1];
 +                      offset = 10 + ie[8] * 4;
 +                      offset += ie[offset] * 4 + 2;
 +
 +                      if (offset <= r_len + 1 &&
 +                                      (ie[offset] & RSN_CAPABILITY_MFP_REQ) != 0)
 +                              bss->pmf_required = TRUE;
 +
 +                      continue;
 +              }
 +#endif
                if (ie[0] != WMM_WPA1_WPS_INFO || ie[1] < WPS_INFO_MIN_LEN ||
                        memcmp(ie+2, WPS_OUI, sizeof(WPS_OUI)) != 0)
                        continue;
  
                SUPPLICANT_DBG("WPS Methods 0x%x", bss->wps_capabilities);
        }
 +#ifdef TIZEN_EXT
 +      get_bss_phy_mode(max_rate, max_ext_rate, ht, vht, user_data);
 +      if (rates)
 +              g_free(rates);
 +      if (ext_rates)
 +              g_free(ext_rates);
 +#endif
  }
  
  static void bss_compute_security(struct g_supplicant_bss *bss)
  
        bss->ieee8021x = FALSE;
        bss->psk = FALSE;
 +#if defined TIZEN_EXT
 +      bss->ft_ieee8021x = FALSE;
 +      bss->ft_psk = FALSE;
 +#endif
  
 +#if defined TIZEN_EXT
 +      if (bss->keymgmt &
 +                      (G_SUPPLICANT_KEYMGMT_WPA_EAP |
 +                                      G_SUPPLICANT_KEYMGMT_WPA_EAP_256))
 +              bss->ieee8021x = TRUE;
 +      else if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_EAP)
 +              bss->ft_ieee8021x = TRUE;
 +#else
        if (bss->keymgmt &
                        (G_SUPPLICANT_KEYMGMT_WPA_EAP |
                                G_SUPPLICANT_KEYMGMT_WPA_FT_EAP |
                                G_SUPPLICANT_KEYMGMT_WPA_EAP_256))
                bss->ieee8021x = TRUE;
 +#endif
  
 +#if defined TIZEN_EXT
 +      if (bss->keymgmt &
 +                      (G_SUPPLICANT_KEYMGMT_WPA_PSK |
 +                                      G_SUPPLICANT_KEYMGMT_WPA_PSK_256))
 +              bss->psk = TRUE;
 +      else if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_PSK)
 +              bss->ft_psk = TRUE;
 +#else
        if (bss->keymgmt &
                        (G_SUPPLICANT_KEYMGMT_WPA_PSK |
                                G_SUPPLICANT_KEYMGMT_WPA_FT_PSK |
                                G_SUPPLICANT_KEYMGMT_WPA_PSK_256))
                bss->psk = TRUE;
 +#endif
 +
 +#if defined TIZEN_EXT
 +      if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_SAE)
 +              bss->sae = TRUE;
 +      if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_OWE)
 +              bss->owe = TRUE;
 +      if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_DPP)
 +              bss->dpp = TRUE;
 +#endif
  
        if (bss->ieee8021x)
                bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
 +#if defined TIZEN_EXT
 +      else if (bss->ft_ieee8021x)
 +              bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
 +      else if (bss->sae)
 +              bss->security = G_SUPPLICANT_SECURITY_SAE;
 +#endif
        else if (bss->psk)
                bss->security = G_SUPPLICANT_SECURITY_PSK;
 +#if defined TIZEN_EXT
 +      else if (bss->ft_psk)
 +              bss->security = G_SUPPLICANT_SECURITY_FT_PSK;
 +      else if (bss->owe || bss->owe_transition_mode)
 +              bss->security = G_SUPPLICANT_SECURITY_OWE;
 +      else if (bss->dpp)
 +              bss->security = G_SUPPLICANT_SECURITY_DPP;
 +#endif
        else if (bss->privacy)
                bss->security = G_SUPPLICANT_SECURITY_WEP;
        else
@@@ -3207,9 -1952,7 +3207,9 @@@ static void bss_property(const char *ke
  
        if (!bss->interface)
                return;
 -
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        SUPPLICANT_DBG("key %s", key);
  
        if (!key)
                bss->rsn_selected = FALSE;
  
                supplicant_dbus_property_foreach(iter, bss_wpa, bss);
 +#if defined TIZEN_EXT
 +      } else if (g_strcmp0(key, "HS20") == 0) {
 +              dbus_bool_t hs20 = FALSE;
 +              dbus_message_iter_get_basic(iter, &hs20);
 +              bss->hs20 = hs20;
 +      } else if (g_strcmp0(key, "SNR") == 0) {
 +              dbus_int16_t snr = 0;
 +
 +              dbus_message_iter_get_basic(iter, &snr);
 +              bss->snr = snr;
 +      } else if (g_strcmp0(key, "EstThroughput") == 0) {
 +              dbus_uint32_t est_throughput = 0;
 +
 +              dbus_message_iter_get_basic(iter, &est_throughput);
 +              if (est_throughput != 0)
 +                      bss->est_throughput = est_throughput;
 +#endif
        } else if (g_strcmp0(key, "IEs") == 0)
                bss_process_ies(iter, bss);
        else
@@@ -3327,9 -2053,7 +3327,9 @@@ static struct g_supplicant_bss *interfa
        GSupplicantNetwork *network;
        struct g_supplicant_bss *bss;
        const char *path = NULL;
 -
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        SUPPLICANT_DBG("");
  
        dbus_message_iter_get_basic(iter, &path);
  
        if (g_strcmp0(path, "/") == 0)
                return NULL;
 -
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        SUPPLICANT_DBG("%s", path);
  
        network = g_hash_table_lookup(interface->bss_mapping, path);
@@@ -3365,9 -2087,7 +3365,9 @@@ static void interface_bss_added_with_ke
                                                void *user_data)
  {
        struct g_supplicant_bss *bss;
 -
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        SUPPLICANT_DBG("");
  
        bss = interface_bss_added(iter, user_data);
        dbus_message_iter_next(iter);
  
        if (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_INVALID)
 +#if defined TIZEN_EXT
 +      {
 +              g_free(bss->path);
 +              g_free(bss);
 +              return;
 +      }
 +#else
                return;
 +#endif
  
        supplicant_dbus_property_foreach(iter, bss_property, bss);
  
@@@ -3398,9 -2110,7 +3398,9 @@@ static void interface_bss_added_without
                                                void *user_data)
  {
        struct g_supplicant_bss *bss;
 -
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        SUPPLICANT_DBG("");
  
        bss = interface_bss_added(iter, user_data);
@@@ -3422,87 -2132,22 +3422,87 @@@ static void update_signal(gpointer key
        struct g_supplicant_bss *bss = value;
        GSupplicantNetwork *network = user_data;
  
 +#if defined TIZEN_EXT
 +      if (!network->best_bss || (network->best_bss == bss)) {
 +              if (bss->signal > network->signal) {
 +                      network->signal = bss->signal;
 +                      network->best_bss = bss;
 +              }
 +              return;
 +      }
 +
 +      update_best_bss(network, bss, network->best_bss);
 +#else
        if (bss->signal > network->signal) {
                network->signal = bss->signal;
                network->best_bss = bss;
        }
 +#endif
 +}
 +
 +static void update_network_signal(GSupplicantNetwork *network)
 +{
 +      if (g_hash_table_size(network->bss_table) <= 1 && network->best_bss)
 +              return;
 +
 +      g_hash_table_foreach(network->bss_table,
 +                              update_signal, network);
 +
 +      SUPPLICANT_DBG("New network signal %d", network->signal);
 +}
 +
 +#if defined TIZEN_EXT
 +static gboolean last_connected_timeout(gpointer data)
 +{
 +      GSupplicantInterface *interface = data;
 +      GSupplicantNetwork *current_network = interface->current_network;
 +
 +      SUPPLICANT_DBG("Timeout last connected bss");
 +
 +      if (current_network && current_network->best_bss) {
 +              if (compare_bssid(current_network->best_bss->bssid, interface->connected_bssid)) {
 +                      g_supplicant_network_set_last_connected_bssid(current_network, interface->connected_bssid);
 +                      callback_network_changed(current_network, "LastConnectedBSSID");
 +              }
 +      }
 +
 +      last_connected_bss_timeout = 0;
 +      return FALSE;
 +}
 +
 +static void add_timer_for_last_connected(GSupplicantInterface *interface)
 +{
 +      GSupplicantNetwork *current_network = interface->current_network;
 +
 +      if (interface->state == G_SUPPLICANT_STATE_COMPLETED) {
 +              if (current_network) {
 +                      struct g_supplicant_bss *best_bss = current_network->best_bss;
 +
 +                      memcpy(interface->connected_bssid, best_bss->bssid, WIFI_BSSID_LEN_MAX);
 +
 +                      if (last_connected_bss_timeout)
 +                              g_source_remove(last_connected_bss_timeout);
 +
 +                      last_connected_bss_timeout = g_timeout_add_seconds(LAST_CONNECTED_TIMEOUT,
 +                              last_connected_timeout, interface);
 +
 +                      SUPPLICANT_DBG("Add timer for last connected bssid [" MACSTR "]",
 +                                      MAC2STR(best_bss->bssid));
 +              }
 +      }
  }
  
 -static void update_network_signal(GSupplicantNetwork *network)
 +static void remove_timer_for_last_connected(GSupplicantInterface *interface)
  {
 -      if (g_hash_table_size(network->bss_table) <= 1 && network->best_bss)
 -              return;
 -
 -      g_hash_table_foreach(network->bss_table,
 -                              update_signal, network);
 -
 -      SUPPLICANT_DBG("New network signal %d", network->signal);
 +      if (interface->state == G_SUPPLICANT_STATE_DISCONNECTED) {
 +              if (last_connected_bss_timeout != 0) {
 +                      g_source_remove(last_connected_bss_timeout);
 +                      last_connected_bss_timeout = 0;
 +                      SUPPLICANT_DBG("Remove timer for last connected bss");
 +              }
 +      }
  }
 +#endif
  
  static void interface_current_bss(GSupplicantInterface *interface,
                                                DBusMessageIter *iter)
                return;
  
        interface->current_network = network;
 +#if defined TIZEN_EXT
 +      SUPPLICANT_DBG("current network [%p]", interface->current_network);
 +#endif
  
        if (bss != network->best_bss) {
                /*
  
                network->best_bss = bss;
  
 +#if defined TIZEN_EXT
 +              if (network->frequency != bss->frequency)
 +                      network->frequency = bss->frequency;
 +#endif
 +
                if (network->signal != bss->signal) {
                        SUPPLICANT_DBG("New network signal %d dBm",
                                                bss->signal);
                        network->signal = bss->signal;
                        callback_network_changed(network, "Signal");
                }
 +#if defined TIZEN_EXT
 +              else
 +                      callback_network_changed(network, "");
 +#endif
        }
  
        /*
        case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
        case G_SUPPLICANT_STATE_COMPLETED:
                callback_network_associated(network);
 +#if defined TIZEN_EXT
 +              add_timer_for_last_connected(interface);
 +#endif
                break;
        }
  }
@@@ -3622,11 -2252,7 +3622,11 @@@ static void interface_bss_removed(DBusM
                g_hash_table_remove(interface->network_table, network->group);
        } else {
                if (is_current_network_bss && network->best_bss)
 +#if defined TIZEN_EXT
 +                      callback_network_changed(network, "CheckMultiBssidConnect");
 +#else
                        callback_network_changed(network, "");
 +#endif
        }
  }
  
@@@ -3642,9 -2268,7 +3642,9 @@@ static void wps_property(const char *ke
  
        if (!interface)
                return;
 -
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        SUPPLICANT_DBG("key: %s", key);
  
        if (g_strcmp0(key, "ConfigMethods") == 0) {
  
  }
  
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +void g_supplicant_replace_config_file(const char *ifname, const char *config_file)
 +{
 +      if (!ifname)
 +             return;
 +
 +      if (!config_file)
 +              return;
 +
 +      SUPPLICANT_DBG("New {%s, %s}", ifname, config_file);
 +      g_hash_table_replace(config_file_table,
 +                      g_strdup(ifname), g_strdup(config_file));
 +}
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
  static void interface_property(const char *key, DBusMessageIter *iter,
                                                        void *user_data)
  {
  
        if (!interface)
                return;
 -
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        SUPPLICANT_DBG("%s", key);
  
        if (!key) {
        if (g_strcmp0(key, "Capabilities") == 0) {
                supplicant_dbus_property_foreach(iter, interface_capability,
                                                                interface);
 +#if !defined TIZEN_EXT
                if (interface->mode_capa & G_SUPPLICANT_CAPABILITY_MODE_P2P)
                        interface->p2p_support = true;
 +#endif
 +#if defined TIZEN_EXT_WIFI_MESH
 +              if (interface->mode_capa & G_SUPPLICANT_CAPABILITY_MODE_MESH)
 +                      interface->mesh_support = true;
 +#endif
        } else if (g_strcmp0(key, "State") == 0) {
                const char *str = NULL;
  
                                interface->state = string2state(str);
                                callback_interface_state(interface);
                        }
 -
 +#if defined TIZEN_EXT
 +              switch (interface->state) {
 +              case G_SUPPLICANT_STATE_COMPLETED:
 +                      add_timer_for_last_connected(interface);
 +                      break;
 +              case G_SUPPLICANT_STATE_DISCONNECTED:
 +                      remove_timer_for_last_connected(interface);
 +                      break;
 +              default:
 +                      break;
 +              }
 +#endif
                if (interface->ap_create_in_progress) {
                        if (interface->state == G_SUPPLICANT_STATE_DISCONNECTED)
                                callback_ap_create_fail(interface);
        } else if (g_strcmp0(key, "CurrentBSS") == 0) {
                interface_current_bss(interface, iter);
        } else if (g_strcmp0(key, "CurrentNetwork") == 0) {
 +#if defined TIZEN_EXT
 +              if (interface->state != G_SUPPLICANT_STATE_COMPLETED)
 +#endif
                interface_network_added(iter, interface);
        } else if (g_strcmp0(key, "BSSs") == 0) {
                supplicant_dbus_array_foreach(iter,
                if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
                        dbus_message_iter_get_basic(iter, &reason_code);
                        callback_disconnect_reason_code(interface, reason_code);
 +#if defined TIZEN_EXT
 +                      SUPPLICANT_DBG("reason code (%d)", reason_code);
 +#endif
                }
        } else if (g_strcmp0(key, "AssocStatusCode") == 0) {
                int status_code;
                if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
                        dbus_message_iter_get_basic(iter, &status_code);
                        callback_assoc_status_code(interface, status_code);
 +#if defined TIZEN_EXT
 +                      SUPPLICANT_DBG("status code (%d)", status_code);
 +#endif
                }
        } else {
                SUPPLICANT_DBG("key %s type %c",
@@@ -3883,32 -2464,15 +3883,32 @@@ static void scan_bss_data(const char *k
  {
        GSupplicantInterface *interface = user_data;
  
 +/*Fixed : stucking in scanning state when scan failed*/
 +#if defined TIZEN_EXT
 +      GSupplicantInterfaceCallback scan_callback;
 +      SUPPLICANT_DBG("");
 +#endif
 +
        if (iter)
                supplicant_dbus_array_foreach(iter, scan_network_update,
                                                interface);
  
 +#if defined TIZEN_EXT
 +      scan_callback = interface->scan_callback;
 +      callback_scan_done(interface);
 +#endif
 +
        if (interface->scan_callback)
                interface->scan_callback(0, interface, interface->scan_data);
  
 +#if defined TIZEN_EXT
 +      if (interface->scan_callback == scan_callback) {
 +#endif
        interface->scan_callback = NULL;
        interface->scan_data = NULL;
 +#if defined TIZEN_EXT
 +      }
 +#endif
  }
  
  static GSupplicantInterface *interface_alloc(const char *path)
@@@ -4116,9 -2680,7 +4116,9 @@@ static void signal_interface_removed(co
  static void signal_interface_changed(const char *path, DBusMessageIter *iter)
  {
        GSupplicantInterface *interface;
 -
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        SUPPLICANT_DBG("");
  
        interface = g_hash_table_lookup(interface_table, path);
@@@ -4168,9 -2730,7 +4168,9 @@@ static void signal_scan_done(const cha
  static void signal_bss_added(const char *path, DBusMessageIter *iter)
  {
        GSupplicantInterface *interface;
 -
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        SUPPLICANT_DBG("");
  
        interface = g_hash_table_lookup(interface_table, path);
@@@ -4218,13 -2778,6 +4218,13 @@@ static void signal_network_removed(cons
  
        interface_network_removed(iter, interface);
  }
 +#if defined TIZEN_EXT
 +void *copy_vsie_list(gconstpointer src, gpointer data)
 +{
 +      return g_strdup(src);
 +}
 +#endif
 +
  
  static void signal_sta_authorized(const char *path, DBusMessageIter *iter)
  {
@@@ -4262,40 -2815,6 +4262,40 @@@ static void signal_sta_deauthorized(con
        callback_sta_deauthorized(interface, addr);
  }
  
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +static void signal_eap(const char *path, DBusMessageIter *iter)
 +{
 +      GSupplicantInterface *interface;
 +      const char *str = NULL;
 +
 +      SUPPLICANT_DBG("EAPOL_DEBUG callback eap signal");
 +
 +      interface = g_hash_table_lookup(interface_table, path);
 +      if (!interface)
 +              return;
 +
 +      // TODO: Identify EAP fail condition, currently timeout is used for failure.
 +
 +      dbus_message_iter_get_basic(iter, &str);
 +      if (!str)
 +              return;
 +
 +      if (g_strcmp0("completion", str))
 +              return;
 +
 +      dbus_message_iter_next(iter);
 +
 +      dbus_message_iter_get_basic(iter, &str);
 +      if (!str)
 +              return;
 +
 +      if (!g_strcmp0("success", str))
 +              callback_eap(interface, true);
 +      else
 +              callback_eap(interface, false);
 +}
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
  static void signal_bss_changed(const char *path, DBusMessageIter *iter)
  {
        GSupplicantInterface *interface;
        unsigned int old_wps_capabilities;
        struct g_supplicant_bss *bss;
  
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        SUPPLICANT_DBG("");
  
        interface = g_hash_table_lookup(bss_mapping, path);
  
        supplicant_dbus_property_foreach(iter, bss_property, bss);
  
 +#if defined TIZEN_EXT
 +      if (network->interface->state != G_SUPPLICANT_STATE_COMPLETED) {
 +              network->frequency = bss->frequency;
 +              network->phy_mode = bss->phy_mode;
 +      }
 +#endif
        old_security = network->security;
        bss_compute_security(bss);
  
  
                memcpy(new_bss, bss, sizeof(struct g_supplicant_bss));
                new_bss->path = g_strdup(bss->path);
 +#if defined TIZEN_EXT
 +              new_bss->vsie_list = g_slist_copy_deep(bss->vsie_list, copy_vsie_list, NULL);
 +#endif
  
                if (network->best_bss == bss) {
                        network->best_bss = NULL;
                callback_network_changed(network, "WPSCapabilities");
        }
  
 +#if defined TIZEN_EXT
 +      if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0) {
 +              network->wps = TRUE;
 +              network->wps_capabilities |= bss->wps_capabilities;
 +      } else
 +              network->wps = FALSE;
 +#endif
 +
        /* Consider only property changes of the connected BSS */
        if (network == interface->current_network && bss != network->best_bss)
                return;
  
        if (bss->signal == network->signal)
 +#ifndef TIZEN_EXT
                return;
 +#else
 +      {
 +              callback_network_changed(network, "");
 +              return;
 +      }
 +#endif
  
        /*
         * If the new signal is lower than the SSID signal, we need
         * to check for the new maximum.
         */
 +#if defined TIZEN_EXT
 +      if (!update_best_bss(network, bss, network->best_bss)) {
 +              if (bss != network->best_bss) {
 +                      callback_network_changed(network, "");
 +                      return;
 +              }
 +
 +              network->signal = bss->signal;
 +              update_network_signal(network);
 +      }
 +#else
        if (bss->signal < network->signal) {
                if (bss != network->best_bss)
                        return;
 +
                network->signal = bss->signal;
                update_network_signal(network);
        } else {
                network->signal = bss->signal;
                network->best_bss = bss;
        }
 +#endif
  
        SUPPLICANT_DBG("New network signal for %s %d dBm", network->ssid,
                        network->signal);
@@@ -4551,29 -3030,6 +4551,29 @@@ static void signal_wps_event(const cha
        supplicant_dbus_property_foreach(iter, wps_event_args, interface);
  }
  
 +#if defined TIZEN_EXT
 +static void signal_power_off(const char *path, DBusMessageIter *iter)
 +{
 +      int poweroff_state = 0;
 +
 +      dbus_message_iter_get_basic(iter, &poweroff_state);
 +
 +      SUPPLICANT_DBG("poweroff_state(%d)", poweroff_state);
 +
 +      /* POWER_OFF_DIRECT 2 && POWER_OFF_RESTART 3 */
 +      if (poweroff_state != 2 && poweroff_state != 3)
 +              return;
 +
 +      if (callbacks_pointer == NULL)
 +              return;
 +
 +      if (callbacks_pointer->system_power_off == NULL)
 +              return;
 +
 +      callbacks_pointer->system_power_off();
 +}
 +#endif
 +
  static void create_peer_identifier(GSupplicantPeer *peer)
  {
        const unsigned char test[ETH_ALEN] = {};
@@@ -5111,217 -3567,9 +5111,217 @@@ static void signal_group_peer_disconnec
        if (!peer)
                return;
  
 -      callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_DISCONNECTED);
 -      peer->connection_requested = false;
 +      callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_DISCONNECTED);
 +      peer->connection_requested = false;
 +}
 +
 +#if defined TIZEN_EXT_WIFI_MESH
 +const void *g_supplicant_interface_get_mesh_group_ssid(
 +                                                      GSupplicantInterface *interface,
 +                                                      unsigned int *ssid_len)
 +{
 +      if (!ssid_len)
 +              return NULL;
 +
 +      if (!interface || interface->group_info.ssid_len == 0) {
 +              *ssid_len = 0;
 +              return NULL;
 +      }
 +
 +      *ssid_len = interface->group_info.ssid_len;
 +      return interface->group_info.ssid;
 +}
 +
 +int g_supplicant_mesh_get_disconnect_reason(GSupplicantInterface *interface)
 +{
 +      if (!interface)
 +              return -EINVAL;
 +
 +      return interface->group_info.disconnect_reason;
 +}
 +
 +const char *g_supplicant_mesh_peer_get_address(GSupplicantMeshPeer *mesh_peer)
 +{
 +      if (!mesh_peer || !mesh_peer->peer_address)
 +              return NULL;
 +
 +      return mesh_peer->peer_address;
 +}
 +
 +int g_supplicant_mesh_peer_get_disconnect_reason(GSupplicantMeshPeer *mesh_peer)
 +{
 +      if (!mesh_peer)
 +              return -EINVAL;
 +
 +      return mesh_peer->disconnect_reason;
 +}
 +
 +static void callback_mesh_group_started(GSupplicantInterface *interface)
 +{
 +      if (!callbacks_pointer)
 +              return;
 +
 +      if (!callbacks_pointer->mesh_group_started)
 +              return;
 +
 +      callbacks_pointer->mesh_group_started(interface);
 +}
 +
 +static void callback_mesh_group_removed(GSupplicantInterface *interface)
 +{
 +      if (!callbacks_pointer)
 +              return;
 +
 +      if (!callbacks_pointer->mesh_group_removed)
 +              return;
 +
 +      callbacks_pointer->mesh_group_removed(interface);
 +}
 +
 +static void mesh_group_info(const char *key, DBusMessageIter *iter,
 +                                                      void *user_data)
 +{
 +      GSupplicantInterface *interface = user_data;
 +      if (!key)
 +              return;
 +
 +      if (g_strcmp0(key, "SSID") == 0) {
 +              DBusMessageIter array;
 +              unsigned char *ssid;
 +              int ssid_len;
 +
 +              dbus_message_iter_recurse(iter, &array);
 +              dbus_message_iter_get_fixed_array(&array, &ssid, &ssid_len);
 +
 +              if (ssid_len > 0 && ssid_len < 33) {
 +                      memcpy(interface->group_info.ssid, ssid, ssid_len);
 +                      interface->group_info.ssid_len = ssid_len;
 +              } else {
 +                      memset(interface->group_info.ssid, 0, 32);
 +                      interface->group_info.ssid_len = 0;
 +              }
 +      } else if (g_strcmp0(key, "DisconnectReason") == 0) {
 +              int disconnect_reason = 0;
 +              dbus_message_iter_get_basic(iter, &disconnect_reason);
 +              interface->group_info.disconnect_reason = disconnect_reason;
 +      }
 +}
 +
 +static void signal_mesh_group_started(const char *path, DBusMessageIter *iter)
 +{
 +      GSupplicantInterface *interface;
 +
 +      interface = g_hash_table_lookup(interface_table, path);
 +      if (!interface)
 +              return;
 +
 +      supplicant_dbus_property_foreach(iter, mesh_group_info, interface);
 +
 +      callback_mesh_group_started(interface);
 +}
 +
 +static void signal_mesh_group_removed(const char *path, DBusMessageIter *iter)
 +{
 +      GSupplicantInterface *interface;
 +
 +      interface = g_hash_table_lookup(interface_table, path);
 +      if (!interface)
 +              return;
 +
 +      supplicant_dbus_property_foreach(iter, mesh_group_info, interface);
 +
 +      callback_mesh_group_removed(interface);
 +}
 +
 +static void callback_mesh_peer_connected(GSupplicantMeshPeer *mesh_peer)
 +{
 +      if (!callbacks_pointer)
 +              return;
 +
 +      if (!callbacks_pointer->mesh_peer_connected)
 +              return;
 +
 +      callbacks_pointer->mesh_peer_connected(mesh_peer);
 +}
 +
 +static void callback_mesh_peer_disconnected(GSupplicantMeshPeer *mesh_peer)
 +{
 +      if (!callbacks_pointer)
 +              return;
 +
 +      if (!callbacks_pointer->mesh_peer_disconnected)
 +              return;
 +
 +      callbacks_pointer->mesh_peer_disconnected(mesh_peer);
 +}
 +
 +static void mesh_peer_info(const char *key, DBusMessageIter *iter,
 +                                                      void *user_data)
 +{
 +      GSupplicantMeshPeer *mesh_peer = user_data;
 +      if (!key)
 +              return;
 +
 +      if (g_strcmp0(key, "PeerAddress") == 0) {
 +              DBusMessageIter array;
 +              unsigned char *addr;
 +              int addr_len;
 +
 +              dbus_message_iter_recurse(iter, &array);
 +              dbus_message_iter_get_fixed_array(&array, &addr, &addr_len);
 +
 +              if (addr_len == 6) {
 +                      mesh_peer->peer_address = g_malloc0(19);
 +                      snprintf(mesh_peer->peer_address, 19,
 +                                       "%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1],
 +                                       addr[2], addr[3], addr[4], addr[5]);
 +              }
 +      } else if (g_strcmp0(key, "DisconnectReason") == 0) {
 +              int disconnect_reason = 0;
 +              dbus_message_iter_get_basic(iter, &disconnect_reason);
 +              mesh_peer->disconnect_reason = disconnect_reason;
 +      }
 +}
 +
 +static void signal_mesh_peer_connected(const char *path, DBusMessageIter *iter)
 +{
 +      GSupplicantInterface *interface;
 +      GSupplicantMeshPeer *mesh_peer;
 +
 +      interface = g_hash_table_lookup(interface_table, path);
 +      if (!interface)
 +              return;
 +
 +      mesh_peer = dbus_malloc0(sizeof(GSupplicantMeshPeer));
 +      mesh_peer->interface = interface;
 +
 +      supplicant_dbus_property_foreach(iter, mesh_peer_info, mesh_peer);
 +
 +      callback_mesh_peer_connected(mesh_peer);
 +      g_free(mesh_peer->peer_address);
 +      g_free(mesh_peer);
 +}
 +
 +static void signal_mesh_peer_disconnected(const char *path,
 +                                                              DBusMessageIter *iter)
 +{
 +      GSupplicantInterface *interface;
 +      GSupplicantMeshPeer *mesh_peer;
 +
 +      interface = g_hash_table_lookup(interface_table, path);
 +      if (!interface)
 +              return;
 +
 +      mesh_peer = dbus_malloc0(sizeof(GSupplicantMeshPeer));
 +      mesh_peer->interface = interface;
 +
 +      supplicant_dbus_property_foreach(iter, mesh_peer_info, mesh_peer);
 +
 +      callback_mesh_peer_disconnected(mesh_peer);
 +      g_free(mesh_peer->peer_address);
 +      g_free(mesh_peer);
  }
 +#endif
  
  static struct {
        const char *interface;
  
        { SUPPLICANT_INTERFACE ".Interface.WPS", "Credentials", signal_wps_credentials },
        { SUPPLICANT_INTERFACE ".Interface.WPS", "Event",       signal_wps_event       },
 +#if defined TIZEN_EXT
 +      { "org.tizen.system.deviced.PowerOff", "ChangeState", signal_power_off },
 +#endif
  
        { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeviceFound", signal_peer_found },
        { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeviceLost",  signal_peer_lost  },
  
        { SUPPLICANT_INTERFACE ".Group", "PeerJoined", signal_group_peer_joined },
        { SUPPLICANT_INTERFACE ".Group", "PeerDisconnected", signal_group_peer_disconnected },
 +#if defined TIZEN_EXT_WIFI_MESH
 +      { SUPPLICANT_INTERFACE ".Interface.Mesh", "MeshGroupStarted",
 +              signal_mesh_group_started },
 +      { SUPPLICANT_INTERFACE ".Interface.Mesh", "MeshGroupRemoved",
 +              signal_mesh_group_removed },
 +      { SUPPLICANT_INTERFACE ".Interface.Mesh", "MeshPeerConnected",
 +              signal_mesh_peer_connected },
 +      { SUPPLICANT_INTERFACE ".Interface.Mesh", "MeshPeerDisconnected",
 +              signal_mesh_peer_disconnected },
 +#endif
 +
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      { SUPPLICANT_INTERFACE ".Interface", "EAP", signal_eap },
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
  
        { }
  };
@@@ -5444,7 -3675,7 +5444,7 @@@ static void country_result(const char *
                regdom->callback(result, regdom->alpha2,
                                        (void *) regdom->user_data);
  
-       dbus_free(regdom);
+       g_free(regdom);
  }
  
  static void country_params(DBusMessageIter *iter, void *user_data)
@@@ -5657,9 -3888,6 +5657,9 @@@ static void interface_create_data_free(
        g_free(data->ifname);
        g_free(data->driver);
        g_free(data->bridge);
 +#if defined TIZEN_EXT_WIFI_MESH
 +      g_free(data->parent_ifname);
 +#endif
        dbus_free(data);
  }
  
@@@ -5684,12 -3912,7 +5684,12 @@@ static void interface_create_property(c
        if (!key) {
                if (data->callback) {
                        data->callback(0, data->interface, data->user_data);
 +#if !defined TIZEN_EXT
                        callback_p2p_support(interface);
 +#endif
 +#if defined TIZEN_EXT_WIFI_MESH
 +                      callback_mesh_support(interface);
 +#endif
                }
  
                interface_create_data_free(data);
@@@ -5708,7 -3931,7 +5708,7 @@@ static void interface_create_result(con
        SUPPLICANT_DBG("");
  
        if (error) {
-               g_message("error %s", error);
+               g_warning("error %s", error);
                err = -EIO;
                goto done;
        }
@@@ -5776,80 -3999,9 +5776,80 @@@ static void interface_create_params(DBu
                                        DBUS_TYPE_STRING, &config_file);
        }
  
 +#ifdef TIZEN_EXT
 +      if (data->driver && g_strstr_len(data->driver, strlen(data->driver), "nl80211")) {
 +              supplicant_dbus_dict_append_basic(&dict, "MacAddr",
 +                              DBUS_TYPE_UINT32, &data->mac_addr);
 +
 +              supplicant_dbus_dict_append_basic(&dict, "PreassocMacAddr",
 +                              DBUS_TYPE_UINT32, &data->preassoc_mac_addr);
 +
 +              supplicant_dbus_dict_append_basic(&dict, "RandAddrLifetime",
 +                              DBUS_TYPE_UINT32, &data->random_mac_lifetime);
 +      }
 +#endif /* TIZEN_EXT */
 +
 +#if defined TIZEN_EXT_WIFI_MESH
 +      if (data->is_mesh_interface) {
 +              if (data->parent_ifname)
 +                      supplicant_dbus_dict_append_basic(&dict, "ParentIfname",
 +                                      DBUS_TYPE_STRING, &data->parent_ifname);
 +
 +              supplicant_dbus_dict_append_basic(&dict, "IsMeshInterface",
 +                                      DBUS_TYPE_BOOLEAN, &data->is_mesh_interface);
 +      }
 +#endif
 +
        supplicant_dbus_dict_close(iter, &dict);
  }
  
 +#if defined TIZEN_EXT
 +static void interface_get_state(const char *key, DBusMessageIter *iter,
 +              void *user_data)
 +{
 +      struct interface_create_data *data = user_data;
 +      GSupplicantInterface *interface = NULL;
 +      const char *str = NULL;
 +
 +      SUPPLICANT_DBG("key[%s]", key);
 +
 +      if (!data) {
 +              SUPPLICANT_DBG("data is NULL");
 +              return;
 +      }
 +
 +      interface = data->interface;
 +      if (!interface) {
 +              SUPPLICANT_DBG("interface is NULL");
 +              return;
 +      }
 +
 +      if (iter)
 +              dbus_message_iter_get_basic(iter, &str);
 +
 +      if (str) {
 +              if (string2state(str) != interface->state)
 +                      interface->state = string2state(str);
 +      }
 +
 +      if (interface->state == G_SUPPLICANT_STATE_DISABLED)
 +              interface->ready = FALSE;
 +      else
 +              interface->ready = TRUE;
 +
 +      SUPPLICANT_DBG("state %s (%d)", str, interface->state);
 +
 +      if (data->callback) {
 +              data->callback(0, interface, data->user_data);
 +#if defined TIZEN_EXT_WIFI_MESH
 +              callback_mesh_support(interface);
 +#endif
 +      }
 +
 +      interface_create_data_free(data);
 +}
 +#endif
 +
  static void interface_get_result(const char *error,
                                DBusMessageIter *iter, void *user_data)
  {
        const char *path = NULL;
        int err;
  
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        SUPPLICANT_DBG("");
  
        if (error) {
                goto done;
        }
  
 +#if defined TIZEN_EXT
 +      data->interface = interface;
 +      err = supplicant_dbus_property_get(path,
 +                      SUPPLICANT_INTERFACE ".Interface",
 +                      "State", interface_get_state, data, NULL);
 +
 +      if (err == 0)
 +              return;
 +#endif
 +
        if (data->callback) {
                data->callback(0, interface, data->user_data);
 +#if !defined TIZEN_EXT
                callback_p2p_support(interface);
 +#endif
 +#if defined TIZEN_EXT_WIFI_MESH
 +              callback_mesh_support(interface);
 +#endif
        }
  
        interface_create_data_free(data);
  static void interface_get_params(DBusMessageIter *iter, void *user_data)
  {
        struct interface_create_data *data = user_data;
 -
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        SUPPLICANT_DBG("");
  
        dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &data->ifname);
  }
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +int g_supplicant_mesh_interface_create(const char *ifname, const char *driver,
 +                                              const char *bridge, const char *parent_ifname,
 +                                              GSupplicantInterfaceCallback callback, void *user_data)
 +{
 +      struct interface_create_data *data;
 +      int ret;
 +
 +      SUPPLICANT_DBG("ifname %s", ifname);
 +
 +      if (!ifname || !parent_ifname)
 +              return -EINVAL;
 +
 +      if (!system_available)
 +              return -EFAULT;
 +
 +      data = dbus_malloc0(sizeof(*data));
 +      if (!data)
 +              return -ENOMEM;
 +
 +      data->ifname = g_strdup(ifname);
 +      data->driver = g_strdup(driver);
 +      data->bridge = g_strdup(bridge);
 +      data->is_mesh_interface = true;
 +      data->parent_ifname = g_strdup(parent_ifname);
 +      data->callback = callback;
 +      data->user_data = user_data;
 +
 +      ret = supplicant_dbus_method_call(SUPPLICANT_PATH,
 +                                              SUPPLICANT_INTERFACE,
 +                                              "CreateInterface",
 +                                              interface_create_params,
 +                                              interface_create_result, data,
 +                                              NULL);
 +      return ret;
 +}
 +
 +struct interface_mesh_peer_data {
 +      char *peer_address;
 +      char *method;
 +      GSupplicantInterface *interface;
 +      GSupplicantInterfaceCallback callback;
 +      void *user_data;
 +};
 +
 +static void interface_mesh_change_peer_params(DBusMessageIter *iter,
 +                                              void *user_data)
 +{
 +      struct interface_mesh_peer_data *data = user_data;
 +
 +      SUPPLICANT_DBG("");
 +
 +      dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &data->peer_address);
 +}
 +
 +static void interface_mesh_change_peer_result(const char *error,
 +                              DBusMessageIter *iter, void *user_data)
 +{
 +      struct interface_mesh_peer_data *data = user_data;
 +      int err = 0;
 +
 +      SUPPLICANT_DBG("%s", data->method);
 +
 +      if (error) {
 +              err = -EIO;
 +              SUPPLICANT_DBG("error %s", error);
 +      }
 +
 +      if (data->callback)
 +              data->callback(err, data->interface, data->user_data);
 +
 +      g_free(data->peer_address);
 +      g_free(data->method);
 +      dbus_free(data);
 +}
 +
 +int g_supplicant_interface_mesh_peer_change_status(
 +                              GSupplicantInterface *interface,
 +                              GSupplicantInterfaceCallback callback, const char *peer_address,
 +                              const char *method, void *user_data)
 +{
 +      struct interface_mesh_peer_data *data;
 +      int ret;
 +
 +      if (!peer_address)
 +              return -EINVAL;
 +
 +      data = dbus_malloc0(sizeof(*data));
 +      if (!data)
 +              return -ENOMEM;
 +
 +      data->peer_address = g_strdup(peer_address);
 +      data->method = g_strdup(method);
 +      data->interface = interface;
 +      data->callback = callback;
 +      data->user_data = user_data;
 +
 +      ret = supplicant_dbus_method_call(interface->path,
 +                                              SUPPLICANT_INTERFACE ".Interface.Mesh",
 +                                              method, interface_mesh_change_peer_params,
 +                                              interface_mesh_change_peer_result, data, NULL);
 +      if (ret < 0) {
 +              g_free(data->peer_address);
 +              g_free(data->method);
 +              dbus_free(data);
 +      }
 +
 +      return ret;
 +}
 +#endif
 +
  int g_supplicant_interface_create(const char *ifname, const char *driver,
                                        const char *bridge,
 +#ifdef TIZEN_EXT
 +                                      unsigned int mac_policy,
 +                                      unsigned int preassoc_mac_policy,
 +                                      unsigned int random_mac_lifetime,
 +#endif /* TIZEN_EXT */
                                        GSupplicantInterfaceCallback callback,
                                                        void *user_data)
  {
        data->driver = g_strdup(driver);
        data->bridge = g_strdup(bridge);
        data->callback = callback;
 +#ifdef TIZEN_EXT
 +      data->mac_addr = mac_policy;
 +      data->preassoc_mac_addr = preassoc_mac_policy;
 +      data->random_mac_lifetime = random_mac_lifetime;
 +#endif /* TIZEN_EXT */
        data->user_data = user_data;
  
        ret = supplicant_dbus_method_call(SUPPLICANT_PATH,
@@@ -6139,6 -4150,7 +6139,6 @@@ static void interface_remove_params(DBu
                                                        &data->interface->path);
  }
  
 -
  int g_supplicant_interface_remove(GSupplicantInterface *interface,
                        GSupplicantInterfaceCallback callback,
                                                        void *user_data)
@@@ -6315,10 -4327,6 +6315,10 @@@ static void interface_scan_params(DBusM
                supplicant_dbus_dict_append_basic(&dict, "Type",
                                        DBUS_TYPE_STRING, &type);
  
 +#if defined TIZEN_EXT
 +              SUPPLICANT_DBG("[specific_scan] num_ssids %d",
 +                             data->scan_params->num_ssids);
 +#endif
  
                if (data->scan_params->ssids) {
                        supplicant_dbus_dict_append_array(&dict, "SSIDs",
@@@ -6353,14 -4361,8 +6353,14 @@@ static int interface_ready_to_scan(GSup
        case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
        case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
                return -EBUSY;
 +#if defined TIZEN_EXT
 +      case G_SUPPLICANT_STATE_DISABLED:
 +              return -ENOLINK;
 +      case G_SUPPLICANT_STATE_UNKNOWN:
 +#else
        case G_SUPPLICANT_STATE_UNKNOWN:
        case G_SUPPLICANT_STATE_DISABLED:
 +#endif
        case G_SUPPLICANT_STATE_DISCONNECTED:
        case G_SUPPLICANT_STATE_INACTIVE:
        case G_SUPPLICANT_STATE_SCANNING:
        return 0;
  }
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +static void interface_abort_scan_result(const char *error,
 +                              DBusMessageIter *iter, void *user_data)
 +{
 +      struct interface_scan_data *data = user_data;
 +      int err = 0;
 +
 +      if (error) {
 +              SUPPLICANT_DBG("error %s", error);
 +              err = -EIO;
 +      }
 +
 +      g_free(data->path);
 +
 +              if (data->callback)
 +                      data->callback(err, data->interface, data->user_data);
 +
 +      dbus_free(data);
 +}
 +
 +int g_supplicant_interface_abort_scan(GSupplicantInterface *interface,
 +                              GSupplicantInterfaceCallback callback, void *user_data)
 +{
 +      struct interface_scan_data *data;
 +      int ret;
 +
 +      if (!interface->scanning)
 +              return -EEXIST;
 +
 +      data = dbus_malloc0(sizeof(*data));
 +      if (!data)
 +              return -ENOMEM;
 +
 +      data->interface = interface;
 +      data->path = g_strdup(interface->path);
 +      data->callback = callback;
 +      data->user_data = user_data;
 +
 +      ret = supplicant_dbus_method_call(interface->path,
 +                      SUPPLICANT_INTERFACE ".Interface", "AbortScan", NULL,
 +                      interface_abort_scan_result, data, interface);
 +
 +      if (ret < 0) {
 +              g_free(data->path);
 +              dbus_free(data);
 +      }
 +
 +      return ret;
 +}
 +#endif
 +
  int g_supplicant_interface_scan(GSupplicantInterface *interface,
                                GSupplicantScanParams *scan_data,
                                GSupplicantInterfaceCallback callback,
  
        data->interface = interface;
        data->path = g_strdup(interface->path);
 +#if defined TIZEN_EXT
 +      data->interface->scan_callback = data->callback = callback;
 +      data->interface->scan_data = data->user_data = user_data;
 +#else
        data->callback = callback;
        data->user_data = user_data;
 +#endif
        data->scan_params = scan_data;
  
          interface->scan_callback = callback;
        return ret;
  }
  
 +#if defined TIZEN_EXT
 +static void interface_signalpoll_result(const char *error,
 +                                DBusMessageIter *iter, void *user_data)
 +{
 +      struct interface_signalpoll_data *data = user_data;
 +      int err = 0;
 +      dbus_int32_t maxspeed = 0;
 +      dbus_int32_t strength = 0;
 +      dbus_int32_t snr = 0;
 +      DBusMessageIter sub_iter, dict;
 +
 +      if (error) {
 +              err = -EIO;
 +              SUPPLICANT_DBG("error: %s", error);
 +              goto out;
 +      }
 +
 +      if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT) {
 +              err = -EINVAL;
 +              SUPPLICANT_DBG("invalid reply");
 +              goto out;
 +      }
 +
 +      dbus_message_iter_recurse(iter, &sub_iter);
 +      dbus_message_iter_recurse(&sub_iter, &dict);
 +
 +      while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
 +              DBusMessageIter entry, value;
 +              const char *key;
 +
 +              dbus_message_iter_recurse(&dict, &entry);
 +              dbus_message_iter_get_basic(&entry, &key);
 +              dbus_message_iter_next(&entry);
 +              dbus_message_iter_recurse(&entry, &value);
 +
 +              switch (dbus_message_iter_get_arg_type(&value)) {
 +              case DBUS_TYPE_INT32:
 +                      if (g_strcmp0(key, "linkspeed") == 0) {
 +                              dbus_message_iter_get_basic(&value, &maxspeed);
 +                              SUPPLICANT_DBG("linkspeed = %d", maxspeed);
 +                              break;
 +                      } else if (g_strcmp0(key, "rssi") == 0) {
 +                              dbus_message_iter_get_basic(&value, &strength);
 +                              SUPPLICANT_DBG("Strength = %d", strength);
 +                              break;
 +                      } else if (g_strcmp0(key, "SNR") == 0) {
 +                              dbus_message_iter_get_basic(&value, &snr);
 +                              SUPPLICANT_DBG("SNR = %d", snr);
 +                              break;
 +                      }
 +              }
 +              dbus_message_iter_next(&dict);
 +      }
 +
 +out:
 +      if(data->callback)
 +              data->callback(err, maxspeed, strength, snr, data->user_data);
 +
 +      g_free(data->path);
 +      dbus_free(data);
 +}
 +
 +int g_supplicant_interface_signalpoll(GSupplicantInterface *interface,
 +                              GSupplicantMaxSpeedCallback callback,
 +                              void *user_data)
 +{
 +      struct interface_signalpoll_data *data;
 +      int ret;
 +
 +      if (!interface)
 +              return -EINVAL;
 +
 +      if (!system_available)
 +              return -EFAULT;
 +
 +      data = dbus_malloc0(sizeof(*data));
 +      if (!data)
 +              return -ENOMEM;
 +
 +      data->interface = interface;
 +      data->path = g_strdup(interface->path);
 +      data->callback = callback;
 +      data->user_data = user_data;
 +
 +      ret = supplicant_dbus_method_call(interface->path,
 +                      SUPPLICANT_INTERFACE ".Interface", "SignalPoll",
 +                      NULL, interface_signalpoll_result, data,
 +                      interface);
 +
 +      if (ret < 0) {
 +              g_free(data->path);
 +              dbus_free(data);
 +      }
 +
 +      return ret;
 +}
 +#endif
 +
  static int parse_supplicant_error(DBusMessageIter *iter)
  {
        int err = -ECONNABORTED;
@@@ -6599,11 -4447,7 +6599,11 @@@ static void interface_select_network_re
  
        err = 0;
        if (error) {
 +#if defined TIZEN_EXT
 +              SUPPLICANT_DBG("SelectNetwork errorFreq %s", error);
 +#else
                SUPPLICANT_DBG("SelectNetwork error %s", error);
 +#endif
                err = parse_supplicant_error(iter);
        }
  
        if (data->callback)
                data->callback(err, data->interface, data->user_data);
  
 +#if defined TIZEN_EXT
 +      g_free(data->ssid->ssid);
 +      g_free((char *)data->ssid->passphrase);
 +      g_free((char *)data->ssid->connector);
 +      g_free((char *)data->ssid->c_sign_key);
 +      g_free((char *)data->ssid->net_access_key);
 +#endif
        g_free(data->ssid);
        dbus_free(data);
  }
@@@ -6628,16 -4465,9 +6628,16 @@@ static void interface_select_network_pa
  {
        struct interface_connect_data *data = user_data;
        GSupplicantInterface *interface = data->interface;
 +#if defined TIZEN_EXT
 +      GSupplicantSSID *ssid = data->ssid;
 +#endif
  
        dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
                                        &interface->network_path);
 +#if defined TIZEN_EXT
 +      if (!ssid->bssid_for_connect_len)
 +              dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &ssid->freq);
 +#endif
  }
  
  static void interface_add_network_result(const char *error,
  
        SUPPLICANT_DBG("PATH: %s", path);
  
 +#if defined TIZEN_EXT
 +      if (interface->network_path)
 +              g_free(interface->network_path);
 +#endif
        interface->network_path = g_strdup(path);
  
        store_network_information(interface, data->ssid);
  
 +#if defined TIZEN_EXT
 +      SUPPLICANT_DBG(".Interface.SelectNetworkFreq");
 +      GSupplicantSSID *ssid = data->ssid;
 +
 +      if (!ssid->bssid_for_connect_len)
 +              supplicant_dbus_method_call(data->interface->path,
 +                              SUPPLICANT_INTERFACE ".Interface", "SelectNetworkFreq",
 +                              interface_select_network_params,
 +                              interface_select_network_result, data,
 +                              interface);
 +      else
 +              supplicant_dbus_method_call(data->interface->path,
 +                              SUPPLICANT_INTERFACE ".Interface", "SelectNetwork",
 +                              interface_select_network_params,
 +                              interface_select_network_result, data,
 +                              interface);
 +#else
        supplicant_dbus_method_call(data->interface->path,
                        SUPPLICANT_INTERFACE ".Interface", "SelectNetwork",
                        interface_select_network_params,
                        interface_select_network_result, data,
                        interface);
 +#endif
  
        return;
  
@@@ -6704,13 -4512,6 +6704,13 @@@ error
        }
  
        g_free(data->path);
 +#if defined TIZEN_EXT
 +      g_free(data->ssid->ssid);
 +      g_free((char *)data->ssid->passphrase);
 +      g_free((char *)data->ssid->connector);
 +      g_free((char *)data->ssid->c_sign_key);
 +      g_free((char *)data->ssid->net_access_key);
 +#endif
        g_free(data->ssid);
        g_free(data);
  }
@@@ -6860,10 -4661,8 +6860,10 @@@ static void add_network_security_tls(DB
        if (!ssid->private_key_path)
                return;
  
 +#if !defined TIZEN_EXT
        if (!ssid->private_key_passphrase)
                return;
 +#endif
  
        if (ssid->ca_cert_path)
                supplicant_dbus_dict_append_basic(dict, "ca_cert",
        supplicant_dbus_dict_append_basic(dict, "private_key",
                                                DBUS_TYPE_STRING,
                                                &ssid->private_key_path);
 +#if !defined TIZEN_EXT
        supplicant_dbus_dict_append_basic(dict, "private_key_passwd",
                                                DBUS_TYPE_STRING,
                                                &ssid->private_key_passphrase);
 +#endif
        supplicant_dbus_dict_append_basic(dict, "client_cert",
                                                DBUS_TYPE_STRING,
                                                &ssid->client_cert_path);
@@@ -6908,10 -4705,8 +6908,10 @@@ static void add_network_security_peap(D
                if (!ssid->private_key_path)
                        return;
  
 +#if !defined TIZEN_EXT
                if (!ssid->private_key_passphrase)
                        return;
 +#endif
  
                supplicant_dbus_dict_append_basic(dict, "client_cert",
                                                DBUS_TYPE_STRING,
                                                DBUS_TYPE_STRING,
                                                &ssid->private_key_path);
  
 +#if !defined TIZEN_EXT
                supplicant_dbus_dict_append_basic(dict, "private_key_passwd",
                                                DBUS_TYPE_STRING,
                                                &ssid->private_key_passphrase);
 +#endif
  
        }
  
        g_free(phase2_auth);
  }
  
 +#if defined TIZEN_EXT
 +static void add_network_security_aka_sim(DBusMessageIter *dict,
 +                                      GSupplicantSSID *ssid)
 +{
 +      if (!ssid->passphrase)
 +              return;
 +
 +      supplicant_dbus_dict_append_basic(dict, "password",
 +                      DBUS_TYPE_STRING,
 +                      &ssid->passphrase);
 +}
 +
 +static void add_network_security_fast(DBusMessageIter *dict,
 +              GSupplicantSSID *ssid)
 +{
 +      /*
 +       * For FAST, we at least need:
 +       *              id / password
 +       *              phase1 (provisiong information)
 +       *              pac_file
 +       */
 +
 +      /* Allow provisioing both authenticated and unauthenticated */
 +      const char *phase1 = "fast_provisioning=2";
 +      supplicant_dbus_dict_append_basic(dict, "phase1",
 +                      DBUS_TYPE_STRING,
 +                      &phase1);
 +
 +      SUPPLICANT_DBG("pac_file [%s]", ssid->pac_file);
 +      if(ssid->pac_file)
 +              supplicant_dbus_dict_append_basic(dict, "pac_file",
 +                              DBUS_TYPE_STRING,
 +                              &ssid->pac_file);
 +
 +      supplicant_dbus_dict_append_basic(dict, "password",
 +                      DBUS_TYPE_STRING,
 +                      &ssid->passphrase);
 +}
 +#endif
 +
  static void add_network_security_eap(DBusMessageIter *dict,
                                        GSupplicantSSID *ssid)
  {
        char *eap_value;
  
 +#if defined TIZEN_EXT
 +      if (!ssid->eap)
 +#else
        if (!ssid->eap || !ssid->identity)
 +#endif
                return;
  
        if (g_strcmp0(ssid->eap, "tls") == 0) {
                add_network_security_tls(dict, ssid);
        } else if (g_strcmp0(ssid->eap, "peap") == 0 ||
                                g_strcmp0(ssid->eap, "ttls") == 0) {
 +#if defined TIZEN_EXT
 +              if (!ssid->identity)
 +                      return;
 +#endif
                add_network_security_peap(dict, ssid);
 +
 +#if defined TIZEN_EXT
 +      } else if (g_strcmp0(ssid->eap, "sim") == 0 ||
 +                      g_strcmp0(ssid->eap, "aka") == 0 ||
 +                      g_strcmp0(ssid->eap, "aka'") == 0) {
 +              add_network_security_aka_sim(dict, ssid);
 +      } else if (g_strcmp0(ssid->eap, "pwd") == 0) {
 +              if(!ssid->passphrase)
 +                      return;
 +              supplicant_dbus_dict_append_basic(dict, "password",
 +                              DBUS_TYPE_STRING,
 +                              &ssid->passphrase);
 +      } else if (g_strcmp0(ssid->eap, "fast") == 0){
 +              if (!ssid->identity || !ssid->passphrase)
 +                      return;
 +
 +              add_network_security_fast(dict, ssid);
 +#endif
        } else
                return;
  
        supplicant_dbus_dict_append_basic(dict, "eap",
                                                DBUS_TYPE_STRING,
                                                &eap_value);
 +#if defined TIZEN_EXT
 +      if (ssid->identity != NULL)
 +              supplicant_dbus_dict_append_basic(dict, "identity",
 +                                                      DBUS_TYPE_STRING,
 +                                                      &ssid->identity);
 +#else
        supplicant_dbus_dict_append_basic(dict, "identity",
                                                DBUS_TYPE_STRING,
                                                &ssid->identity);
 +#endif
        if(ssid->anonymous_identity)
                supplicant_dbus_dict_append_basic(dict, "anonymous_identity",
                                                     DBUS_TYPE_STRING,
@@@ -7170,83 -4890,6 +7170,83 @@@ static void add_network_security_proto(
        g_free(proto);
  }
  
 +#if defined TIZEN_EXT
 +static void add_network_ieee80211w(DBusMessageIter *dict, GSupplicantSSID *ssid)
 +{
 +      if (ssid->security != G_SUPPLICANT_SECURITY_SAE
 +                      && ssid->security != G_SUPPLICANT_SECURITY_OWE
 +                      && ssid->security != G_SUPPLICANT_SECURITY_DPP)
 +              return;
 +
 +      supplicant_dbus_dict_append_basic(dict, "ieee80211w", DBUS_TYPE_UINT32,
 +                                        &ssid->ieee80211w);
 +}
 +
 +static void add_network_security_connector(DBusMessageIter *dict, GSupplicantSSID *ssid)
 +{
 +      if (ssid->connector && strlen(ssid->connector) > 0) {
 +              const char *key = "dpp_connector";
 +
 +              supplicant_dbus_dict_append_basic(dict,
 +                              key, DBUS_TYPE_STRING,
 +                              &ssid->connector);
 +      }
 +}
 +
 +static size_t convert_hexstr_to_bin(const char *hex_str, unsigned char **bin)
 +{
 +      unsigned char *bin_res = NULL;
 +      unsigned int i, j, hex;
 +      size_t hex_str_len;
 +
 +      if (!hex_str || strlen(hex_str) == 0)
 +              return 0;
 +
 +      hex_str_len = strlen(hex_str);
 +      bin_res = g_try_malloc0(hex_str_len / 2);
 +      if (!bin_res)
 +              return 0;
 +
 +      j = 0;
 +      for (i = 0; i < hex_str_len; i+=2) {
 +              sscanf(hex_str + i, "%02x", &hex);
 +              bin_res[j++] = hex;
 +      }
 +
 +      *bin = bin_res;
 +      return hex_str_len / 2;
 +}
 +
 +static void add_network_security_c_sign_key(DBusMessageIter *dict, GSupplicantSSID *ssid)
 +{
 +      if (ssid->c_sign_key && strlen(ssid->c_sign_key) > 0) {
 +              const char *key = "dpp_csign";
 +              unsigned char *bin_csign = NULL;
 +              size_t bin_csign_len = convert_hexstr_to_bin(ssid->c_sign_key, &bin_csign);
 +              if  (bin_csign_len != 0)
 +                      supplicant_dbus_dict_append_fixed_array(dict,
 +                                      key, DBUS_TYPE_BYTE,
 +                                      &bin_csign, bin_csign_len);
 +              g_free(bin_csign);
 +      }
 +}
 +
 +static void add_network_security_net_access_key(DBusMessageIter *dict, GSupplicantSSID *ssid)
 +{
 +      if (ssid->net_access_key && strlen(ssid->net_access_key) > 0) {
 +              const char *key = "dpp_netaccesskey";
 +              unsigned char *bin_netaccesskey = NULL;
 +              size_t bin_netaccesskey_len = convert_hexstr_to_bin(ssid->net_access_key, &bin_netaccesskey);
 +              if  (bin_netaccesskey_len != 0)
 +                      supplicant_dbus_dict_append_fixed_array(dict,
 +                                      key, DBUS_TYPE_BYTE,
 +                                      &bin_netaccesskey, bin_netaccesskey_len);
 +              g_free(bin_netaccesskey);
 +      }
 +}
 +
 +#endif
 +
  static void add_network_security(DBusMessageIter *dict, GSupplicantSSID *ssid)
  {
        char *key_mgmt;
                add_network_security_ciphers(dict, ssid);
                add_network_security_proto(dict, ssid);
                break;
 +#if defined TIZEN_EXT
 +      case G_SUPPLICANT_SECURITY_FT_PSK:
 +              key_mgmt = "FT-PSK";
 +              add_network_security_psk(dict, ssid);
 +              add_network_security_ciphers(dict, ssid);
 +              add_network_security_proto(dict, ssid);
 +              break;
 +      case G_SUPPLICANT_SECURITY_FT_IEEE8021X:
 +              key_mgmt = "FT-EAP";
 +              add_network_security_eap(dict, ssid);
 +              add_network_security_ciphers(dict, ssid);
 +              add_network_security_proto(dict, ssid);
 +              break;
 +      case G_SUPPLICANT_SECURITY_SAE:
 +              if (ssid->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_PSK)
 +                      key_mgmt = "SAE WPA-PSK"; // WFA (WPA3 & WPA2 Mixed -> WPA2 only)
 +              else
 +                      key_mgmt = "SAE";
 +              add_network_security_psk(dict, ssid);
 +              break;
 +      case G_SUPPLICANT_SECURITY_OWE:
 +              key_mgmt = "OWE";
 +              add_network_security_ciphers(dict, ssid);
 +              add_network_security_proto(dict, ssid);
 +              break;
 +      case G_SUPPLICANT_SECURITY_DPP:
 +              key_mgmt = "DPP";
 +              add_network_security_connector(dict, ssid);
 +              add_network_security_c_sign_key(dict, ssid);
 +              add_network_security_net_access_key(dict, ssid);
 +              break;
 +#endif
        }
  
        supplicant_dbus_dict_append_basic(dict, "key_mgmt",
@@@ -7328,11 -4939,6 +7328,11 @@@ static void add_network_mode(DBusMessag
        case G_SUPPLICANT_MODE_MASTER:
                mode = 2;
                break;
 +#if defined TIZEN_EXT_WIFI_MESH
 +      case G_SUPPLICANT_MODE_MESH:
 +              mode = 5;
 +              break;
 +#endif
        }
  
        supplicant_dbus_dict_append_basic(dict, "mode",
@@@ -7344,9 -4950,6 +7344,9 @@@ static void interface_add_network_param
        DBusMessageIter dict;
        struct interface_connect_data *data = user_data;
        GSupplicantSSID *ssid = data->ssid;
 +#if defined TIZEN_EXT
 +      GSupplicantInterface *interface = data->interface;
 +#endif
  
        supplicant_dbus_dict_open(iter, &dict);
  
  
        add_network_mode(&dict, ssid);
  
 -      add_network_security(&dict, ssid);
 +      add_network_security(&dict, ssid);
 +
 +#if defined TIZEN_EXT
 +      add_network_ieee80211w(&dict, ssid);
 +#endif
 +
 +      supplicant_dbus_dict_append_fixed_array(&dict, "ssid",
 +                                      DBUS_TYPE_BYTE, &ssid->ssid,
 +                                              ssid->ssid_len);
 +
 +#if defined TIZEN_EXT
 +      bool owe_transition_mode = FALSE;
 +      if ((ssid->security == G_SUPPLICANT_SECURITY_OWE) && !(ssid->keymgmt & G_SUPPLICANT_KEYMGMT_OWE))
 +              owe_transition_mode = TRUE;
 +
 +      if (ssid->bssid && !owe_transition_mode) {
 +              char *bssid = NULL;
 +              bssid = g_try_malloc0(18);
 +              if (bssid == NULL) {
 +                      SUPPLICANT_DBG("memory allocation error");
 +                      supplicant_dbus_dict_close(iter, &dict);
 +                      return;
 +              }
 +
 +              if (ssid->bssid_for_connect_len) {
 +                      snprintf(bssid, 18, MACSTR, MAC2STR(ssid->bssid_for_connect));
 +                      memcpy(interface->add_network_bssid, ssid->bssid_for_connect, WIFI_BSSID_LEN_MAX);
 +              } else {
 +                      snprintf(bssid, 18, MACSTR, MAC2STR(ssid->bssid));
 +                      memcpy(interface->add_network_bssid, ssid->bssid, WIFI_BSSID_LEN_MAX);
 +              }
 +
 +              SUPPLICANT_DBG("bssid [" MACSTR "]", MAC2STR(interface->add_network_bssid));
 +
 +              supplicant_dbus_dict_append_basic(&dict, "bssid",
 +                                      DBUS_TYPE_STRING, &bssid);
 +              g_free(bssid);
 +      }
 +#endif
 +
 +      supplicant_dbus_dict_close(iter, &dict);
 +}
 +
 +static void interface_wps_start_result(const char *error,
 +                              DBusMessageIter *iter, void *user_data)
 +{
 +      struct interface_connect_data *data = user_data;
 +      int err;
 +
 +      SUPPLICANT_DBG("");
 +
 +      err = 0;
 +      if (error) {
 +              SUPPLICANT_DBG("error: %s", error);
 +              err = parse_supplicant_error(iter);
 +      }
 +
 +      if(data->callback)
 +              data->callback(err, data->interface, data->user_data);
 +
 +      g_free(data->path);
 +      g_free(data->ssid);
 +      dbus_free(data);
 +}
 +
 +static void interface_add_wps_params(DBusMessageIter *iter, void *user_data)
 +{
 +      struct interface_connect_data *data = user_data;
 +      GSupplicantSSID *ssid = data->ssid;
 +      const char *role = "enrollee", *type;
 +      DBusMessageIter dict;
 +
 +      SUPPLICANT_DBG("");
 +
 +      supplicant_dbus_dict_open(iter, &dict);
 +
 +      supplicant_dbus_dict_append_basic(&dict, "Role",
 +                                              DBUS_TYPE_STRING, &role);
 +
 +      type = "pbc";
 +      if (ssid->pin_wps) {
 +              type = "pin";
 +              supplicant_dbus_dict_append_basic(&dict, "Pin",
 +                                      DBUS_TYPE_STRING, &ssid->pin_wps);
 +      }
 +
 +      supplicant_dbus_dict_append_basic(&dict, "Type",
 +                                      DBUS_TYPE_STRING, &type);
 +
 +#if defined TIZEN_EXT
 +      if (ssid->bssid)
 +              supplicant_dbus_dict_append_fixed_array(&dict, "Bssid",
 +                                              DBUS_TYPE_BYTE, &ssid->bssid, 6);
 +#endif
 +
 +      supplicant_dbus_dict_close(iter, &dict);
 +}
 +
 +static void wps_start(const char *error, DBusMessageIter *iter, void *user_data)
 +{
 +      struct interface_connect_data *data = user_data;
 +
 +      SUPPLICANT_DBG("");
 +
 +      if (error) {
 +              SUPPLICANT_DBG("error: %s", error);
 +              g_free(data->path);
 +              g_free(data->ssid);
 +              dbus_free(data);
 +              return;
 +      }
 +
 +#if defined TIZEN_EXT
 +      GSupplicantSSID *ssid = data->ssid;
 +      if (ssid->pin_wps != NULL) {
 +              if (!g_utf8_validate(ssid->pin_wps, 8, NULL)) {
 +                      SUPPLICANT_DBG("Invalid characters in WPS_PIN");
 +                      g_free(data->ssid);
 +                      dbus_free(data);
 +                      return;
 +              }
 +      }
 +#endif
 +      supplicant_dbus_method_call(data->interface->path,
 +                      SUPPLICANT_INTERFACE ".Interface.WPS", "Start",
 +                      interface_add_wps_params,
 +                      interface_wps_start_result, data, NULL);
 +}
 +
 +static void wps_process_credentials(DBusMessageIter *iter, void *user_data)
 +{
 +      dbus_bool_t credentials = TRUE;
 +
 +      SUPPLICANT_DBG("");
 +
 +      dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &credentials);
 +}
 +
 +
 +#if defined TIZEN_EXT
 +#define NETCONFIG_SERVICE "net.netconfig"
 +#define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
 +#define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
 +
 +struct dec_method_call_data {
 +      struct interface_connect_data *data;
 +      DBusPendingCall *pending_call;
 +};
 +
 +static struct dec_method_call_data decrypt_request_data;
 +
 +static void crypt_method_call_cancel(void)
 +{
 +      if (decrypt_request_data.pending_call) {
 +              dbus_pending_call_cancel(decrypt_request_data.pending_call);
 +              dbus_pending_call_unref(decrypt_request_data.pending_call);
 +              decrypt_request_data.pending_call = NULL;
 +      }
 +
 +      g_free(decrypt_request_data.data->path);
 +      g_free(decrypt_request_data.data->ssid);
 +      dbus_free(decrypt_request_data.data);
 +      decrypt_request_data.data = NULL;
 +}
 +
 +static void decryption_request_reply(DBusPendingCall *call,
 +                                              void *user_data)
 +{
 +      DBusMessage *reply;
 +      DBusError error;
 +      DBusMessageIter args;
 +      char *out_data;
 +      int ret;
 +      struct interface_connect_data *data = user_data;
 +
 +      SUPPLICANT_DBG("");
 +
 +      reply = dbus_pending_call_steal_reply(call);
 +
 +      dbus_error_init(&error);
 +      if (dbus_set_error_from_message(&error, reply)) {
 +              SUPPLICANT_DBG("decryption_request_reply() %s %s", error.name, error.message);
 +              dbus_error_free(&error);
 +              ret = -EINVAL;
 +              goto done;
 +      }
 +
 +      if (dbus_message_iter_init(reply, &args) == FALSE) {
 +              SUPPLICANT_DBG("dbus_message_iter_init() failed");
 +              ret = -EINVAL;
 +              goto done;
 +      }
 +
 +      dbus_message_iter_get_basic(&args, &out_data);
 +      data->ssid->passphrase = g_strdup((const gchar *)out_data);
 +
 +      ret = supplicant_dbus_method_call(data->interface->path,
 +              SUPPLICANT_INTERFACE ".Interface", "AddNetwork",
 +              interface_add_network_params,
 +              interface_add_network_result, data,
 +              data->interface);
 +
 +done:
 +      if (ret < 0) {
 +              SUPPLICANT_DBG("AddNetwork failed %d", ret);
 +              callback_assoc_failed(decrypt_request_data.data->user_data);
 +              g_free(data->path);
 +              g_free(data->ssid->ssid);
 +              g_free((char *)data->ssid->passphrase);
 +              g_free((char *)data->ssid->connector);
 +              g_free((char *)data->ssid->c_sign_key);
 +              g_free((char *)data->ssid->net_access_key);
 +              g_free(data->ssid);
 +              dbus_free(data);
 +      }
 +
 +      dbus_message_unref(reply);
 +      dbus_pending_call_unref(call);
 +
 +      decrypt_request_data.pending_call = NULL;
 +      decrypt_request_data.data = NULL;
 +}
 +
 +static int send_decryption_request(const char *passphrase,
 +                      struct interface_connect_data *data)
 +{
 +      DBusMessage *msg = NULL;
 +      DBusPendingCall *call;
 +
 +      SUPPLICANT_DBG("Decryption request");
 +
 +      if (!passphrase) {
 +              SUPPLICANT_DBG("Invalid parameter");
 +              return -EINVAL;
 +      }
 +
 +      if (!connection)
 +              return -EINVAL;
 +
 +      msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
 +                      NETCONFIG_WIFI_INTERFACE, "DecryptPassphrase");
 +      if (!msg)
 +              return -EINVAL;
 +
 +#if defined TIZEN_EXT
 +      if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
 +                                                      DBUS_TYPE_INVALID)) {
 +              SUPPLICANT_DBG("Could not fulfill decryption request");
 +              return -ENOMEM;
 +      }
 +#else
 +      dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
 +                                                      DBUS_TYPE_INVALID);
 +#endif
 +
 +      if (!dbus_connection_send_with_reply(connection, msg,
 +                              &call, DBUS_TIMEOUT_USE_DEFAULT)) {
 +              dbus_message_unref(msg);
 +              return -EIO;
 +      }
 +
 +      if (!call) {
 +              dbus_message_unref(msg);
 +              return -EIO;
 +      }
 +
 +      decrypt_request_data.pending_call = call;
 +      decrypt_request_data.data = data;
 +
 +      dbus_pending_call_set_notify(call, decryption_request_reply, data, NULL);
 +      dbus_message_unref(msg);
  
 -      supplicant_dbus_dict_append_fixed_array(&dict, "ssid",
 -                                      DBUS_TYPE_BYTE, &ssid->ssid,
 -                                              ssid->ssid_len);
 +      SUPPLICANT_DBG("Decryption request succeeded");
  
 -      supplicant_dbus_dict_close(iter, &dict);
 +      return 0;
  }
  
 -static void interface_wps_start_result(const char *error,
 -                              DBusMessageIter *iter, void *user_data)
 +static void decrypt_conf_obj_reply(DBusPendingCall *call,
 +                                              void *user_data)
  {
 +      DBusMessage *reply;
 +      DBusError error;
 +      DBusMessageIter iter, dict;
 +      char *out_data;
 +      int ret;
        struct interface_connect_data *data = user_data;
 -      int err;
  
 -      SUPPLICANT_DBG("");
 +      reply = dbus_pending_call_steal_reply(call);
  
 -      err = 0;
 -      if (error) {
 -              SUPPLICANT_DBG("error: %s", error);
 -              err = parse_supplicant_error(iter);
 +      dbus_error_init(&error);
 +      if (dbus_set_error_from_message(&error, reply)) {
 +              SUPPLICANT_DBG("decryption_conf_obj_reply() %s %s", error.name, error.message);
 +              dbus_error_free(&error);
 +              ret = -EINVAL;
 +              goto done;
        }
  
 -      if(data->callback)
 -              data->callback(err, data->interface, data->user_data);
 +      if (dbus_message_iter_init(reply, &iter) == FALSE) {
 +              SUPPLICANT_DBG("dbus_message_iter_init() failed");
 +              ret = -EINVAL;
 +              goto done;
 +      }
  
 -      g_free(data->path);
 -      g_free(data->ssid);
 -      dbus_free(data);
 -}
 +      dbus_message_iter_recurse(&iter, &dict);
 +
 +      while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
 +              DBusMessageIter entry, value;
 +              const char *key;
 +
 +              dbus_message_iter_recurse(&dict, &entry);
 +              dbus_message_iter_get_basic(&entry, &key);
 +              dbus_message_iter_next(&entry);
 +              dbus_message_iter_recurse(&entry, &value);
 +              if (dbus_message_iter_get_arg_type(&value) == DBUS_TYPE_STRING) {
 +                      if (g_strcmp0(key, "connector") == 0) {
 +                              dbus_message_iter_get_basic(&value, &out_data);
 +                              data->ssid->connector = g_strdup((const gchar *)out_data);
 +                              SUPPLICANT_DBG("connector %s", data->ssid->connector);
 +                      } else if (g_strcmp0(key, "c_sign_key") == 0) {
 +                              dbus_message_iter_get_basic(&value, &out_data);
 +                              data->ssid->c_sign_key = g_strdup((const gchar *)out_data);
 +                              SUPPLICANT_DBG("c_sign_key %s", data->ssid->c_sign_key);
 +                      } else if (g_strcmp0(key, "net_access_key") == 0) {
 +                              dbus_message_iter_get_basic(&value, &out_data);
 +                              data->ssid->net_access_key = g_strdup((const gchar *)out_data);
 +                              SUPPLICANT_DBG("net_access_key %s", data->ssid->net_access_key);
 +                      }
 +              }
 +              dbus_message_iter_next(&dict);
 +      }
  
 -static void interface_add_wps_params(DBusMessageIter *iter, void *user_data)
 -{
 -      struct interface_connect_data *data = user_data;
 -      GSupplicantSSID *ssid = data->ssid;
 -      const char *role = "enrollee", *type;
 -      DBusMessageIter dict;
 +      ret = supplicant_dbus_method_call(data->interface->path,
 +              SUPPLICANT_INTERFACE ".Interface", "AddNetwork",
 +              interface_add_network_params,
 +              interface_add_network_result, data,
 +              data->interface);
  
 -      SUPPLICANT_DBG("");
 +done:
 +      if (ret < 0) {
 +              SUPPLICANT_DBG("AddNetwork failed %d", ret);
 +              callback_assoc_failed(decrypt_request_data.data->user_data);
 +              g_free(data->path);
 +              g_free(data->ssid->ssid);
 +              g_free((char *)data->ssid->connector);
 +              g_free((char *)data->ssid->c_sign_key);
 +              g_free((char *)data->ssid->net_access_key);
 +              g_free(data->ssid);
 +              dbus_free(data);
 +      }
  
 -      supplicant_dbus_dict_open(iter, &dict);
 +      dbus_message_unref(reply);
 +      dbus_pending_call_unref(call);
  
 -      supplicant_dbus_dict_append_basic(&dict, "Role",
 -                                              DBUS_TYPE_STRING, &role);
 +      decrypt_request_data.pending_call = NULL;
 +      decrypt_request_data.data = NULL;
 +}
  
 -      type = "pbc";
 -      if (ssid->pin_wps) {
 -              type = "pin";
 -              supplicant_dbus_dict_append_basic(&dict, "Pin",
 -                                      DBUS_TYPE_STRING, &ssid->pin_wps);
 +static int send_decryption_conf_obj_request(GSupplicantSSID *ssid,
 +                      struct interface_connect_data *data)
 +{
 +      DBusMessage *msg = NULL;
 +      DBusPendingCall *call;
 +
 +      SUPPLICANT_DBG("Decryption configuration object request");
 +
 +      if (!ssid) {
 +              SUPPLICANT_DBG("Invalid parameter");
 +              return -EINVAL;
        }
  
 -      supplicant_dbus_dict_append_basic(&dict, "Type",
 -                                      DBUS_TYPE_STRING, &type);
 +      if (!connection)
 +              return -EINVAL;
  
 -      supplicant_dbus_dict_close(iter, &dict);
 -}
 +      msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
 +                      NETCONFIG_WIFI_INTERFACE, "DecryptConfObj");
 +      if (!msg)
 +              return -EINVAL;
  
 -static void wps_start(const char *error, DBusMessageIter *iter, void *user_data)
 -{
 -      struct interface_connect_data *data = user_data;
 +      dbus_message_append_args(msg, DBUS_TYPE_STRING, &ssid->connector,
 +                                                      DBUS_TYPE_INVALID);
 +      dbus_message_append_args(msg, DBUS_TYPE_STRING, &ssid->c_sign_key,
 +                                                      DBUS_TYPE_INVALID);
 +      dbus_message_append_args(msg, DBUS_TYPE_STRING, &ssid->net_access_key,
 +                                                      DBUS_TYPE_INVALID);
  
 -      SUPPLICANT_DBG("");
 +      if (!dbus_connection_send_with_reply(connection, msg,
 +                              &call, DBUS_TIMEOUT_USE_DEFAULT)) {
 +              dbus_message_unref(msg);
 +              return -EIO;
 +      }
  
 -      if (error) {
 -              SUPPLICANT_DBG("error: %s", error);
 -              g_free(data->path);
 -              g_free(data->ssid);
 -              dbus_free(data);
 -              return;
 +      if (!call) {
 +              dbus_message_unref(msg);
 +              return -EIO;
        }
  
 -      supplicant_dbus_method_call(data->interface->path,
 -                      SUPPLICANT_INTERFACE ".Interface.WPS", "Start",
 -                      interface_add_wps_params,
 -                      interface_wps_start_result, data, NULL);
 -}
 +      decrypt_request_data.pending_call = call;
 +      decrypt_request_data.data = data;
  
 -static void wps_process_credentials(DBusMessageIter *iter, void *user_data)
 -{
 -      dbus_bool_t credentials = TRUE;
 +      dbus_pending_call_set_notify(call, decrypt_conf_obj_reply, data, NULL);
 +      dbus_message_unref(msg);
  
 -      SUPPLICANT_DBG("");
 +      SUPPLICANT_DBG("Decrypt Conf Obj request succeeded");
  
 -      dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &credentials);
 +      return 0;
  }
  
 +static bool is_valid_config_object(GSupplicantSSID *ssid)
 +{
 +      return ((ssid->connector &&
 +                      g_strcmp0(ssid->connector, "") != 0) &&
 +                      (ssid->c_sign_key &&
 +                      g_strcmp0(ssid->c_sign_key, "") != 0) &&
 +                      (ssid->net_access_key &&
 +                      g_strcmp0(ssid->net_access_key, "") != 0));
 +}
 +#endif
  
  int g_supplicant_interface_connect(GSupplicantInterface *interface,
                                GSupplicantSSID *ssid,
                        intf_data->network_remove_in_progress = TRUE;
                        network_remove(intf_data);
                } else {
 +#if defined TIZEN_EXT
 +                      if (ssid->passphrase &&
 +                          g_strcmp0(ssid->passphrase, "") != 0 &&
 +#if defined TIZEN_EXT_WIFI_MESH
 +                          ssid->mode != G_SUPPLICANT_MODE_MESH &&
 +#endif
 +                          !ssid->eap) {
 +                              ret = send_decryption_request(ssid->passphrase, data);
 +                              if (ret < 0)
 +                                      SUPPLICANT_DBG("Decryption request failed %d", ret);
 +                      } else if (is_valid_config_object(ssid)) {
 +                              ret = send_decryption_conf_obj_request(ssid, data);
 +                              if (ret < 0)
 +                                      SUPPLICANT_DBG("Decryption Conf Obj request failed %d", ret);
 +
 +                      } else
 +#endif
                        ret = supplicant_dbus_method_call(interface->path,
                                        SUPPLICANT_INTERFACE ".Interface", "AddNetwork",
                                        interface_add_network_params,
                                        interface_add_network_result, data,
                                        interface);
                }
 -        }
 +      }
  
        if (ret < 0) {
                g_free(data->path);
@@@ -7934,27 -5190,6 +7934,27 @@@ static void network_remove_result(cons
                connect_data->ssid = data->ssid;
                connect_data->user_data = data->user_data;
  
 +#if defined TIZEN_EXT
 +              int ret;
 +              if (data->ssid->passphrase && g_strcmp0(data->ssid->passphrase, "") != 0
 +                      && !data->ssid->eap) {
 +                      ret = send_decryption_request(data->ssid->passphrase, connect_data);
 +                      if (ret < 0) {
 +                              SUPPLICANT_DBG("Decryption request failed %d", ret);
 +                              g_free(connect_data->ssid);
 +                              g_free(connect_data->path);
 +                              dbus_free(connect_data);
 +                      }
 +              } else if (is_valid_config_object(data->ssid)) {
 +                      ret = send_decryption_conf_obj_request(data->ssid, connect_data);
 +                      if (ret < 0) {
 +                              SUPPLICANT_DBG("Decryption Conf Obj request failed %d", ret);
 +                              g_free(connect_data->ssid);
 +                              g_free(connect_data->path);
 +                              dbus_free(connect_data);
 +                      }
 +              } else
 +#endif
                supplicant_dbus_method_call(data->interface->path,
                        SUPPLICANT_INTERFACE ".Interface", "AddNetwork",
                        interface_add_network_params,
@@@ -7984,16 -5219,6 +7984,16 @@@ static int network_remove(struct interf
  
        SUPPLICANT_DBG("");
  
 +#if defined TIZEN_EXT
 +      GSupplicantInterface *intf = NULL;
 +      /*
 +       * Check if 'interface' is valid
 +       */
 +      intf = g_hash_table_lookup(interface_table, interface->path);
 +      if (intf == NULL)
 +              return -EINVAL;
 +#endif
 +
        return supplicant_dbus_method_call(interface->path,
                        SUPPLICANT_INTERFACE ".Interface", "RemoveNetwork",
                        network_remove_params, network_remove_result, data,
@@@ -8060,17 -5285,7 +8060,17 @@@ int g_supplicant_interface_disconnect(G
  
        if (!system_available)
                return -EFAULT;
 +#if defined TIZEN_EXT
 +      if (decrypt_request_data.pending_call &&
 +                      decrypt_request_data.data &&
 +                      decrypt_request_data.data->user_data == user_data) {
  
 +              callback_assoc_failed(decrypt_request_data.data->user_data);
 +              crypt_method_call_cancel();
 +
 +              return 0;
 +      }
 +#endif
        data = dbus_malloc0(sizeof(*data));
        if (!data)
                return -ENOMEM;
@@@ -8562,18 -5777,12 +8562,18 @@@ static const char *g_supplicant_rule4 
                        "interface=" SUPPLICANT_INTERFACE ".BSS";
  static const char *g_supplicant_rule5 = "type=signal,"
                        "interface=" SUPPLICANT_INTERFACE ".Network";
 +#if !defined TIZEN_EXT
  static const char *g_supplicant_rule6 = "type=signal,"
                "interface=" SUPPLICANT_INTERFACE ".Interface.P2PDevice";
  static const char *g_supplicant_rule7 = "type=signal,"
                "interface=" SUPPLICANT_INTERFACE ".Peer";
  static const char *g_supplicant_rule8 = "type=signal,"
                "interface=" SUPPLICANT_INTERFACE ".Group";
 +#endif
 +#if defined TIZEN_EXT_WIFI_MESH
 +static const char *g_supplicant_rule9 = "type=signal,"
 +              "interface=" SUPPLICANT_INTERFACE ".Interface.Mesh";
 +#endif
  
  static void invoke_introspect_method(void)
  {
        dbus_message_unref(message);
  }
  
 +#if defined TIZEN_EXT && defined TIZEN_EXT_INS
 +void g_supplicant_set_ins_settings(GSupplicantINSPreferredFreq preferred_freq_bssid,
 +              bool last_connected_bssid, bool assoc_reject, bool signal_bssid,
 +              unsigned int preferred_freq_bssid_score, unsigned int last_connected_bssid_score,
 +              unsigned int assoc_reject_score, int signal_level3_5ghz, int signal_level3_24ghz)
 +{
 +      ins_settings.preferred_freq_bssid = preferred_freq_bssid;
 +      ins_settings.last_connected_bssid = last_connected_bssid;
 +      ins_settings.assoc_reject = assoc_reject;
 +      ins_settings.signal_bssid = signal_bssid;
 +      ins_settings.preferred_freq_bssid_score = preferred_freq_bssid_score;
 +      ins_settings.last_connected_bssid_score = last_connected_bssid_score;
 +      ins_settings.assoc_reject_score = assoc_reject_score;
 +      ins_settings.signal_level3_5ghz = signal_level3_5ghz;
 +      ins_settings.signal_level3_24ghz = signal_level3_24ghz;
 +
 +      SUPPLICANT_DBG("preferred_freq_bssid [%s]", preferred_freq_bssid ? "true" : "false");
 +      SUPPLICANT_DBG("preferred_freq_bssid_score [%d]", preferred_freq_bssid_score);
 +      SUPPLICANT_DBG("last_connected_bssid [%s]", last_connected_bssid ? "true" : "false");
 +      SUPPLICANT_DBG("last_connected_bssid_score [%d]", last_connected_bssid_score);
 +      SUPPLICANT_DBG("assoc_reject [%s]", assoc_reject ? "true" : "false");
 +      SUPPLICANT_DBG("assoc_reject_score [%d]", assoc_reject_score);
 +      SUPPLICANT_DBG("signal_bssid [%s]", signal_bssid ? "true" : "false");
 +      SUPPLICANT_DBG("signal_level3_5ghz [%d]", signal_level3_5ghz);
 +      SUPPLICANT_DBG("signal_level3_24ghz [%d]", signal_level3_24ghz);
 +}
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
 +
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +void g_supplicant_register_eap_callback(g_supplicant_eap_callback cb)
 +{
 +      SUPPLICANT_DBG("g_supplicant_register_eap_callback %p", cb);
 +
 +      if (!callbacks_pointer) {
 +              SUPPLICANT_DBG("callbacks_pointer is NULL");
 +              return;
 +      }
 +
 +      callbacks_pointer->eap = cb;
 +}
 +
 +void g_supplicant_unregister_eap_callback(void)
 +{
 +      SUPPLICANT_DBG("g_supplicant_unregister_eap_callback");
 +
 +      if (!callbacks_pointer) {
 +              SUPPLICANT_DBG("callbacks_pointer is NULL");
 +              return;
 +      }
 +
 +      callbacks_pointer->eap = NULL;
 +}
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +int g_supplicant_register(GSupplicantCallbacks *callbacks)
 +#else /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
  int g_supplicant_register(const GSupplicantCallbacks *callbacks)
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
  {
        connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
        if (!connection)
                connection = NULL;
                return -EIO;
        }
 -
 +#if defined TIZEN_EXT
 +      simplified_log = connman_setting_get_bool("SimplifiedLog");
 +#endif
        callbacks_pointer = callbacks;
        eap_methods = 0;
  
        dbus_bus_add_match(connection, g_supplicant_rule3, NULL);
        dbus_bus_add_match(connection, g_supplicant_rule4, NULL);
        dbus_bus_add_match(connection, g_supplicant_rule5, NULL);
 +#if defined TIZEN_EXT
 +      dbus_bus_add_match(connection,
 +                      "type=signal,interface=org.tizen.system.deviced.PowerOff,"
 +                      "member=ChangeState", NULL);
 +#endif
 +#if !defined TIZEN_EXT
        dbus_bus_add_match(connection, g_supplicant_rule6, NULL);
        dbus_bus_add_match(connection, g_supplicant_rule7, NULL);
        dbus_bus_add_match(connection, g_supplicant_rule8, NULL);
 +#endif
 +#if defined TIZEN_EXT_WIFI_MESH
 +      dbus_bus_add_match(connection, g_supplicant_rule9, NULL);
 +#endif
        dbus_connection_flush(connection);
  
        if (dbus_bus_name_has_owner(connection,
        } else
                invoke_introspect_method();
  
 +      SUPPLICANT_DBG("supplicant dbus setup completed");
        return 0;
  }
  
@@@ -8745,14 -5883,9 +8745,14 @@@ void g_supplicant_unregister(const GSup
        SUPPLICANT_DBG("");
  
        if (connection) {
 +#if defined TIZEN_EXT_WIFI_MESH
 +              dbus_bus_remove_match(connection, g_supplicant_rule9, NULL);
 +#endif
 +#if !defined TIZEN_EXT
                dbus_bus_remove_match(connection, g_supplicant_rule8, NULL);
                dbus_bus_remove_match(connection, g_supplicant_rule7, NULL);
                dbus_bus_remove_match(connection, g_supplicant_rule6, NULL);
 +#endif
                dbus_bus_remove_match(connection, g_supplicant_rule5, NULL);
                dbus_bus_remove_match(connection, g_supplicant_rule4, NULL);
                dbus_bus_remove_match(connection, g_supplicant_rule3, NULL);
        callbacks_pointer = NULL;
        eap_methods = 0;
  }
 +
 +#ifdef TIZEN_EXT
 +struct supplicant_mac_policy {
 +      GSupplicantMacPolicyCallback callback;
 +      dbus_uint32_t policy;
 +      const void *user_data;
 +};
 +
 +static void mac_policy_result(const char *error,
 +                              DBusMessageIter *iter, void *user_data)
 +{
 +      struct supplicant_mac_policy *data = user_data;
 +      int result = 0;
 +
 +      if (!user_data)
 +              return;
 +
 +      if (error) {
 +              SUPPLICANT_DBG("Mac policy setting failure %s", error);
 +              result = -EINVAL;
 +      }
 +
 +      if (data->callback)
 +              data->callback(result, data->policy,
 +                                      (void *) data->user_data);
 +
 +      dbus_free(data);
 +}
 +
 +static void mac_policy_params(DBusMessageIter *iter, void *user_data)
 +{
 +      struct supplicant_mac_policy *data = user_data;
 +
 +      dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &(data->policy));
 +}
 +
 +int g_supplicant_interface_set_mac_policy(GSupplicantInterface *interface,
 +                                      GSupplicantMacPolicyCallback callback,
 +                                                      unsigned int policy,
 +                                                      void *user_data)
 +{
 +      struct supplicant_mac_policy *data = NULL;
 +      int ret;
 +
 +      if (!system_available)
 +              return -EFAULT;
 +
 +      if (!interface)
 +              return -EINVAL;
 +
 +      data = dbus_malloc0(sizeof(*data));
 +      if (!data)
 +              return -ENOMEM;
 +
 +      data->callback = callback;
 +      data->policy = policy;
 +      data->user_data = user_data;
 +
 +      ret =  supplicant_dbus_property_set(interface->path,
 +                              SUPPLICANT_INTERFACE ".Interface",
 +                              "MacAddr", DBUS_TYPE_INT32_AS_STRING,
 +                              mac_policy_params, mac_policy_result, data, NULL);
 +      if (ret < 0) {
 +              SUPPLICANT_DBG("Unable to set MacAddr configuration");
 +              dbus_free(data);
 +      }
 +
 +      return ret;
 +}
 +
 +int g_supplicant_interface_set_preassoc_mac_policy(GSupplicantInterface *interface,
 +                                      GSupplicantMacPolicyCallback callback,
 +                                                      unsigned int policy,
 +                                                      void *user_data)
 +{
 +      struct supplicant_mac_policy *data;
 +      int ret;
 +
 +      if (!system_available)
 +              return -EFAULT;
 +
 +      if (!interface)
 +              return -EINVAL;
 +
 +      data = dbus_malloc0(sizeof(*data));
 +      if (!data)
 +              return -ENOMEM;
 +
 +      data->callback = callback;
 +      data->policy = policy;
 +      data->user_data = user_data;
 +
 +      ret =  supplicant_dbus_property_set(interface->path,
 +                              SUPPLICANT_INTERFACE ".Interface",
 +                              "PreassocMacAddr", DBUS_TYPE_INT32_AS_STRING,
 +                              mac_policy_params, mac_policy_result, data, NULL);
 +      if (ret < 0) {
 +              SUPPLICANT_DBG("Unable to set PreassocMacAddr configuration");
 +              dbus_free(data);
 +      }
 +
 +      return ret;
 +}
 +
 +struct supplicant_random_mac_lifetime {
 +      GSupplicantRandomMaclifetimeCallback callback;
 +      dbus_uint32_t lifetime;
 +      const void *user_data;
 +};
 +
 +static void random_mac_lifetime_result(const char *error,
 +                              DBusMessageIter *iter, void *user_data)
 +{
 +      struct supplicant_random_mac_lifetime *data = user_data;
 +      int result = 0;
 +
 +      if (!user_data)
 +              return;
 +
 +      if (error) {
 +              SUPPLICANT_DBG("Random Mac lifetime setting failure %s", error);
 +              result = -EINVAL;
 +      }
 +
 +      if (data->callback)
 +              data->callback(result, data->lifetime,
 +                                      (void *) data->user_data);
 +
 +      dbus_free(data);
 +}
 +
 +static void random_mac_lifetime_params(DBusMessageIter *iter, void *user_data)
 +{
 +      struct supplicant_random_mac_lifetime *data = user_data;
 +
 +      dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &(data->lifetime));
 +}
 +
 +int g_supplicant_interface_set_random_mac_lifetime(GSupplicantInterface *interface,
 +                                      GSupplicantRandomMaclifetimeCallback callback,
 +                                                      unsigned int lifetime,
 +                                                      void *user_data)
 +{
 +      struct supplicant_random_mac_lifetime *data;
 +      int ret;
 +
 +      if (!system_available)
 +              return -EFAULT;
 +
 +      if (!interface)
 +              return -EINVAL;
 +
 +      data = dbus_malloc0(sizeof(*data));
 +      if (!data)
 +              return -ENOMEM;
 +
 +      data->callback = callback;
 +      data->lifetime = lifetime;
 +      data->user_data = user_data;
 +
 +      ret =  supplicant_dbus_property_set(interface->path,
 +                              SUPPLICANT_INTERFACE ".Interface",
 +                              "RandAddrLifetime", DBUS_TYPE_UINT32_AS_STRING,
 +                              random_mac_lifetime_params, random_mac_lifetime_result,
 +                              data, NULL);
 +      if (ret < 0) {
 +              SUPPLICANT_DBG("Unable to set RandAddrLifetime configuration");
 +              dbus_free(data);
 +      }
 +
 +      return ret;
 +}
 +#endif
diff --combined include/inet.h
@@@ -40,10 -40,6 +40,10 @@@ int connman_inet_ifup(int index)
  int connman_inet_ifdown(int index);
  bool connman_inet_is_ifup(int index);
  
 +#if defined TIZEN_EXT
 +void connman_inet_update_device_ident(struct connman_device *device);
 +#endif
 +
  int connman_inet_set_address(int index, struct connman_ipaddress *ipaddress);
  int connman_inet_clear_address(int index, struct connman_ipaddress *ipaddress);
  int connman_inet_add_host_route(int index, const char *host, const char *gateway);
@@@ -59,7 -55,7 +59,7 @@@ bool connman_inet_compare_ipv6_subnet(i
  int connman_inet_set_ipv6_address(int index,
                struct connman_ipaddress *ipaddress);
  int connman_inet_clear_ipv6_address(int index,
-               const char *address, int prefix_len);
+                                       struct connman_ipaddress *ipaddress);
  int connman_inet_add_ipv6_network_route(int index, const char *host,
                                        const char *gateway, unsigned char prefix_len);
  int connman_inet_add_ipv6_host_route(int index, const char *host,
@@@ -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
diff --combined include/ipaddress.h
index 3655ca8,652db0f..652db0f
mode 100755,100644..100755
@@@ -22,6 -22,8 +22,8 @@@
  #ifndef __CONNMAN_IPADDRESS_H
  #define __CONNMAN_IPADDRESS_H
  
+ #include <stdbool.h>
  #ifdef __cplusplus
  extern "C" {
  #endif
@@@ -36,6 -38,8 +38,8 @@@ struct connman_ipaddress
  
  unsigned char connman_ipaddress_calc_netmask_len(const char *netmask);
  struct connman_ipaddress *connman_ipaddress_alloc(int family);
+ void connman_ipaddress_set_p2p(struct connman_ipaddress *ipaddress,
+                               bool value);
  void connman_ipaddress_free(struct connman_ipaddress *ipaddress);
  int connman_ipaddress_set_ipv4(struct connman_ipaddress *ipaddress,
                                const char *address, const char *netmask,
diff --combined include/network.h
index 9f5bb1f,8f9dd94..4d09dff
mode 100755,100644..100755
  extern "C" {
  #endif
  
 +#if defined TIZEN_EXT
 +#define WIFI_ENCYPTION_MODE_LEN_MAX 6
 +#define WIFI_BSSID_LEN_MAX 6
 +#define MAC_ADDRESS_LENGTH 18
 +#endif
 +
  /**
   * SECTION:network
   * @title: Network premitives
@@@ -63,55 -57,9 +63,55 @@@ enum connman_network_error 
        CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL  = 2,
        CONNMAN_NETWORK_ERROR_INVALID_KEY     = 3,
        CONNMAN_NETWORK_ERROR_CONNECT_FAIL    = 4,
 +#if defined TIZEN_EXT
 +      CONNMAN_NETWORK_ERROR_DHCP_FAIL       = 5,
 +      CONNMAN_NETWORK_ERROR_BLOCKED         = 6,
 +      CONNMAN_NETWORK_ERROR_AUTHENTICATE_FAIL = 7,
 +#else
        CONNMAN_NETWORK_ERROR_BLOCKED         = 5,
 +#endif
 +};
 +
 +#if defined TIZEN_EXT
 +struct connman_bssids {
 +      unsigned char bssid[WIFI_BSSID_LEN_MAX];
 +      uint16_t strength;
 +      uint16_t frequency;
 +      uint16_t assoc_reject_cnt;
 +      bool is_last_connected;
 +#if defined TIZEN_EXT_INS
 +      int score_last_connected_bssid;
 +      int score_assoc_reject;
 +      int score_frequency;
 +      int score_strength;
 +#endif
 +      int ins_score;
  };
  
 +/* Backward compatible
 + * modes of available network */
 +typedef enum {
 +      IEEE80211_UNKNOWN,
 +      IEEE80211_MODE_B,
 +      IEEE80211_MODE_BG,
 +      IEEE80211_MODE_BGN,
 +      IEEE80211_MODE_A,
 +      IEEE80211_MODE_AN,
 +      IEEE80211_MODE_ANAC,
 +} ieee80211_modes_e;
 +
 +/* connection mode of connected network
 + * based on current linkspeed */
 +typedef enum {
 +      CONNECTION_MODE_IEEE80211_UNKNOWN,
 +      CONNECTION_MODE_IEEE80211B,
 +      CONNECTION_MODE_IEEE80211G,
 +      CONNECTION_MODE_IEEE80211N,
 +      CONNECTION_MODE_IEEE80211A,
 +      CONNECTION_MODE_IEEE80211AC,
 +} connection_mode_e;
 +#endif
 +
  #define CONNMAN_NETWORK_PRIORITY_LOW      -100
  #define CONNMAN_NETWORK_PRIORITY_DEFAULT     0
  #define CONNMAN_NETWORK_PRIORITY_HIGH      100
@@@ -144,12 -92,6 +144,12 @@@ void connman_network_set_group(struct c
  const char *connman_network_get_group(struct connman_network *network);
  
  bool connman_network_get_connecting(struct connman_network *network);
 +#if defined TIZEN_EXT
 +void connman_network_set_connecting(struct connman_network *network);
 +#endif
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +bool connman_network_check_validity(struct connman_network *network);
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
  int connman_network_set_available(struct connman_network *network,
                                                bool available);
  bool connman_network_get_available(struct connman_network *network);
@@@ -179,83 -121,6 +179,83 @@@ int connman_network_set_nameservers(str
                                const char *nameservers);
  int connman_network_set_domain(struct connman_network *network,
                                     const char *domain);
 +#if defined TIZEN_EXT
 +/*
 + * Description: Network client requires additional wifi specific info
 + */
 +int connman_network_set_bssid(struct connman_network *network,
 +                              const unsigned char *bssid);
 +unsigned char *connman_network_get_bssid(struct connman_network *network);
 +
 +int connman_network_set_transition_mode_bssid(struct connman_network *network,
 +                              const unsigned char *transition_mode_bssid);
 +
 +unsigned char *connman_network_get_transition_mode_bssid(struct connman_network *network);
 +
 +bool connman_network_check_transition_mode(struct connman_network *network1, struct connman_network *network2);
 +
 +int connman_network_set_maxrate(struct connman_network *network,
 +                              unsigned int maxrate);
 +
 +int connman_network_set_maxspeed(struct connman_network *network,
 +                              int maxrate);
 +
 +unsigned int connman_network_get_maxrate(struct connman_network *network);
 +
 +int connman_network_get_maxspeed(struct connman_network *network);
 +
 +int connman_network_set_sec_list(struct connman_network *network,
 +                                      GSList *sec_list);
 +void *connman_network_get_sec_list(struct connman_network *network);
 +
 +int connman_network_set_enc_mode(struct connman_network *network,
 +                              const char *encryption_mode);
 +const char *connman_network_get_enc_mode(struct connman_network *network);
 +
 +int connman_network_set_rsn_mode(struct connman_network *network,
 +                              bool rsn_mode);
 +
 +int connman_network_set_proxy(struct connman_network *network,
 +                               const char *proxies);
 +
 +void connman_network_clear_associating(struct connman_network *network);
 +
 +int connman_network_set_keymgmt(struct connman_network *network,
 +                              unsigned int keymgmt);
 +unsigned int connman_network_get_keymgmt(struct connman_network *network);
 +int connman_network_set_disconnect_reason(struct connman_network *network,
 +                              int reason_code);
 +int connman_network_get_disconnect_reason(struct connman_network *network);
 +int connman_network_get_assoc_status_code(struct connman_network *network);
 +int connman_network_set_assoc_status_code(struct connman_network *network,
 +                              int assoc_status_code);
 +int connman_network_set_countrycode(struct connman_network *network, const
 +                                  unsigned char *country_code);
 +unsigned char *connman_network_get_countrycode(struct connman_network *network);
 +int connman_network_set_bssid_list(struct connman_network *network,
 +                                      GSList *bssids);
 +void *connman_network_get_bssid_list(struct connman_network *network);
 +#if defined TIZEN_EXT
 +int connman_network_set_last_connected_bssid(struct connman_network *network,
 +                              const unsigned char *bssid);
 +unsigned char *connman_network_get_last_connected_bssid(struct connman_network *network);
 +void connman_network_set_assoc_reject_table(struct connman_network *network,
 +              GHashTable *assoc_reject_table);
 +GHashTable *connman_network_get_assoc_reject_table(struct connman_network *network);
 +__time_t connman_network_get_roam_scan_time(struct connman_network *network);
 +void connman_network_set_roam_scan_time(struct connman_network *network,
 +                                              __time_t roam_scan_time);
 +int connman_network_get_snr(struct connman_network *network);
 +void connman_network_set_snr(struct connman_network *network, int snr);
 +#endif
 +int connman_network_set_phy_mode(struct connman_network *network,
 +                              ieee80211_modes_e mode);
 +ieee80211_modes_e connman_network_get_phy_mode(struct connman_network *network);
 +int connman_network_set_connection_mode(struct connman_network *network,
 +                              connection_mode_e mode);
 +connection_mode_e connman_network_get_connection_mode(struct connman_network *network);
 +#endif
 +
  int connman_network_set_name(struct connman_network *network,
                                                        const char *name);
  int connman_network_set_strength(struct connman_network *network,
@@@ -267,6 -132,8 +267,8 @@@ uint16_t connman_network_get_frequency(
  int connman_network_set_wifi_channel(struct connman_network *network,
                                        uint16_t channel);
  uint16_t connman_network_get_wifi_channel(struct connman_network *network);
+ int connman_network_set_autoconnect(struct connman_network *network,
+                               bool autoconnect);
  
  int connman_network_set_string(struct connman_network *network,
                                        const char *key, const char *value);
@@@ -280,10 -147,6 +282,10 @@@ int connman_network_set_blob(struct con
                        const char *key, const void *data, unsigned int size);
  const void *connman_network_get_blob(struct connman_network *network,
                                        const char *key, unsigned int *size);
 +#if defined TIZEN_EXT
 +void connman_network_set_vsie_list(struct connman_network *network, GSList *vsie_list);
 +void *connman_network_get_vsie_list(struct connman_network *network);
 +#endif
  
  struct connman_device *connman_network_get_device(struct connman_network *network);
  
@@@ -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);
diff --combined include/provider.h
index b585665,1f12099..1f12099
mode 100755,100644..100755
@@@ -113,6 -113,10 +113,10 @@@ int connman_provider_set_nameservers(st
                                        char * const *nameservers);
  void connman_provider_set_autoconnect(struct connman_provider *provider,
                                                                bool flag);
+ bool connman_provider_is_split_routing(struct connman_provider *provider);
+ int connman_provider_set_split_routing(struct connman_provider *provider,
+                                                       bool split_routing);
+ int connman_provider_get_family(struct connman_provider *provider);
  
  const char *connman_provider_get_driver_name(struct connman_provider *provider);
  const char *connman_provider_get_save_group(struct connman_provider *provider);
diff --combined include/service.h
index acd8852,8f6b36b..041949f
mode 100755,100644..100755
  
  #include <stdbool.h>
  
 +#if defined TIZEN_EXT
 +#include <glib.h>
 +#include <gdbus.h>
 +#endif
 +
  #ifdef __cplusplus
  extern "C" {
  #endif
@@@ -50,15 -45,8 +50,15 @@@ enum connman_service_type 
        CONNMAN_SERVICE_TYPE_VPN       = 7,
        CONNMAN_SERVICE_TYPE_GADGET    = 8,
        CONNMAN_SERVICE_TYPE_P2P       = 9,
 +#if defined TIZEN_EXT_WIFI_MESH
 +      CONNMAN_SERVICE_TYPE_MESH      = 10,
 +#endif
  };
 +#if defined TIZEN_EXT_WIFI_MESH
 +#define       MAX_CONNMAN_SERVICE_TYPES        11
 +#else
  #define       MAX_CONNMAN_SERVICE_TYPES        10
 +#endif
  
  
  enum connman_service_security {
        CONNMAN_SERVICE_SECURITY_8021X   = 4,
        CONNMAN_SERVICE_SECURITY_WPA     = 8,
        CONNMAN_SERVICE_SECURITY_RSN     = 9,
 +#if defined TIZEN_EXT
 +      CONNMAN_SERVICE_SECURITY_SAE     = 10,
 +      CONNMAN_SERVICE_SECURITY_OWE     = 11,
 +      CONNMAN_SERVICE_SECURITY_DPP     = 12,
 +#endif
 +#if defined TIZEN_EXT
 +      CONNMAN_SERVICE_SECURITY_MAX
 +#endif
  };
  
  enum connman_service_state {
@@@ -100,9 -80,6 +100,9 @@@ enum connman_service_error 
        CONNMAN_SERVICE_ERROR_AUTH_FAILED    = 6,
        CONNMAN_SERVICE_ERROR_INVALID_KEY    = 7,
        CONNMAN_SERVICE_ERROR_BLOCKED        = 8,
 +#if defined TIZEN_EXT
 +      CONNMAN_SERVICE_ERROR_ASSOC_FAILED   = 9,
 +#endif
  };
  
  enum connman_service_proxy_method {
@@@ -117,6 -94,7 +117,7 @@@ enum connman_service_connect_reason 
        CONNMAN_SERVICE_CONNECT_REASON_AUTO     = 1,
        CONNMAN_SERVICE_CONNECT_REASON_USER     = 2,
        CONNMAN_SERVICE_CONNECT_REASON_SESSION  = 3,
+       CONNMAN_SERVICE_CONNECT_REASON_NATIVE   = 4,
  };
  
  struct connman_service;
@@@ -172,53 -150,6 +173,53 @@@ void connman_service_create_ip4config(s
  void connman_service_create_ip6config(struct connman_service *service,
                                                                int index);
  
 +#if defined TIZEN_EXT
 +/*
 + * Description: TIZEN implements system global connection management.
 + *              It's only for PDP (cellular) bearer. Wi-Fi is managed by ConnMan automatically.
 + *              Reference count can help to manage open/close connection requests by each application.
 + */
 +
 +/*
 + * Increase reference count of user-initiated packet data network connection
 + */
 +void connman_service_user_pdn_connection_ref(struct connman_service *service);
 +
 +/*
 + * Decrease reference count of user initiated packet data network connection
 + * and return TRUE if counter is zero.
 + */
 +gboolean connman_service_user_pdn_connection_unref_and_test(
 +                                      struct connman_service *service);
 +
 +/*
 + * Test reference count of user initiated packet data network connection
 + * and return TRUE if counter is zero. No impact to reference count
 + */
 +gboolean connman_service_is_no_ref_user_pdn_connection(
 +                                      struct connman_service *service);
 +
 +struct connman_service *connman_service_get_default_connection(void);
 +struct connman_service *connman_service_get_connected_service(const char *ifname);
 +
 +/*
 + * Description: telephony plug-in requires manual PROXY setting
 + */
 +int connman_service_set_proxy(struct connman_service *service,
 +                                      const char *proxy, gboolean active);
 +
 +void connman_service_set_disconnection_requested(struct connman_service *service,
 +                                               bool disconnection_requested);
 +#endif
 +
 +#if defined TIZEN_EXT
 +void connman_service_set_internet_connection(struct connman_service *service,
 +                                                      bool internet_connection);
 +bool connman_service_get_internet_connection(struct connman_service *service);
 +DBusMessage *connman_service_create_dbus_service_reply(DBusMessage *msg,
 +                                                      struct connman_service *service);
 +#endif
 +
  #ifdef __cplusplus
  }
  #endif
diff --combined include/setting.h
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);
  
diff --combined packaging/connman.spec
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
diff --combined plugins/bluetooth.c
index 704d216,5336103..a8383e7
mode 100755,100644..100755
@@@ -192,14 -192,8 +192,14 @@@ static bool pan_connect(struct bluetoot
                return false;
        }
  
 +#if defined TIZEN_EXT
 +      if (pan->network) {
 +#endif
        connman_network_set_index(pan->network, index);
        connman_network_set_connected(pan->network, true);
 +#if defined TIZEN_EXT
 +      }
 +#endif
  
        return true;
  }
@@@ -268,9 -262,6 +268,9 @@@ static int bluetooth_pan_connect(struc
                        g_strdup(path), g_free))
                return -EIO;
  
 +#if defined TIZEN_EXT
 +      if (pan->network)
 +#endif
        connman_network_set_associating(pan->network, true);
  
        return -EINPROGRESS;
@@@ -295,9 -286,6 +295,9 @@@ static void pan_disconnect_cb(DBusMessa
  
        DBG("network %p", pan->network);
  
 +#if defined TIZEN_EXT
 +      if (pan->network)
 +#endif
        connman_network_set_connected(pan->network, false);
  }
  
@@@ -311,11 -299,6 +311,11 @@@ static int bluetooth_pan_disconnect(str
        if (!pan)
                return -EINVAL;
  
 +#if defined TIZEN_EXT
 +      if (connman_network_get_associating(network) == TRUE)
 +              connman_network_clear_associating(network);
 +#endif
 +
        path = g_dbus_proxy_get_path(pan->btnetwork_proxy);
  
        if (!g_dbus_proxy_method_call(pan->btnetwork_proxy, "Disconnect",
@@@ -541,9 -524,7 +541,9 @@@ static void device_enable_cb(const DBus
                goto out;
        }
  
 +#if !defined TIZEN_EXT
        enable_device(device, path);
 +#endif
  out:
        g_free(path);
  }
@@@ -610,9 -591,7 +610,9 @@@ static void device_disable_cb(const DBu
                goto out;
        }
  
 +#if !defined TIZEN_EXT
        disable_device(device, path);
 +#endif
  
  out:
        g_free(path);
@@@ -738,8 -717,6 +738,6 @@@ static bool tethering_create(const cha
        const char *method;
        bool result;
  
-       DBG("path %s bridge %s", path, bridge);
        if (!bridge) {
                g_free(tethering);
                return false;
                return false;
        }
  
+       DBG("path %s bridge %s", path, bridge);
        tethering->technology = technology;
        tethering->bridge = g_strdup(bridge);
        tethering->enable = enabled;
diff --combined plugins/dundee.c
index b5420ac,57571ec..57571ec
mode 100755,100644..100755
@@@ -488,7 -488,7 +488,7 @@@ static void extract_settings(DBusMessag
        if (index < 0)
                goto out;
  
-       info->address = connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4);
+       info->address = connman_ipaddress_alloc(AF_INET);
        if (!info->address)
                goto out;
  
diff --combined plugins/ethernet.c
  #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;
  
@@@ -65,9 -57,6 +64,9 @@@ struct ethernet_data 
        unsigned flags;
        unsigned int watch;
        struct connman_network *network;
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      GSupplicantInterface *interface;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
  };
  
  
@@@ -84,7 -73,7 +83,7 @@@ static int get_vlan_vid(const char *ifn
                return -errno;
  
        vifr.cmd = GET_VLAN_VID_CMD;
-       stpncpy(vifr.device1, ifname, sizeof(vifr.device1));
+       stpncpy(vifr.device1, ifname, sizeof(vifr.device1) - 1);
  
        if(ioctl(sk, SIOCSIFVLAN, &vifr) >= 0)
                vid = vifr.u.VID;
@@@ -110,14 -99,16 +109,16 @@@ static int get_dsa_port(const char *ifn
                return -errno;
  
        memset(&ifr, 0, sizeof(ifr));
-       stpncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+       stpncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
  
        /* check if it is a vlan and get physical interface name*/
        vifr.cmd = GET_VLAN_REALDEV_NAME_CMD;
-       stpncpy(vifr.device1, ifname, sizeof(vifr.device1));
+       stpncpy(vifr.device1, ifname, sizeof(vifr.device1) - 1);
  
-       if(ioctl(sk, SIOCSIFVLAN, &vifr) >= 0)
-               stpncpy(ifr.ifr_name, vifr.u.device2, sizeof(ifr.ifr_name));
+       if(ioctl(sk, SIOCSIFVLAN, &vifr) >= 0) {
+               stpncpy(ifr.ifr_name, vifr.u.device2, sizeof(ifr.ifr_name) - 1);
+               ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
+       }
  
        /* get driver info */
        drvinfocmd.cmd =  ETHTOOL_GDRVINFO;
@@@ -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);
@@@ -402,8 -159,6 +402,8 @@@ static int eth_network_disconnect(struc
        return 0;
  }
  
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
  static struct connman_network_driver eth_network_driver = {
        .name           = "cable",
        .type           = CONNMAN_NETWORK_TYPE_ETHERNET,
@@@ -501,10 -256,6 +501,10 @@@ static void ethernet_newlink(unsigned f
                } else {
                        DBG("carrier off");
                        remove_network(device, ethernet);
 +#if defined TIZEN_EXT_WIFI_MESH
 +                      /* Remove ethernet from mesh bridge */
 +                      __connman_mesh_remove_ethernet_from_bridge();
 +#endif
                }
        }
  
@@@ -525,9 -276,6 +525,9 @@@ static int eth_dev_probe(struct connman
  
        ethernet->index = connman_device_get_index(device);
        ethernet->flags = 0;
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      ethernet->interface = NULL;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
  
        ethernet->watch = connman_rtnl_add_newlink_watch(ethernet->index,
                                                ethernet_newlink, device);
@@@ -543,16 -291,6 +543,16 @@@ static void eth_dev_remove(struct connm
  
        connman_device_set_data(device, NULL);
  
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      if (!ethernet)
 +             return;
 +
 +      if (ethernet->interface) {
 +              g_supplicant_interface_remove(ethernet->interface, NULL, NULL);
 +              ethernet->interface = NULL;
 +      }
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
        connman_rtnl_remove_watch(ethernet->watch);
  
        remove_network(device, ethernet);
@@@ -696,54 -434,6 +696,54 @@@ static struct connman_technology_drive
        .set_tethering          = eth_tech_set_tethering,
  };
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +static int eth_mesh_add_to_bridge(const char *bridge)
 +{
 +      GList *list;
 +      struct ethernet_data *ethernet;
 +
 +      DBG("Add ethernet to bridge %s", bridge);
 +
 +      for (list = eth_interface_list; list; list = list->next) {
 +              int index = GPOINTER_TO_INT(list->data);
 +              struct connman_device *device =
 +                      connman_device_find_by_index(index);
 +
 +              if (device) {
 +                      ethernet = connman_device_get_data(device);
 +                      if (ethernet)
 +                              remove_network(device, ethernet);
 +              }
 +
 +              connman_inet_ifup(index);
 +
 +              connman_inet_add_to_bridge(index, bridge);
 +      }
 +
 +      return 0;
 +}
 +
 +static int eth_mesh_remove_from_bridge(const char *bridge)
 +{
 +      GList *list;
 +
 +      DBG("Remove ethernet from bridge %s", bridge);
 +
 +      for (list = eth_interface_list; list; list = list->next) {
 +              int index = GPOINTER_TO_INT(list->data);
 +
 +              connman_inet_remove_from_bridge(index, bridge);
 +      }
 +
 +      return 0;
 +}
 +
 +static struct connman_mesh_eth_driver eth_mesh_driver = {
 +      .add_to_bridge          = eth_mesh_add_to_bridge,
 +      .remove_from_bridge     = eth_mesh_remove_from_bridge,
 +};
 +#endif
 +
  static int ethernet_init(void)
  {
        int err;
        if (err < 0)
                return err;
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +      err = connman_mesh_eth_driver_register(&eth_mesh_driver);
 +      if (err < 0)
 +              return err;
 +#endif
 +
        err = connman_network_driver_register(&eth_network_driver);
        if (err < 0)
                return err;
@@@ -775,10 -459,6 +775,10 @@@ static void ethernet_exit(void
  {
        connman_technology_driver_unregister(&eth_tech_driver);
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +      connman_mesh_eth_driver_unregister(&eth_mesh_driver);
 +#endif
 +
        connman_network_driver_unregister(&eth_network_driver);
  
        connman_device_driver_unregister(&eth_dev_driver);
diff --combined plugins/iwd.c
@@@ -95,6 -95,8 +95,8 @@@ struct iwd_network 
  
        struct iwd_device *iwdd;
        struct connman_network *network;
+       /* service's autoconnect */
+       bool autoconnect;
  };
  
  struct iwd_known_network {
        char *last_connected_time;
        bool auto_connect;
        int auto_connect_id;
+       /* service's autoconnect */
+       bool autoconnect;
  };
  
  struct iwd_station {
@@@ -244,7 -249,7 +249,7 @@@ static void cm_network_connect_cb(DBusM
                if (!strcmp(dbus_error, "net.connman.iwd.Failed"))
                        connman_network_set_error(iwdn->network,
                                        CONNMAN_NETWORK_ERROR_INVALID_KEY);
-               else
+               else if (!iwdn->autoconnect)
                        connman_network_set_error(iwdn->network,
                                        CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
                return;
@@@ -318,12 -323,157 +323,157 @@@ static int cm_network_disconnect(struc
        return -EINPROGRESS;
  }
  
+ struct auto_connect_cb_data {
+       char *path;
+       bool auto_connect;
+ };
+ static void auto_connect_cb_free(struct auto_connect_cb_data *cbd)
+ {
+       g_free(cbd->path);
+       g_free(cbd);
+ }
+ static void auto_connect_cb(const DBusError *error, void *user_data)
+ {
+       struct auto_connect_cb_data *cbd = user_data;
+       struct iwd_known_network *iwdkn;
+       iwdkn = g_hash_table_lookup(known_networks, cbd->path);
+       if (!iwdkn)
+               goto out;
+       if (dbus_error_is_set(error))
+               connman_warn("WiFi known network %s property auto connect %s",
+                       cbd->path, error->message);
+       /* property is updated via watch known_network_property_change() */
+ out:
+       auto_connect_cb_free(cbd);
+ }
+ static int set_auto_connect(struct iwd_known_network *iwdkn, bool auto_connect)
+ {
+       dbus_bool_t dbus_auto_connect = auto_connect;
+       struct auto_connect_cb_data *cbd;
+       if (proxy_get_bool(iwdkn->proxy, "AutoConnect") == auto_connect)
+               return -EALREADY;
+       cbd = g_new(struct auto_connect_cb_data, 1);
+       cbd->path = g_strdup(iwdkn->path);
+       cbd->auto_connect = auto_connect;
+       if (!g_dbus_proxy_set_property_basic(iwdkn->proxy, "AutoConnect",
+                                               DBUS_TYPE_BOOLEAN,
+                                               &dbus_auto_connect,
+                                               auto_connect_cb, cbd, NULL)) {
+               auto_connect_cb_free(cbd);
+               return -EIO;
+       }
+       return -EINPROGRESS;
+ }
+ static gboolean disable_auto_connect_cb(gpointer data)
+ {
+       char *path = data;
+       struct iwd_known_network *iwdkn;
+       iwdkn = g_hash_table_lookup(known_networks, path);
+       if (!iwdkn)
+               return FALSE;
+       if (set_auto_connect(iwdkn, false) != -EINPROGRESS)
+               connman_warn("Failed to disable auto connect");
+       iwdkn->auto_connect_id = 0;
+       return FALSE;
+ }
+ static int disable_auto_connect(struct iwd_known_network *iwdkn)
+ {
+       if (iwdkn->auto_connect_id)
+               return -EBUSY;
+       iwdkn->auto_connect_id = g_timeout_add_full(G_PRIORITY_DEFAULT,
+                                               0,
+                                               disable_auto_connect_cb,
+                                               g_strdup(iwdkn->path),
+                                               g_free);
+       return 0;
+ }
+ static gboolean enable_auto_connect_cb(gpointer data)
+ {
+       char *path = data;
+       struct iwd_known_network *iwdkn;
+       iwdkn = g_hash_table_lookup(known_networks, path);
+       if (!iwdkn)
+               return FALSE;
+       if (set_auto_connect(iwdkn, true) != -EINPROGRESS)
+               connman_warn("Failed to enable auto connect");
+       iwdkn->auto_connect_id = 0;
+       return FALSE;
+ }
+ static int enable_auto_connect(struct iwd_known_network *iwdkn)
+ {
+       if (iwdkn->auto_connect_id)
+               return -EBUSY;
+       iwdkn->auto_connect_id = g_timeout_add_full(G_PRIORITY_DEFAULT,
+                                               0,
+                                               enable_auto_connect_cb,
+                                               g_strdup(iwdkn->path),
+                                               g_free);
+       return 0;
+ }
+ static int update_auto_connect(struct iwd_known_network *iwdkn)
+ {
+       DBG("auto_connect %d autoconnect %d", iwdkn->auto_connect, iwdkn->autoconnect);
+       if (iwdkn->auto_connect == iwdkn->autoconnect)
+               return -EALREADY;
+       if (iwdkn->autoconnect)
+               return enable_auto_connect(iwdkn);
+       return disable_auto_connect(iwdkn);
+ }
+ static int cm_network_set_autoconnect(struct connman_network *network,
+                               bool autoconnect)
+ {
+       struct iwd_network *iwdn = connman_network_get_data(network);
+       struct iwd_known_network *iwdkn;
+       DBG("autoconnect %d", autoconnect);
+       iwdn->autoconnect = autoconnect;
+       if (!iwdn->known_network)
+               return -ENOENT;
+       iwdkn = g_hash_table_lookup(known_networks, iwdn->known_network);
+       if (!iwdkn)
+               return -ENOENT;
+       iwdkn->autoconnect = autoconnect;
+       return update_auto_connect(iwdkn);
+ }
  static struct connman_network_driver network_driver = {
-       .name           = "iwd",
-       .type           = CONNMAN_NETWORK_TYPE_WIFI,
-       .probe          = cm_network_probe,
-       .connect        = cm_network_connect,
-       .disconnect     = cm_network_disconnect,
+       .name                   = "iwd",
+       .type                   = CONNMAN_NETWORK_TYPE_WIFI,
+       .probe                  = cm_network_probe,
+       .connect                = cm_network_connect,
+       .disconnect             = cm_network_disconnect,
+       .set_autoconnect        = cm_network_set_autoconnect,
  };
  
  static int cm_device_probe(struct connman_device *device)
@@@ -535,7 -685,7 +685,7 @@@ static void tech_enable_tethering_cb(co
  {
        struct tech_cb_data *cbd = user_data;
        struct iwd_device *iwdd;
-       struct iwd_ap *iwdap;
+       struct iwd_ap *iwdap = NULL;
  
        DBG("");
  
@@@ -616,7 -766,7 +766,7 @@@ static void tech_disable_tethering_cb(c
  
        if (!g_dbus_proxy_method_call(iwdap->proxy, "Stop",
                                        NULL, tech_ap_stop_cb, cbd, NULL)) {
-               connman_warn("iwd ap %s could not start AccessPoint mode: %s",
+               connman_warn("iwd ap %s could not stop AccessPoint mode: %s",
                        cbd->path, error->message);
                goto out;
        }
@@@ -923,6 -1073,7 +1073,7 @@@ static void network_property_change(GDB
                DBusMessageIter *iter, void *user_data)
  {
        struct iwd_network *iwdn;
+       struct iwd_known_network *iwdkn;
        const char *path;
  
        path = g_dbus_proxy_get_path(proxy);
                        update_network_connected(iwdn);
                else
                        update_network_disconnected(iwdn);
+       } else if (!strcmp(name, "KnownNetwork")) {
+               g_free(iwdn->known_network);
+               iwdn->known_network =
+                       g_strdup(proxy_get_string(proxy, "KnownNetwork"));
+               if (!iwdn->known_network)
+                       return;
+               iwdkn = g_hash_table_lookup(known_networks,
+                                       iwdn->known_network);
+               if (iwdkn)
+                       update_auto_connect(iwdkn);
        }
  }
  
@@@ -972,12 -1134,15 +1134,15 @@@ static void _update_signal_strength(con
  
        connman_network_set_strength(iwdn->network,
                                        calculate_strength(signal_strength));
+       connman_network_set_available(iwdn->network, true);
        connman_network_update(iwdn->network);
  }
  
  static void ordered_networks_cb(DBusMessage *message, void *user_data)
  {
        DBusMessageIter array, entry;
+       struct iwd_device *iwdd;
+       char *path = user_data;
  
        DBG("");
  
  
                dbus_message_iter_next(&entry);
        }
+       iwdd = g_hash_table_lookup(devices, path);
+       if (iwdd)
+               connman_device_set_scanning(iwdd->device,
+                               CONNMAN_SERVICE_TYPE_WIFI, false);
  }
  
  static void update_signal_strength(struct iwd_station *iwds)
        if (!g_dbus_proxy_method_call(iwds->proxy,
                                        "GetOrderedNetworks",
                                        NULL, ordered_networks_cb,
-                                       NULL, NULL))
+                                       g_strdup(iwds->path), g_free))
                DBG("GetOrderedNetworks() failed");
  }
  
@@@ -1020,6 -1190,7 +1190,7 @@@ static void station_property_change(GDB
                DBusMessageIter *iter, void *user_data)
  {
        struct iwd_station *iwds;
+       struct iwd_device *iwdd;
        const char *path;
  
        path = g_dbus_proxy_get_path(proxy);
                dbus_message_iter_get_basic(iter, &scanning);
                iwds->scanning = scanning;
  
-               if (!iwds->scanning)
+               if (iwds->scanning) {
+                       iwdd = g_hash_table_lookup(devices, path);
+                       if (iwdd)
+                               connman_device_set_scanning(iwdd->device,
+                                       CONNMAN_SERVICE_TYPE_WIFI, true);
+               } else {
                        update_signal_strength(iwds);
+               }
  
                DBG("%s scanning %d", path, iwds->scanning);
        }
@@@ -1452,86 -1630,6 +1630,86 @@@ static void create_network(GDBusProxy *
        add_network(path, iwdn);
  }
  
 +struct auto_connect_cb_data {
 +      char *path;
 +      bool auto_connect;
 +};
 +
 +static void auto_connect_cb_free(struct auto_connect_cb_data *cbd)
 +{
 +      g_free(cbd->path);
 +      g_free(cbd);
 +}
 +
 +static void auto_connect_cb(const DBusError *error, void *user_data)
 +{
 +      struct auto_connect_cb_data *cbd = user_data;
 +      struct iwd_known_network *iwdkn;
 +
 +      iwdkn = g_hash_table_lookup(known_networks, cbd->path);
 +      if (!iwdkn)
 +              goto out;
 +
 +      if (dbus_error_is_set(error))
 +              connman_warn("WiFi known network %s property auto connect %s",
 +                      cbd->path, error->message);
 +
 +      /* property is updated via watch known_network_property_change() */
 +out:
 +      auto_connect_cb_free(cbd);
 +}
 +
 +static int set_auto_connect(struct iwd_known_network *iwdkn, bool auto_connect)
 +{
 +      dbus_bool_t dbus_auto_connect = auto_connect;
 +      struct auto_connect_cb_data *cbd;
 +
 +      if (proxy_get_bool(iwdkn->proxy, "AutoConnect") == auto_connect)
 +              return -EALREADY;
 +
 +      cbd = g_new(struct auto_connect_cb_data, 1);
 +      cbd->path = g_strdup(iwdkn->path);
 +      cbd->auto_connect = auto_connect;
 +
 +      if (!g_dbus_proxy_set_property_basic(iwdkn->proxy, "AutoConnect",
 +                                              DBUS_TYPE_BOOLEAN,
 +                                              &dbus_auto_connect,
 +                                              auto_connect_cb, cbd, NULL)) {
 +              auto_connect_cb_free(cbd);
 +              return -EIO;
 +      }
 +
 +      return -EINPROGRESS;
 +}
 +
 +static gboolean disable_auto_connect_cb(gpointer data)
 +{
 +      char *path = data;
 +      struct iwd_known_network *iwdkn;
 +
 +      iwdkn = g_hash_table_lookup(known_networks, path);
 +      if (!iwdkn)
 +              return FALSE;
 +
 +      if (set_auto_connect(iwdkn, false) != -EINPROGRESS)
 +              connman_warn("Failed to disable auto connect");
 +
 +      iwdkn->auto_connect_id = 0;
 +      return FALSE;
 +}
 +
 +static void disable_auto_connect(struct iwd_known_network *iwdkn)
 +{
 +      if (iwdkn->auto_connect_id)
 +              return;
 +
 +      iwdkn->auto_connect_id = g_timeout_add_full(G_PRIORITY_DEFAULT,
 +                                              0,
 +                                              disable_auto_connect_cb,
 +                                              g_strdup(iwdkn->path),
 +                                              g_free);
 +}
 +
  static void known_network_property_change(GDBusProxy *proxy, const char *name,
                DBusMessageIter *iter, void *user_data)
  {
  
                DBG("%p auto_connect %d", path, iwdkn->auto_connect);
  
-               if (iwdkn->auto_connect)
-                       disable_auto_connect(iwdkn);
+               update_auto_connect(iwdkn);
+       }
+ }
+ static void init_auto_connect(struct iwd_known_network *iwdkn)
+ {
+       GHashTableIter iter;
+       gpointer key, value;
+       g_hash_table_iter_init(&iter, networks);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               struct iwd_network *iwdn = value;
+               struct iwd_known_network *kn;
+               if (!iwdn->known_network)
+                       continue;
+               kn = g_hash_table_lookup(known_networks, iwdn->known_network);
+               if (iwdkn != kn)
+                       continue;
+               iwdkn->autoconnect = iwdn->autoconnect;
+               update_auto_connect(iwdkn);
+               return;
        }
  }
  
@@@ -1589,11 -1710,10 +1790,10 @@@ static void create_know_network(GDBusPr
                iwdkn->name, iwdkn->type, iwdkn->hidden,
                iwdkn->last_connected_time, iwdkn->auto_connect);
  
+       init_auto_connect(iwdkn);
        g_dbus_proxy_set_property_watch(iwdkn->proxy,
                        known_network_property_change, NULL);
-       if (iwdkn->auto_connect)
-               disable_auto_connect(iwdkn);
  }
  
  static void create_station(GDBusProxy *proxy)
diff --combined plugins/loopback.c
index 28a59c9,e113887..3809d8f
mode 100755,100644..100755
  #include <sys/socket.h>
  #include <arpa/inet.h>
  #include <net/if.h>
 +#include <stdio.h>
  
  #include <glib.h>
 +#include <glib/gprintf.h>
  
  #define CONNMAN_API_SUBJECT_TO_CHANGE
  #include <connman/plugin.h>
@@@ -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);
        else
                create_hostname();
 +#endif
  
        memset(name, 0, sizeof(name));
  
diff --combined plugins/neard.c
index 69586df,45effd4..45effd4
mode 100755,100644..100755
@@@ -499,7 -499,7 +499,7 @@@ static void register_agent_cb(DBusPendi
        DBusMessage *reply;
  
        if (!dbus_pending_call_get_completed(pending))
-               return;
+               goto out;
  
        register_call = NULL;
  
diff --combined plugins/ofono.c
index 36873d5,f0bd3c5..f0bd3c5
mode 100755,100644..100755
@@@ -910,7 -910,7 +910,7 @@@ static void extract_ipv4_settings(DBusM
        if (context->ipv4_method != CONNMAN_IPCONFIG_METHOD_FIXED)
                goto out;
  
-       context->ipv4_address = connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4);
+       context->ipv4_address = connman_ipaddress_alloc(AF_INET);
        if (!context->ipv4_address) {
                context->index = -1;
                goto out;
@@@ -998,7 -998,7 +998,7 @@@ static void extract_ipv6_settings(DBusM
        context->ipv6_method = CONNMAN_IPCONFIG_METHOD_AUTO;
  
        context->ipv6_address =
-               connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6);
+               connman_ipaddress_alloc(AF_INET6);
        if (!context->ipv6_address)
                goto out;
  
diff --combined plugins/vpn.c
index 5668c00,d708d1f..d708d1f
mode 100755,100644..100755
@@@ -85,6 -85,7 +85,7 @@@ struct connection_data 
        char *domain;
        char **nameservers;
        bool immutable;
+       bool default_route_set;
  
        GHashTable *server_routes;
        GHashTable *user_routes;
@@@ -94,6 -95,7 +95,7 @@@
  
        GResolv *resolv;
        guint resolv_id;
+       guint remove_resolv_id;
  };
  
  static int set_string(struct connman_provider *provider,
@@@ -151,6 -153,8 +153,8 @@@ static const char *get_string(struct co
                        return data->host_ip[0];
        } else if (g_str_equal(key, "VPN.Domain"))
                return data->domain;
+       else if (g_str_equal(key, "Transport"))
+               return data->service_ident;
  
        return g_hash_table_lookup(data->setting_strings, key);
  }
@@@ -171,10 -175,15 +175,15 @@@ static char *get_ident(const char *path
  
  static void cancel_host_resolv(struct connection_data *data)
  {
-       if (data->resolv_id != 0)
+       if (data->remove_resolv_id)
+               g_source_remove(data->remove_resolv_id);
+       if (data->resolv && data->resolv_id)
                g_resolv_cancel_lookup(data->resolv, data->resolv_id);
  
        data->resolv_id = 0;
+       data->remove_resolv_id = 0;
  
        g_resolv_unref(data->resolv);
        data->resolv = NULL;
@@@ -206,7 -215,7 +215,7 @@@ static void resolv_result(GResolvResult
         * We cannot unref the resolver here as resolv struct is manipulated
         * by gresolv.c after we return from this callback.
         */
-       g_idle_add(remove_resolv, data);
+       data->remove_resolv_id = g_idle_add(remove_resolv, data);
  
        data->resolv_id = 0;
  }
@@@ -261,14 -270,12 +270,12 @@@ static bool provider_is_connected(struc
  static void set_provider_state(struct connection_data *data)
  {
        enum connman_provider_state state = CONNMAN_PROVIDER_STATE_UNKNOWN;
+       bool connected;
        int err = 0;
  
        DBG("provider %p new state %s", data->provider, data->state);
  
-       if (!provider_is_connected(data)) {
-               g_free(data->service_ident);
-               data->service_ident = NULL;
-       }
+       connected = provider_is_connected(data);
  
        if (g_str_equal(data->state, "ready")) {
                state = CONNMAN_PROVIDER_STATE_READY;
        }
  
        connman_provider_set_state(data->provider, state);
-       return;
+       goto free;
  
  set:
        if (data->cb_data)
  
        free_config_cb_data(data->cb_data);
        data->cb_data = NULL;
+ free:
+       if (!connected) {
+               g_free(data->service_ident);
+               data->service_ident = NULL;
+       }
  }
  
  static int create_provider(struct connection_data *data, void *user_data)
@@@ -431,6 -444,7 +444,7 @@@ static int extract_ip(DBusMessageIter *
        }
  
        connman_ipaddress_set_peer(data->ip, peer);
+       connman_ipaddress_set_p2p(data->ip, true);
  
        return 0;
  }
@@@ -490,8 -504,12 +504,12 @@@ static void connect_reply(DBusPendingCa
        struct connection_data *data = user_data;
        struct config_create_data *cb_data = data->cb_data;
  
-       if (!dbus_pending_call_get_completed(call))
-               return;
+       DBG("");
+       if (!dbus_pending_call_get_completed(call)) {
+               connman_warn("vpn connect reply pending call incomplete");
+               goto out;
+       }
  
        if (call != data->call) {
                connman_error("invalid call %p to VPN connect_reply data %p "
@@@ -769,12 -787,16 +787,16 @@@ static void get_connections_reply(DBusP
                DBUS_DICT_ENTRY_END_CHAR_AS_STRING
                DBUS_STRUCT_END_CHAR_AS_STRING;
  
-       if (!dbus_pending_call_get_completed(call))
-               return;
        DBG("");
  
+       if (!dbus_pending_call_get_completed(call)) {
+               connman_warn("get connections reply pending call incomplete");
+               goto out;
+       }
        reply = dbus_pending_call_steal_reply(call);
+       if (!reply)
+               goto out;
  
        dbus_error_init(&error);
  
  done:
        dbus_message_unref(reply);
  
+ out:
        dbus_pending_call_unref(call);
  }
  
@@@ -861,12 -884,16 +884,16 @@@ static void remove_connection_reply(DBu
        DBusMessage *reply;
        DBusError error;
  
-       if (!dbus_pending_call_get_completed(call))
-               return;
        DBG("");
  
+       if (!dbus_pending_call_get_completed(call)) {
+               connman_warn("remove connection reply pending call incomplete");
+               goto out;
+       }
        reply = dbus_pending_call_steal_reply(call);
+       if (!reply)
+               goto out;
  
        dbus_error_init(&error);
  
  
        dbus_message_unref(reply);
  
+ out:
        dbus_pending_call_unref(call);
  }
  
@@@ -1010,11 -1038,14 +1038,14 @@@ static int disconnect_provider(struct c
        dbus_pending_call_set_notify(data->disconnect_call, disconnect_reply,
                                                                data, NULL);
  
-       g_free(data->service_ident);
-       data->service_ident = NULL;
+       data->default_route_set = false;
  
        connman_provider_set_state(data->provider,
                                        CONNMAN_PROVIDER_STATE_DISCONNECT);
+       g_free(data->service_ident);
+       data->service_ident = NULL;
        return -EINPROGRESS;
  }
  
@@@ -1055,12 -1086,16 +1086,16 @@@ static void configuration_create_reply(
        struct connection_data *data;
        struct config_create_data *cb_data = user_data;
  
-       if (!dbus_pending_call_get_completed(call))
-               return;
        DBG("user %p", cb_data);
  
+       if (!dbus_pending_call_get_completed(call)) {
+               connman_warn("configuration create reply pending call incomplete");
+               goto out;
+       }
        reply = dbus_pending_call_steal_reply(call);
+       if (!reply)
+               goto out;
  
        dbus_error_init(&error);
  
  done:
        dbus_message_unref(reply);
  
+ out:
        dbus_pending_call_unref(call);
  }
  
@@@ -1461,6 -1497,17 +1497,17 @@@ static void set_route(struct connection
                return;
        }
  
+       DBG("set route provider %p %s/%s/%s", data->provider,
+                                               route->network, route->gateway,
+                                               route->netmask);
+       /* Do not add default route for split routed VPNs.*/
+       if (connman_provider_is_split_routing(data->provider) &&
+                               connman_inet_is_default_route(route->family,
+                                       route->network, route->gateway,
+                                       route->netmask))
+               return;
        if (route->family == AF_INET6) {
                unsigned char prefix_len = atoi(route->netmask);
  
                                                route->gateway,
                                                route->netmask);
        }
+       if (connman_inet_is_default_route(route->family, route->network,
+                                       route->gateway, route->netmask))
+               data->default_route_set = true;
+ }
+ static int save_route(GHashTable *routes, int family, const char *network,
+                       const char *netmask, const char *gateway);
+ static int add_network_route(struct connection_data *data)
+ {
+       struct vpn_route rt = { 0, };
+       int err;
+       if (!data)
+               return -EINVAL;
+       rt.family = connman_provider_get_family(data->provider);
+       switch (rt.family) {
+       case PF_INET:
+               err = connman_inet_get_route_addresses(data->index,
+                                       &rt.network, &rt.netmask, &rt.gateway);
+               break;
+       case PF_INET6:
+               err = connman_inet_ipv6_get_route_addresses(data->index,
+                                       &rt.network, &rt.netmask, &rt.gateway);
+               break;
+       default:
+               connman_error("invalid protocol family %d", rt.family);
+               return -EINVAL;
+       }
+       DBG("network %s gateway %s netmask %s for provider %p",
+                                               rt.network, rt.gateway, rt.netmask,
+                                               data->provider);
+       if (err) {
+               connman_error("cannot get network/gateway/netmask for %p",
+                                                       data->provider);
+               goto out;
+       }
+       err = save_route(data->server_routes, rt.family, rt.network, rt.netmask,
+                               rt.gateway);
+       if (err) {
+               connman_warn("failed to add network route for provider"
+                                       "%p", data->provider);
+               goto out;
+       }
+       set_route(data, &rt);
+ out:
+       g_free(rt.network);
+       g_free(rt.netmask);
+       g_free(rt.gateway);
+       return 0;
+ }
+ static bool is_valid_route_table(struct connman_provider *provider,
+                                                       GHashTable *table)
+ {
+       GHashTableIter iter;
+       gpointer value, key;
+       struct vpn_route *route;
+       size_t table_size;
+       if (!table)
+               return false;
+       table_size = g_hash_table_size(table);
+       /* Non-split routed may have only the default route */
+       if (table_size > 0 && !connman_provider_is_split_routing(provider))
+               return true;
+       /* Split routed has more than the default route */
+       if (table_size > 1)
+               return true;
+       /*
+        * Only one route for split routed VPN, which should not be the
+        * default route.
+        */
+       g_hash_table_iter_init(&iter, table);
+       if (!g_hash_table_iter_next(&iter, &key, &value)) /* First and only */
+               return false;
+       route = value;
+       if (!route)
+               return false;
+       DBG("check route %d %s/%s/%s", route->family, route->network,
+                                       route->gateway, route->netmask);
+       if (!connman_inet_is_default_route(route->family, route->network,
+                               route->gateway, route->netmask))
+               return true;
+       return false;
+ }
+ static bool check_routes(struct connman_provider *provider)
+ {
+       struct connection_data *data;;
+       DBG("provider %p", provider);
+       data = connman_provider_get_data(provider);
+       if (!data)
+               return false;
+       if (is_valid_route_table(provider, data->user_routes))
+               return true;
+       if (is_valid_route_table(provider, data->server_routes))
+               return true;
+       return false;
  }
  
  static int set_routes(struct connman_provider *provider,
                        set_route(data, value);
        }
  
-       return 0;
- }
- static bool check_routes(struct connman_provider *provider)
- {
-       struct connection_data *data;
-       DBG("provider %p", provider);
+       /* If non-split routed VPN does not have a default route, add it */
+       if (!connman_provider_is_split_routing(provider) &&
+                                               !data->default_route_set) {
+               int family = connman_provider_get_family(provider);
+               const char *ipaddr_any = family == AF_INET6 ?
+                                                       "::" : "0.0.0.0";
+               struct vpn_route def_route = {family, (char*) ipaddr_any,
+                                               (char*) ipaddr_any, NULL};
  
-       data = connman_provider_get_data(provider);
-       if (!data)
-               return false;
-       if (data->user_routes &&
-                       g_hash_table_size(data->user_routes) > 0)
-               return true;
+               set_route(data, &def_route);
+       }
  
-       if (data->server_routes &&
-                       g_hash_table_size(data->server_routes) > 0)
-               return true;
+       /* Split routed VPN must have at least one route to the network */
+       if (connman_provider_is_split_routing(provider) &&
+                                               !check_routes(provider)) {
+               int err = add_network_route(data);
+               if (err) {
+                       connman_warn("cannot add network route provider %p",
+                                                               provider);
+                       return err;
+               }
+       }
  
-       return false;
+       return 0;
  }
  
  static struct connman_provider_driver provider_driver = {
@@@ -1694,12 -1863,52 +1863,52 @@@ static int save_route(GHashTable *route
                route->gateway = g_strdup(gateway);
  
                g_hash_table_replace(routes, key, route);
-       } else
+       } else {
                g_free(key);
+               return -EALREADY;
+       }
  
        return 0;
  }
  
+ static void change_provider_split_routing(struct connman_provider *provider,
+                                                       bool split_routing)
+ {
+       struct connection_data *data;
+       int err;
+       if (!provider)
+               return;
+       if (connman_provider_is_split_routing(provider) == split_routing)
+               return;
+       data = connman_provider_get_data(provider);
+       if (split_routing && data && provider_is_connected(data) &&
+                                               !check_routes(provider)) {
+               err = add_network_route(data);
+               if (err) {
+                       connman_warn("cannot add network route provider %p",
+                                                               provider);
+                       return;
+               }
+       }
+       err = connman_provider_set_split_routing(provider, split_routing);
+       switch (err) {
+       case 0:
+               /* fall through */
+       case -EALREADY:
+               break;
+       case -EINVAL:
+               /* fall through */
+       case -EOPNOTSUPP:
+               connman_warn("cannot change split routing %d", err);
+       default:
+               break;
+       }
+ }
  static int read_route_dict(GHashTable *routes, DBusMessageIter *dicts)
  {
        DBusMessageIter dict;
@@@ -1876,6 -2085,10 +2085,10 @@@ static gboolean property_changed(DBusCo
                g_free(data->domain);
                data->domain = g_strdup(str);
                connman_provider_set_domain(data->provider, data->domain);
+       } else if (g_str_equal(key, "SplitRouting")) {
+               dbus_bool_t split_routing;
+               dbus_message_iter_get_basic(&value, &split_routing);
+               change_provider_split_routing(data->provider, split_routing);
        }
  
        if (ip_set && err == 0) {
@@@ -1964,6 -2177,10 +2177,10 @@@ static void vpn_disconnect_check_provid
                if (!vpn_is_valid_transport(service)) {
                        connman_provider_disconnect(data->provider);
                }
+               /* VPN moved to be split routed, default route is not set */
+               if (connman_provider_is_split_routing(data->provider))
+                       data->default_route_set = false;
        }
  }
  
diff --combined plugins/wifi.c
index 26b988e,e701451..bcb9344
mode 100755,100644..100755
@@@ -49,7 -49,6 +49,6 @@@
  #include <connman/service.h>
  #include <connman/peer.h>
  #include <connman/log.h>
- #include <connman/option.h>
  #include <connman/storage.h>
  #include <include/setting.h>
  #include <connman/provision.h>
  #define BGSCAN_DEFAULT "simple:30:-65:300"
  #define AUTOSCAN_EXPONENTIAL "exponential:3:300"
  #define AUTOSCAN_SINGLE "single:3"
+ #define SCAN_MAX_DURATION 10
  
  #define P2P_FIND_TIMEOUT 30
  #define P2P_CONNECTION_TIMEOUT 100
  #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;
@@@ -235,123 -182,6 +240,123 @@@ static int tech_set_tethering(struct co
                                const char *identifier, const char *passphrase,
                                const char *bridge, bool enabled);
  
 +#if defined TIZEN_EXT
 +#define NETCONFIG_SERVICE "net.netconfig"
 +#define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
 +#define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
 +
 +struct enc_method_call_data {
 +      DBusConnection *connection;
 +      struct connman_network *network;
 +};
 +
 +static struct enc_method_call_data encrypt_request_data;
 +
 +static void encryption_request_reply(DBusPendingCall *call,
 +                                              void *user_data)
 +{
 +      DBusMessage *reply;
 +      DBusError error;
 +      DBusMessageIter args;
 +      char *out_data;
 +      struct connman_service *service;
 +      gchar* encrypted_value = NULL;
 +      struct connman_network *network = encrypt_request_data.network;
 +
 +      DBG("");
 +
 +      reply = dbus_pending_call_steal_reply(call);
 +
 +      dbus_error_init(&error);
 +      if (dbus_set_error_from_message(&error, reply)) {
 +              DBG("send_encryption_request() %s %s", error.name, error.message);
 +              dbus_error_free(&error);
 +              goto done;
 +      }
 +
 +      if (dbus_message_iter_init(reply, &args) == FALSE)
 +              goto done;
 +
 +      dbus_message_iter_get_basic(&args, &out_data);
 +
 +      encrypted_value = g_strdup((const gchar *)out_data);
 +      service = connman_service_lookup_from_network(network);
 +
 +      if (!service) {
 +              DBG("encryption result: no service");
 +              goto done;
 +      }
 +
 +      if (connman_service_get_favorite(service)) {
 +              __connman_service_set_passphrase(service, encrypted_value);
 +              __connman_service_save(service);
 +      } else
 +              connman_network_set_string(network, "WiFi.Passphrase",
 +                                                      encrypted_value);
 +
 +      DBG("encryption result: succeeded");
 +
 +done:
 +      dbus_message_unref(reply);
 +      dbus_pending_call_unref(call);
 +      dbus_connection_unref(encrypt_request_data.connection);
 +      g_free(encrypted_value);
 +
 +      encrypt_request_data.connection = NULL;
 +      encrypt_request_data.network = NULL;
 +}
 +
 +static int send_encryption_request(const char *passphrase,
 +                              struct connman_network *network)
 +{
 +      DBusConnection *connection = NULL;
 +      DBusMessage *msg = NULL;
 +      DBusPendingCall *call;
 +
 +      if (!passphrase) {
 +              DBG("Invalid parameter");
 +              return -EINVAL;
 +      }
 +
 +      connection = connman_dbus_get_connection();
 +      if (!connection) {
 +              DBG("dbus connection does not exist");
 +              return -EINVAL;
 +      }
 +
 +      msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
 +                      NETCONFIG_WIFI_INTERFACE, "EncryptPassphrase");
 +      if (!msg) {
 +              dbus_connection_unref(connection);
 +              return -EINVAL;
 +      }
 +
 +      dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
 +                                                      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;
 +      }
 +
 +      encrypt_request_data.connection = connection;
 +      encrypt_request_data.network = network;
 +
 +      dbus_pending_call_set_notify(call, encryption_request_reply, NULL, NULL);
 +      dbus_message_unref(msg);
 +
 +      return 0;
 +}
 +#endif
 +
  static int p2p_tech_probe(struct connman_technology *technology)
  {
        p2p_technology = technology;
@@@ -393,2952 -223,1671 +398,2984 @@@ static void add_pending_wifi_device(str
        pending_wifi_device = g_list_append(pending_wifi_device, wifi);
  }
  
 -static struct wifi_data *get_pending_wifi_data(const char *ifname)
 -{
 -      GList *list;
 -
 -      for (list = pending_wifi_device; list; list = list->next) {
 -              struct wifi_data *wifi;
 -              const char *dev_name;
 -
 -              wifi = list->data;
 -              if (!wifi || !wifi->device)
 -                      continue;
 +#if defined TIZEN_EXT_WIFI_MESH
 +struct wifi_mesh_info {
 +      struct wifi_data *wifi;
 +      GSupplicantInterface *interface;
 +      struct connman_mesh *mesh;
 +      char *parent_ifname;
 +      char *ifname;
 +      char *identifier;
 +      int index;
 +};
  
 -              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;
 -              }
 -      }
 +struct mesh_change_peer_status_info {
 +      char *peer_address;
 +      enum connman_mesh_peer_status peer_status;
 +      mesh_change_peer_status_cb_t callback;
 +      void *user_data;
 +};
  
 -      return NULL;
 -}
 +static struct connman_technology_driver mesh_tech_driver = {
 +      .name = "mesh",
 +      .type = CONNMAN_SERVICE_TYPE_MESH,
 +};
  
 -static void remove_pending_wifi_device(struct wifi_data *wifi)
 +static void mesh_interface_create_callback(int result,
 +                                         GSupplicantInterface *interface,
 +                                         void *user_data)
  {
 -      GList *link;
 -
 -      link = g_list_find(pending_wifi_device, wifi);
 +      struct wifi_mesh_info *mesh_info = user_data;
 +      struct wifi_data *wifi;
 +      bool success = false;
  
 -      if (!link)
 -              return;
 +      DBG("result %d ifname %s, mesh_info %p", result,
 +                              g_supplicant_interface_get_ifname(interface),
 +                              mesh_info);
  
 -      pending_wifi_device = g_list_delete_link(pending_wifi_device, link);
 -}
 +      if (result < 0 || !mesh_info)
 +              goto done;
  
 -static void peer_cancel_timeout(struct wifi_data *wifi)
 -{
 -      if (wifi->p2p_connection_timeout > 0)
 -              g_source_remove(wifi->p2p_connection_timeout);
 +      wifi = mesh_info->wifi;
  
 -      wifi->p2p_connection_timeout = 0;
 -      wifi->p2p_connecting = false;
 +      mesh_info->interface = interface;
 +      mesh_info->identifier = connman_inet_ifaddr(mesh_info->ifname);
 +      mesh_info->index = connman_inet_ifindex(mesh_info->ifname);
 +      DBG("Mesh Interface identifier %s", mesh_info->identifier);
 +      wifi->mesh_interface = true;
 +      wifi->mesh_info = mesh_info;
 +      g_supplicant_interface_set_data(interface, wifi);
 +      success = true;
  
 -      if (wifi->pending_peer) {
 -              connman_peer_unref(wifi->pending_peer);
 -              wifi->pending_peer = NULL;
 -      }
 +done:
 +      connman_mesh_notify_interface_create(success);
  }
  
 -static gboolean peer_connect_timeout(gpointer data)
 +static int add_mesh_interface(const char *ifname, const char *parent_ifname)
  {
 -      struct wifi_data *wifi = data;
 +      GList *list;
 +      struct wifi_data *wifi;
 +      struct wifi_mesh_info *mesh_info;
 +      const char *wifi_ifname;
 +      bool parent_found = false;
 +      const char *driver = "nl80211";
  
 -      DBG("");
 +      for (list = iface_list; list; list = list->next) {
 +              wifi = list->data;
  
 -      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_interface_has_mesh(wifi->interface))
 +                      continue;
  
 -              if (g_supplicant_peer_has_requested_connection(gs_peer))
 -                      state = CONNMAN_PEER_STATE_IDLE;
 +              wifi_ifname = g_supplicant_interface_get_ifname(wifi->interface);
 +              if (!wifi_ifname)
 +                      continue;
  
 -              connman_peer_set_state(wifi->pending_peer, state);
 +              if (!g_strcmp0(wifi_ifname, parent_ifname)) {
 +                      parent_found = true;
 +                      break;
 +              }
        }
  
 -      peer_cancel_timeout(wifi);
 +      if (!parent_found) {
 +              DBG("Parent interface %s doesn't exist", parent_ifname);
 +              return -ENODEV;
 +      }
  
 -      return FALSE;
 +      mesh_info = g_try_malloc0(sizeof(struct wifi_mesh_info));
 +      if (!mesh_info)
 +              return -ENOMEM;
 +
 +      mesh_info->wifi = wifi;
 +      mesh_info->ifname = g_strdup(ifname);
 +      mesh_info->parent_ifname = g_strdup(parent_ifname);
 +
 +      g_supplicant_mesh_interface_create(ifname, driver, NULL, parent_ifname,
 +                                              mesh_interface_create_callback, mesh_info);
 +      return -EINPROGRESS;
  }
  
 -static void peer_connect_callback(int result, GSupplicantInterface *interface,
 +static void mesh_interface_remove_callback(int result,
 +                                      GSupplicantInterface *interface,
                                                        void *user_data)
  {
        struct wifi_data *wifi = user_data;
 -      struct connman_peer *peer = wifi->pending_peer;
 +      struct wifi_mesh_info *mesh_info = wifi->mesh_info;
 +      bool success = false;
  
 -      DBG("peer %p - %d", peer, result);
 -
 -      if (!peer)
 -              return;
 +      DBG("result %d mesh_info %p", result, mesh_info);
  
 -      if (result < 0) {
 -              peer_connect_timeout(wifi);
 -              return;
 -      }
 +      if (result < 0 || !mesh_info)
 +              goto done;
  
 -      connman_peer_set_state(peer, CONNMAN_PEER_STATE_ASSOCIATION);
 +      mesh_info->interface = NULL;
 +      g_free(mesh_info->parent_ifname);
 +      g_free(mesh_info->ifname);
 +      g_free(mesh_info->identifier);
 +      g_free(mesh_info);
 +      wifi->mesh_interface = false;
 +      wifi->mesh_info = NULL;
 +      success = true;
  
 -      wifi->p2p_connection_timeout = g_timeout_add_seconds(
 -                                              P2P_CONNECTION_TIMEOUT,
 -                                              peer_connect_timeout, wifi);
 +done:
 +      connman_mesh_notify_interface_remove(success);
  }
  
 -static int peer_connect(struct connman_peer *peer,
 -                      enum connman_peer_wps_method wps_method,
 -                      const char *wps_pin)
 +static int remove_mesh_interface(const char *ifname)
  {
 -      struct connman_device *device = connman_peer_get_device(peer);
 -      GSupplicantPeerParams *peer_params;
 -      GSupplicantPeer *gs_peer;
 +      GList *list;
        struct wifi_data *wifi;
 -      bool pbc, pin;
 +      struct wifi_mesh_info *mesh_info;
 +      bool mesh_if_found = false;
        int ret;
  
 -      DBG("peer %p", peer);
 +      for (list = iface_list; list; list = list->next) {
 +              wifi = list->data;
  
 -      if (!device)
 -              return -ENODEV;
 +              if (wifi->mesh_interface) {
 +                      mesh_if_found = true;
 +                      break;
 +              }
 +      }
  
 -      wifi = connman_device_get_data(device);
 -      if (!wifi || !wifi->interface)
 +      if (!mesh_if_found) {
 +              DBG("Mesh interface %s doesn't exist", ifname);
                return -ENODEV;
 -
 -      if (wifi->p2p_connecting)
 -              return -EBUSY;
 -
 -      gs_peer = g_supplicant_interface_peer_lookup(wifi->interface,
 -                                      connman_peer_get_identifier(peer));
 -      if (!gs_peer)
 -              return -EINVAL;
 -
 -      pbc = g_supplicant_peer_is_wps_pbc(gs_peer);
 -      pin = g_supplicant_peer_is_wps_pin(gs_peer);
 -
 -      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;
        }
  
 -      peer_params = g_try_malloc0(sizeof(GSupplicantPeerParams));
 -      if (!peer_params)
 -              return -ENOMEM;
 -
 -      peer_params->path = g_strdup(g_supplicant_peer_get_path(gs_peer));
 -      if (wps_pin)
 -              peer_params->wps_pin = g_strdup(wps_pin);
 +      mesh_info = wifi->mesh_info;
 +      ret = g_supplicant_interface_remove(mesh_info->interface,
 +                                              mesh_interface_remove_callback, wifi);
 +      if (ret < 0)
 +              return ret;
  
 -      peer_params->master = connman_peer_service_is_master();
 +      return -EINPROGRESS;
 +}
  
 -      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);
 -      }
 +static void mesh_disconnect_callback(int result,
 +                                      GSupplicantInterface *interface, void *user_data)
 +{
 +      struct connman_mesh *mesh = user_data;
  
 -      return ret;
 +      DBG("result %d interface %p mesh %p", result, interface, mesh);
  }
  
 -static int peer_disconnect(struct connman_peer *peer)
 +static int mesh_peer_disconnect(struct connman_mesh *mesh)
  {
 -      struct connman_device *device = connman_peer_get_device(peer);
 -      GSupplicantPeerParams peer_params = {};
 -      GSupplicantPeer *gs_peer;
 +      GList *list;
        struct wifi_data *wifi;
 -      int ret;
 +      struct wifi_mesh_info *mesh_info;
 +      bool mesh_if_found = false;
 +      GSupplicantInterface *interface;
  
 -      DBG("peer %p", peer);
 +      for (list = iface_list; list; list = list->next) {
 +              wifi = list->data;
  
 -      if (!device)
 -              return -ENODEV;
 +              if (wifi->mesh_interface) {
 +                      mesh_if_found = true;
 +                      break;
 +              }
 +      }
  
 -      wifi = connman_device_get_data(device);
 -      if (!wifi)
 +      if (!mesh_if_found) {
 +              DBG("Mesh interface is not created");
                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));
 +      mesh_info = wifi->mesh_info;
  
 -      ret = g_supplicant_interface_p2p_disconnect(wifi->interface,
 -                                                      &peer_params);
 -      g_free(peer_params.path);
 +      interface = mesh_info->interface;
 +      return g_supplicant_interface_disconnect(interface,
 +                                              mesh_disconnect_callback, mesh);
 +}
  
 -      if (ret == -EINPROGRESS) {
 -              peer_cancel_timeout(wifi);
 -              wifi->p2p_device = false;
 -      }
 +static void mesh_connect_callback(int result, GSupplicantInterface *interface,
 +                                                                void *user_data)
 +{
 +      struct connman_mesh *mesh = user_data;
 +      DBG("mesh %p result %d", mesh, result);
  
 -      return ret;
 +      if (result < 0)
 +              connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_FAILURE);
 +      else
 +              connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_ASSOCIATION);
  }
  
 -struct peer_service_registration {
 -      peer_service_registration_cb_t callback;
 -      void *user_data;
 -};
 -
 -static bool is_service_wfd(const unsigned char *specs, int length)
 +static GSupplicantSecurity mesh_network_security(const char *security)
  {
 -      if (length < 9 || specs[0] != 0 || specs[1] != 0 || specs[2] != 6)
 -              return false;
 +      if (g_str_equal(security, "none"))
 +              return G_SUPPLICANT_SECURITY_NONE;
 +      else if (g_str_equal(security, "sae"))
 +              return G_SUPPLICANT_SECURITY_SAE;
  
 -      return true;
 +      return G_SUPPLICANT_SECURITY_UNKNOWN;
  }
  
 -static void apply_p2p_listen_on_iface(gpointer data, gpointer user_data)
 +static void mesh_ssid_init(GSupplicantSSID *ssid, struct connman_mesh *mesh)
  {
 -      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);
 -      }
 +      const char *name;
 +      const char *security;
  
 -      wifi->servicing++;
 -}
 +      if (ssid->ssid)
 +              g_free(ssid->ssid);
  
 -static void register_wfd_service_cb(int result,
 -                              GSupplicantInterface *iface, void *user_data)
 -{
 -      struct peer_service_registration *reg_data = user_data;
 +      memset(ssid, 0, sizeof(*ssid));
 +      ssid->mode = G_SUPPLICANT_MODE_MESH;
  
 -      DBG("");
 +      security = connman_mesh_get_security(mesh);
 +      ssid->security = mesh_network_security(security);
  
 -      if (result == 0)
 -              g_list_foreach(iface_list, apply_p2p_listen_on_iface, NULL);
 +      if (ssid->security == G_SUPPLICANT_SECURITY_SAE)
 +              ssid->passphrase = connman_mesh_get_passphrase(mesh);
  
 -      if (reg_data && reg_data->callback) {
 -              reg_data->callback(result, reg_data->user_data);
 -              g_free(reg_data);
 +      ssid->freq = connman_mesh_get_frequency(mesh);
 +      name = connman_mesh_get_name(mesh);
 +      if (name) {
 +              ssid->ssid_len = strlen(name);
 +              ssid->ssid = g_malloc0(ssid->ssid_len + 1);
 +              memcpy(ssid->ssid, name, ssid->ssid_len);
 +              ssid->scan_ssid = 1;
        }
  }
  
 -static GSupplicantP2PServiceParams *fill_in_peer_service_params(
 -                              const unsigned char *spec,
 -                              int spec_length, const unsigned char *query,
 -                              int query_length, int version)
 +static int mesh_peer_connect(struct connman_mesh *mesh)
  {
 -      GSupplicantP2PServiceParams *params;
 +      GList *list;
 +      struct wifi_data *wifi;
 +      struct wifi_mesh_info *mesh_info;
 +      bool mesh_if_found = false;
 +      GSupplicantInterface *interface;
 +      GSupplicantSSID *ssid;
  
 -      params = g_try_malloc0(sizeof(GSupplicantP2PServiceParams));
 -      if (!params)
 -              return NULL;
 +      for (list = iface_list; list; list = list->next) {
 +              wifi = list->data;
  
 -      if (version > 0) {
 -              params->version = version;
 -              if (spec_length > 0) {
 -                      params->service = g_malloc(spec_length);
 -                      memcpy(params->service, spec, spec_length);
 +              if (wifi->mesh_interface) {
 +                      mesh_if_found = true;
 +                      break;
                }
 -      } else if (query_length > 0 && spec_length > 0) {
 -              params->query = g_malloc(query_length);
 -              memcpy(params->query, query, query_length);
 -              params->query_length = query_length;
 +      }
  
 -              params->response = g_malloc(spec_length);
 -              memcpy(params->response, spec, spec_length);
 -              params->response_length = spec_length;
 -      } else {
 -              if (spec_length > 0) {
 -                      params->wfd_ies = g_malloc(spec_length);
 -                      memcpy(params->wfd_ies, spec, spec_length);
 -              }
 -              params->wfd_ies_length = spec_length;
 +      if (!mesh_if_found) {
 +              DBG("Mesh interface is not created");
 +              return -ENODEV;
        }
  
 -      return params;
 +      mesh_info = wifi->mesh_info;
 +
 +      interface = mesh_info->interface;
 +
 +      ssid = g_try_malloc0(sizeof(GSupplicantSSID));
 +      if (!ssid)
 +              return -ENOMEM;
 +
 +      mesh_info->mesh = mesh;
 +
 +      mesh_ssid_init(ssid, mesh);
 +      return g_supplicant_interface_connect(interface, ssid,
 +                                              mesh_connect_callback, mesh);
  }
  
 -static void free_peer_service_params(GSupplicantP2PServiceParams *params)
 +static void mesh_peer_change_status_callback(int result,
 +                                           GSupplicantInterface *interface,
 +                                           void *user_data)
  {
 -      if (!params)
 -              return;
 +      struct mesh_change_peer_status_info *data = user_data;
  
 -      g_free(params->service);
 -      g_free(params->query);
 -      g_free(params->response);
 -      g_free(params->wfd_ies);
 +      DBG("result %d Peer Status %d", result, data->peer_status);
  
 -      g_free(params);
 +      if (result == 0 && data->peer_status == CONNMAN_MESH_PEER_REMOVE) {
 +              /* WLAN_REASON_MESH_PEERING_CANCELLED = 52 */
 +              connman_mesh_remove_connected_peer(data->peer_address, 52);
 +      }
 +
 +      if (data->callback)
 +              data->callback(result, data->user_data);
 +
 +      g_free(data->peer_address);
 +      g_free(data);
 +      return;
  }
  
 -static int peer_register_wfd_service(const unsigned char *specification,
 -                              int specification_length,
 -                              peer_service_registration_cb_t callback,
 -                              void *user_data)
 +static int mesh_change_peer_status(const char *peer_address,
 +                                 enum connman_mesh_peer_status status,
 +                                 mesh_change_peer_status_cb_t callback, void *user_data)
  {
 -      struct peer_service_registration *reg_data = NULL;
 -      static GSupplicantP2PServiceParams *params;
 -      int ret;
 -
 -      DBG("");
 +      GList *list;
 +      struct wifi_data *wifi;
 +      struct wifi_mesh_info *mesh_info;
 +      bool mesh_if_found = false;
 +      GSupplicantInterface *interface;
 +      struct mesh_change_peer_status_info *data;
 +      const char *method;
  
 -      if (wfd_service_registered)
 -              return -EBUSY;
 +      for (list = iface_list; list; list = list->next) {
 +              wifi = list->data;
  
 -      params = fill_in_peer_service_params(specification,
 -                                      specification_length, NULL, 0, 0);
 -      if (!params)
 -              return -ENOMEM;
 +              if (wifi->mesh_interface) {
 +                      mesh_if_found = true;
 +                      break;
 +              }
 +      }
  
 -      reg_data = g_try_malloc0(sizeof(*reg_data));
 -      if (!reg_data) {
 -              ret = -ENOMEM;
 -              goto error;
 +      if (!mesh_if_found) {
 +              DBG("Mesh interface is not created");
 +              return -ENODEV;
        }
  
 -      reg_data->callback = callback;
 -      reg_data->user_data = user_data;
 +      mesh_info = wifi->mesh_info;
  
 -      ret = g_supplicant_set_widi_ies(params,
 -                                      register_wfd_service_cb, reg_data);
 -      if (ret < 0 && ret != -EINPROGRESS)
 -              goto error;
 +      interface = mesh_info->interface;
  
 -      wfd_service_registered = true;
 +      switch (status) {
 +      case CONNMAN_MESH_PEER_ADD:
 +              method = "MeshPeerAdd";
 +              break;
 +      case CONNMAN_MESH_PEER_REMOVE:
 +              method = "MeshPeerRemove";
 +              break;
 +      default:
 +              DBG("Invalid method");
 +              return -EINVAL;
 +      }
  
 -      return ret;
 -error:
 -      free_peer_service_params(params);
 -      g_free(reg_data);
 +      data = g_try_malloc0(sizeof(struct mesh_change_peer_status_info));
 +      if (data == NULL) {
 +              DBG("Memory allocation failed");
 +              return -ENOMEM;
 +      }
  
 -      return ret;
 +      data->peer_address = g_strdup(peer_address);
 +      data->peer_status = status;
 +      data->callback = callback;
 +      data->user_data = user_data;
 +
 +      return g_supplicant_interface_mesh_peer_change_status(interface,
 +                                              mesh_peer_change_status_callback, peer_address, method,
 +                                              data);
  }
  
 -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;
 +static struct connman_mesh_driver mesh_driver = {
 +      .add_interface      = add_mesh_interface,
 +      .remove_interface   = remove_mesh_interface,
 +      .connect            = mesh_peer_connect,
 +      .disconnect         = mesh_peer_disconnect,
 +      .change_peer_status = mesh_change_peer_status,
 +};
  
 +static void mesh_support(GSupplicantInterface *interface)
 +{
        DBG("");
  
 -      if (result == 0)
 -              apply_p2p_listen_on_iface(wifi, NULL);
 +      if (!g_supplicant_interface_has_mesh(interface))
 +              return;
  
 -      if (reg_data->callback)
 -              reg_data->callback(result, reg_data->user_data);
 +      if (connman_technology_driver_register(&mesh_tech_driver) < 0) {
 +              DBG("Could not register Mesh technology driver");
 +              return;
 +      }
  
 -      g_free(reg_data);
 +      connman_mesh_driver_register(&mesh_driver);
  }
  
 -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)
 +static void check_mesh_technology(void)
  {
 -      struct peer_service_registration *reg_data;
 -      GSupplicantP2PServiceParams *params;
 -      bool found = false;
 -      int ret, ret_f;
 +      bool mesh_exists = false;
        GList *list;
  
 -      DBG("");
 +      for (list = iface_list; list; list = list->next) {
 +              struct wifi_data *w = list->data;
  
 -      if (specification && !version && !query &&
 -                      is_service_wfd(specification, specification_length)) {
 -              return peer_register_wfd_service(specification,
 -                              specification_length, callback, user_data);
 +              if (w->interface &&
 +                              g_supplicant_interface_has_mesh(w->interface))
 +                      mesh_exists = true;
        }
  
 -      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;
 +      if (!mesh_exists) {
 +              connman_technology_driver_unregister(&mesh_tech_driver);
 +              connman_mesh_driver_unregister(&mesh_driver);
 +      }
 +}
  
 -      for (list = iface_list; list; list = list->next) {
 -              struct wifi_data *wifi = list->data;
 -              GSupplicantInterface *iface = wifi->interface;
 +static void mesh_group_started(GSupplicantInterface *interface)
 +{
 +      struct wifi_data *wifi;
 +      struct wifi_mesh_info *mesh_info;
 +      struct connman_mesh *mesh;
 +      const unsigned char *ssid;
 +      unsigned int ssid_len;
 +      char name[33];
  
 -              if (!g_supplicant_interface_has_p2p(iface))
 -                      continue;
 +      ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
 +      memcpy(name, ssid, ssid_len);
 +      name[ssid_len] = '\0';
 +      DBG("name %s", name);
 +      wifi = g_supplicant_interface_get_data(interface);
 +      DBG("wifi %p", wifi);
  
 -              params = fill_in_peer_service_params(specification,
 -                                              specification_length, query,
 -                                              query_length, version);
 -              if (!params)
 -                      continue;
 +      if (!wifi)
 +              return;
  
 -              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);
 -      }
 +      mesh_info = wifi->mesh_info;
 +      if (!mesh_info)
 +              return;
  
 -      if (ret_f != 0 && ret_f != -EINPROGRESS)
 -              g_free(reg_data);
 +      mesh = mesh_info->mesh;
 +      if (!mesh)
 +              return;
  
 -      return ret_f;
 +      connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_CONFIGURATION);
  }
  
 -static int peer_unregister_wfd_service(void)
 +static void mesh_group_removed(GSupplicantInterface *interface)
  {
 -      GSupplicantP2PServiceParams *params;
 -      GList *list;
 -
 -      if (!wfd_service_registered)
 -              return -EALREADY;
 +      struct wifi_data *wifi;
 +      struct wifi_mesh_info *mesh_info;
 +      struct connman_mesh *mesh;
 +      const unsigned char *ssid;
 +      unsigned int ssid_len;
 +      int disconnect_reason;
 +      char name[33];
  
 -      params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
 -      if (!params)
 -              return -ENOMEM;
 +      ssid = g_supplicant_interface_get_mesh_group_ssid(interface, &ssid_len);
 +      memcpy(name, ssid, ssid_len);
 +      name[ssid_len] = '\0';
 +      DBG("name %s", name);
  
 -      wfd_service_registered = false;
 +      disconnect_reason = g_supplicant_mesh_get_disconnect_reason(interface);
 +      DBG("Disconnect Reason %d", disconnect_reason);
  
 -      g_supplicant_set_widi_ies(params, NULL, NULL);
 +      wifi = g_supplicant_interface_get_data(interface);
 +      DBG("wifi %p", wifi);
  
 -      for (list = iface_list; list; list = list->next) {
 -              struct wifi_data *wifi = list->data;
 +      if (!wifi)
 +              return;
  
 -              if (!g_supplicant_interface_has_p2p(wifi->interface))
 -                      continue;
 +      mesh_info = wifi->mesh_info;
 +      if (!mesh_info)
 +              return;
  
 -              wifi->servicing--;
 -              if (!wifi->servicing || wifi->servicing < 0) {
 -                      g_supplicant_interface_p2p_listen(wifi->interface,
 -                                                                      0, 0);
 -                      wifi->servicing = 0;
 +      mesh = connman_get_connected_mesh_from_name(name);
 +      if (!mesh) {
 +              DBG("%s is not connected", name);
 +              mesh = connman_get_connecting_mesh_from_name(name);
 +              if (!mesh) {
 +                      DBG("%s is not connecting", name);
 +                      return;
                }
        }
  
 -      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;
  
 -      wifi->connected = false;
 -      wifi->disconnecting = false;
 +      if (wifi->p2p_device)
 +              return 0;
  
 -      if (wifi->pending_network)
 -              wifi->pending_network = NULL;
 +      if (type == CONNMAN_SERVICE_TYPE_P2P)
 +              return p2p_find(device);
  
 -      stop_autoscan(device);
 +      if (wifi->tethering)
 +              return 0;
  
 -      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);
 -      }
 +      scanning =
 +              connman_device_get_scanning(device,
 +                                          CONNMAN_SERVICE_TYPE_WIFI);
 +      if (scanning)
 +              return -EALREADY;
  
 -      /* 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);
 -      }
 +      DBG("scan_type: %d", scan_type);
 +      if (scan_type == CONNMAN_MULTI_SCAN_SSID) { /* ssid based scan */
 +              scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
 +              if (!scan_params) {
 +                      DBG("Failed to allocate memory.");
 +                      return -ENOMEM;
 +              }
  
 -      remove_networks(device, wifi);
 -      remove_peers(wifi);
 +              for (list = specific_scan_list; list; list = list->next) {
 +                      ssid = (char *)list->data;
 +                      int ssid_len = strlen(ssid);
  
 -      ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL);
 -      if (ret < 0)
 -              return ret;
 +                      scan_ssid = g_try_new0(struct scan_ssid, 1);
 +                      if (!scan_ssid) {
 +                              DBG("Failed to allocate memory.");
 +                              g_supplicant_free_scan_params(scan_params);
 +                              return -ENOMEM;
 +                      }
  
 -      return -EINPROGRESS;
 -}
 +                      memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
 +                      /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
 +                      scan_ssid->ssid_len = ssid_len;
 +                      scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
 +                      count++;
 +              }
 +              scan_params->num_ssids = count;
  
 -struct last_connected {
 -      struct timeval modified;
 -      gchar *ssid;
 -      int freq;
 -};
 +      } else if (scan_type == CONNMAN_MULTI_SCAN_FREQ) { /* frequency based scan */
  
 -static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
 -{
 -      struct timeval *aval = (struct timeval *)a;
 -      struct timeval *bval = (struct timeval *)b;
 +              scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
 +              if (!scan_params) {
 +                      DBG("Failed to allocate memory.");
 +                      return -ENOMEM;
 +              }
  
 -      /* Note that the sort order is descending */
 -      if (aval->tv_sec < bval->tv_sec)
 -              return 1;
 +              guint num_freqs = g_slist_length(specific_scan_list);
 +              DBG("num_freqs: %d", num_freqs);
  
 -      if (aval->tv_sec > bval->tv_sec)
 -              return -1;
 +              scan_params->freqs = g_try_new0(uint16_t, num_freqs);
 +              if (!scan_params->freqs) {
 +                      DBG("Failed to allocate memory.");
 +                      g_free(scan_params);
 +                      return -ENOMEM;
 +              }
  
 -      return 0;
 -}
 +              count = 0;
 +              for (list = specific_scan_list; list; list = list->next) {
 +                      freq = (int)list->data;
  
 -static void free_entry(gpointer data)
 -{
 -      struct last_connected *entry = data;
 +                      scan_params->freqs[count] = freq;
 +                      DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]);
 +                      count++;
 +              }
 +              scan_params->num_freqs = count;
  
 -      g_free(entry->ssid);
 -      g_free(entry);
 +      } else if (scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ) { /* SSID & Frequency mixed scan */
 +              int freq_count, ap_count;
 +              scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
 +              if (!scan_params) {
 +                      DBG("Failed to allocate memory.");
 +                      return -ENOMEM;
 +              }
 +
 +              guint size = g_slist_length(specific_scan_list);
 +
 +              scan_params->freqs = g_try_new0(uint16_t, size/2);
 +              if (!scan_params->freqs) {
 +                      DBG("Failed to allocate memory.");
 +                      g_free(scan_params);
 +                      return -ENOMEM;
 +              }
 +
 +              ap_count = freq_count = 0;
 +              for (list = specific_scan_list; list; list = list->next) {
 +                      if (((connman_multi_scan_ap_s *)list->data)->flag == true) { /** ssid */
 +                              ssid = ((connman_multi_scan_ap_s *)list->data)->str;
 +                              int ssid_len = strlen(ssid);
 +
 +                              scan_ssid = g_try_new0(struct scan_ssid, 1);
 +                              if (!scan_ssid) {
 +                                      DBG("Failed to allocate memory.");
 +                                      g_supplicant_free_scan_params(scan_params);
 +                                      return -ENOMEM;
 +                              }
 +
 +                              memcpy(scan_ssid->ssid, ssid, (ssid_len + 1));
 +                              /* DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); */
 +                              scan_ssid->ssid_len = ssid_len;
 +                              scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
 +                              ap_count++;
 +
 +                      } else { /* freq */
 +                              freq = atoi(((connman_multi_scan_ap_s *)list->data)->str);
 +                              scan_params->freqs[freq_count] = freq;
 +                              DBG("scan_params->freqs[%d]: %d", freq_count, scan_params->freqs[freq_count]);
 +                              freq_count++;
 +                      }
 +              }
 +              scan_params->num_ssids = ap_count;
 +              scan_params->num_freqs = freq_count;
 +      } else {
 +              DBG("Invalid scan");
 +              return -EINVAL;
 +      }
 +
 +      reset_autoscan(device);
 +      connman_device_ref(device);
 +
 +      ret = g_supplicant_interface_scan(wifi->interface, scan_params,
 +                                              specific_scan_callback, device);
 +
 +      if (ret == 0) {
 +              connman_device_set_scanning(device,
 +                              CONNMAN_SERVICE_TYPE_WIFI, true);
 +      } else {
 +              g_supplicant_free_scan_params(scan_params);
 +              connman_device_unref(device);
 +      }
 +
 +      return ret;
  }
  
 -static int get_latest_connections(int max_ssids,
 -                              GSupplicantScanParams *scan_data)
 +static void wifi_mac_policy_callback(int result,
 +                                      unsigned int policy,
 +                                              void *user_data)
  {
 -      GSequenceIter *iter;
 -      GSequence *latest_list;
 -      struct last_connected *entry;
 -      GKeyFile *keyfile;
 -      struct timeval modified;
 -      gchar **services;
 -      gchar *str;
 -      char *ssid;
 -      int i, freq;
 -      int num_ssids = 0;
 -
 -      latest_list = g_sequence_new(free_entry);
 -      if (!latest_list)
 -              return -ENOMEM;
 +      struct connman_device *device = user_data;
  
 -      services = connman_storage_get_services();
 -      for (i = 0; services && services[i]; i++) {
 -              if (strncmp(services[i], "wifi_", 5) != 0)
 -                      continue;
 +      if (result == 0)
 +              connman_device_mac_policy_notify(device, result, policy);
  
 -              keyfile = connman_storage_load_service(services[i]);
 -              if (!keyfile)
 -                      continue;
 +      connman_device_unref(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);
 +int wifi_set_mac_policy(struct connman_device *device, unsigned int policy)
 +{
 +      struct wifi_data *wifi = connman_device_get_data(device);
 +      int ret;
  
 -              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);
 +      if (!wifi)
 +              return -EINVAL;
  
 -              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);
 +      connman_device_ref(device);
  
 -              ssid = g_key_file_get_string(keyfile,
 -                                      services[i], "SSID", NULL);
 +      ret = g_supplicant_interface_set_mac_policy(wifi->interface,
 +                                      wifi_mac_policy_callback,
 +                                      policy, device);
 +      if (ret != 0)
 +              connman_device_unref(device);
  
 -              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);
 -                              return -ENOMEM;
 -                      }
 +      return ret;
 +}
  
 -                      entry->ssid = ssid;
 -                      entry->modified = modified;
 -                      entry->freq = freq;
 +static void wifi_preassoc_mac_policy_callback(int result,
 +                                      unsigned int policy,
 +                                              void *user_data)
 +{
 +      struct connman_device *device = user_data;
  
 -                      g_sequence_insert_sorted(latest_list, entry,
 -                                              sort_entry, NULL);
 -                      num_ssids++;
 -              } else
 -                      g_free(ssid);
 +      if (result == 0)
 +              connman_device_preassoc_mac_policy_notify(device, result, policy);
  
 -              g_key_file_free(keyfile);
 -      }
 +      connman_device_unref(device);
 +}
  
 -      g_strfreev(services);
 +int wifi_set_preassoc_mac_policy(struct connman_device *device, unsigned int policy)
 +{
 +      struct wifi_data *wifi = connman_device_get_data(device);
 +      int ret;
  
 -      num_ssids = num_ssids > max_ssids ? max_ssids : num_ssids;
 +      if (!wifi)
 +              return -EINVAL;
  
 -      iter = g_sequence_get_begin_iter(latest_list);
 +      connman_device_ref(device);
  
 -      for (i = 0; i < num_ssids; i++) {
 -              entry = g_sequence_get(iter);
 +      ret = g_supplicant_interface_set_preassoc_mac_policy(wifi->interface,
 +                                      wifi_preassoc_mac_policy_callback,
 +                                      policy, device);
 +      if (ret != 0)
 +              connman_device_unref(device);
  
 -              DBG("ssid %s freq %d modified %lu", entry->ssid, entry->freq,
 -                                              entry->modified.tv_sec);
 +      return ret;
 +}
  
 -              add_scan_param(entry->ssid, NULL, 0, entry->freq, scan_data,
 -                                              max_ssids, entry->ssid);
 +static void wifi_random_mac_lifetime_callback(int result,
 +                                      unsigned int lifetime,
 +                                              void *user_data)
 +{
 +      struct connman_device *device = user_data;
  
 -              iter = g_sequence_iter_next(iter);
 -      }
 +      if (result == 0)
 +              connman_device_random_mac_lifetime_notify(device, result, lifetime);
  
 -      g_sequence_free(latest_list);
 -      return num_ssids;
 +      connman_device_unref(device);
  }
  
 -static void wifi_update_scanner_type(struct wifi_data *wifi,
 -                                      enum wifi_scanning_type new_type)
 +int wifi_set_random_mac_lifetime(struct connman_device *device, unsigned int lifetime)
  {
 -      DBG("");
 +      struct wifi_data *wifi = connman_device_get_data(device);
 +      int ret;
  
 -      if (!wifi || wifi->scanning_type == new_type)
 -              return;
 +      if (!wifi)
 +              return -EINVAL;
  
 -      wifi->scanning_type = new_type;
 +      connman_device_ref(device);
  
 -      setup_autoscan(wifi);
 +      ret = g_supplicant_interface_set_random_mac_lifetime(wifi->interface,
 +                                      wifi_random_mac_lifetime_callback,
 +                                      lifetime, device);
 +      if (ret != 0)
 +              connman_device_unref(device);
 +
 +      return ret;
  }
 +#endif
  
 -static int wifi_scan_simple(struct connman_device *device)
 +#if defined TIZEN_EXT_WIFI_MESH
 +static void mesh_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;
  
 -      reset_autoscan(device);
 +      DBG("result %d wifi %p", result, wifi);
  
 -      /* Distinguish between devices performing passive and active scanning */
 -      if (wifi)
 -              wifi_update_scanner_type(wifi, WIFI_SCANNING_PASSIVE);
 +      scanning = connman_device_get_scanning(device,
 +                                             CONNMAN_SERVICE_TYPE_MESH);
 +      if (scanning)
 +              connman_device_set_scanning(device,
 +                              CONNMAN_SERVICE_TYPE_MESH, false);
  
 -      return throw_wifi_scan(device, scan_callback_hidden);
 +      if (scanning)
 +              connman_device_unref(device);
  }
  
 -static gboolean p2p_find_stop(gpointer data)
 +static int mesh_scan(struct connman_device *device)
  {
 -      struct connman_device *device = data;
 -      struct wifi_data *wifi = connman_device_get_data(device);
 +      struct wifi_data *wifi;
 +      struct wifi_mesh_info *mesh_info;
 +      int ret;
  
        DBG("");
  
 -      if (wifi) {
 -              wifi->p2p_find_timeout = 0;
 +      wifi = connman_device_get_data(device);
  
 -              g_supplicant_interface_p2p_stop_find(wifi->interface);
 -      }
 +      if (!wifi || !wifi->mesh_interface)
 +              return -ENOTSUP;
  
 -      connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
 +      mesh_info = wifi->mesh_info;
 +      reset_autoscan(device);
 +      connman_device_ref(device);
  
 -      connman_device_unref(device);
 -      start_autoscan(device);
 +      ret = g_supplicant_interface_scan(mesh_info->interface, NULL,
 +                                              mesh_scan_callback, device);
 +      if (ret)
 +              connman_device_unref(device);
 +      else
 +              connman_device_set_scanning(device,
 +                              CONNMAN_SERVICE_TYPE_MESH, true);
  
 -      return FALSE;
 +      return ret;
  }
  
 -static void p2p_find_callback(int result, GSupplicantInterface *interface,
 -                                                      void *user_data)
 +static void abort_scan_callback(int result, GSupplicantInterface *interface,
 +                                              void *user_data)
  {
        struct connman_device *device = user_data;
        struct wifi_data *wifi = connman_device_get_data(device);
  
        DBG("result %d wifi %p", result, wifi);
  
 -      if (!wifi)
 -              goto error;
 +      __connman_technology_notify_abort_scan(CONNMAN_SERVICE_TYPE_MESH, result);
 +}
  
 -      if (wifi->p2p_find_timeout) {
 -              g_source_remove(wifi->p2p_find_timeout);
 -              wifi->p2p_find_timeout = 0;
 -      }
 +static int mesh_abort_scan(enum connman_service_type type,
 +                                              struct connman_device *device)
 +{
 +      struct wifi_data *wifi = connman_device_get_data(device);
 +      struct wifi_mesh_info *mesh_info;
 +      bool scanning;
 +      int ret;
  
 -      if (result)
 -              goto error;
 +      if (!wifi || !wifi->mesh_interface)
 +              return -ENODEV;
  
 -      wifi->p2p_find_timeout = g_timeout_add_seconds(P2P_FIND_TIMEOUT,
 -                                                      p2p_find_stop, device);
 -      if (!wifi->p2p_find_timeout)
 -              goto error;
 +      if (type != CONNMAN_SERVICE_TYPE_MESH)
 +              return -EINVAL;
  
 -      return;
 -error:
 -      p2p_find_stop(device);
 +      mesh_info = wifi->mesh_info;
 +
 +      scanning = connman_device_get_scanning(device,
 +                                             CONNMAN_SERVICE_TYPE_MESH);
 +      if (!scanning)
 +              return -EEXIST;
 +
 +      ret = g_supplicant_interface_abort_scan(mesh_info->interface,
 +                                              abort_scan_callback, device);
 +
 +      return ret;
  }
  
 -static int p2p_find(struct connman_device *device)
 +static int mesh_specific_scan(enum connman_service_type type,
 +                            struct connman_device *device, const char *ssid,
 +                            unsigned int freq, void *user_data)
  {
 -      struct wifi_data *wifi;
 +      struct wifi_data *wifi = connman_device_get_data(device);
 +      GSupplicantScanParams *scan_params = NULL;
 +      struct wifi_mesh_info *mesh_info;
 +      struct scan_ssid *scan_ssid;
 +      bool scanning;
        int ret;
  
 -      DBG("");
 +      if (!wifi || !wifi->mesh_interface)
 +              return -ENODEV;
  
 -      if (!p2p_technology)
 -              return -ENOTSUP;
 +      if (type != CONNMAN_SERVICE_TYPE_MESH)
 +              return -EINVAL;
  
 -      wifi = connman_device_get_data(device);
 +      if (wifi->p2p_device)
 +              return 0;
  
 -      if (g_supplicant_interface_is_p2p_finding(wifi->interface))
 +      mesh_info = wifi->mesh_info;
 +
 +      scanning = connman_device_get_scanning(device,
 +                                             CONNMAN_SERVICE_TYPE_MESH);
 +      if (scanning)
                return -EALREADY;
  
 +      scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
 +      if (!scan_params)
 +              return -ENOMEM;
 +
 +      scan_ssid = g_try_new(struct scan_ssid, 1);
 +      if (!scan_ssid) {
 +              g_free(scan_params);
 +              return -ENOMEM;
 +      }
 +
 +      scan_ssid->ssid_len = strlen(ssid);
 +      memcpy(scan_ssid->ssid, ssid, scan_ssid->ssid_len);
 +      scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid);
 +      scan_params->num_ssids = 1;
 +
 +      scan_params->freqs = g_try_new(uint16_t, 1);
 +      if (!scan_params->freqs) {
 +              g_slist_free_full(scan_params->ssids, g_free);
 +              g_free(scan_params);
 +              return -ENOMEM;
 +      }
 +
 +      scan_params->freqs[0] = freq;
 +      scan_params->num_freqs = 1;
 +
        reset_autoscan(device);
        connman_device_ref(device);
  
 -      ret = g_supplicant_interface_p2p_find(wifi->interface,
 -                                              p2p_find_callback, device);
 -      if (ret) {
 -              connman_device_unref(device);
 -              start_autoscan(device);
 -      } else {
 +      ret = g_supplicant_interface_scan(mesh_info->interface, scan_params,
 +                                              mesh_scan_callback, device);
 +
 +      if (ret == 0) {
                connman_device_set_scanning(device,
 -                              CONNMAN_SERVICE_TYPE_P2P, true);
 +                              CONNMAN_SERVICE_TYPE_MESH, true);
 +      } else {
 +              g_supplicant_free_scan_params(scan_params);
 +              connman_device_unref(device);
        }
  
        return ret;
  }
 +#endif
  
  /*
   * Note that the hidden scan is only used when connecting to this specific
@@@ -3368,11 -1917,6 +3405,11 @@@ static int wifi_scan(struct connman_dev
        if (params->type == CONNMAN_SERVICE_TYPE_P2P)
                return p2p_find(device);
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +      if (params->type == CONNMAN_SERVICE_TYPE_MESH)
 +              return mesh_scan(device);
 +#endif
 +
        DBG("device %p wifi %p hidden ssid %s", device, wifi->interface,
                params->ssid);
  
        connman_device_ref(device);
  
        reset_autoscan(device);
 -
 +#if defined TIZEN_EXT
 +      /*
 +       * When doing a full scan, stored hidden networks also need to be scanned
 +       * so that we can autoconnect to them.
 +       */
 +      if (params->force_full_scan)
 +              ret = g_supplicant_interface_scan(wifi->interface, scan_params,
 +                                                      scan_callback_hidden, device);
 +      else
 +#endif
        ret = g_supplicant_interface_scan(wifi->interface, scan_params,
                                                scan_callback, device);
        if (ret == 0) {
                connman_device_set_scanning(device,
                                CONNMAN_SERVICE_TYPE_WIFI, true);
 +#if defined TIZEN_EXT
 +              /*
 +               * To allow the Full Scan after ssid based scan, set the flag here
 +               * It is required because Tizen does not use the ConnMan specific
 +               * backgroung Scan feature.Tizen has added the BG Scan feature in
 +               * net-config. To sync with up ConnMan, we need to issue the Full Scan
 +               * after SSID specific scan.
 +               */
 +              if (!params->force_full_scan && !do_hidden)
 +                      wifi->allow_full_scan = TRUE;
 +#endif
        } else {
                g_supplicant_free_scan_params(scan_params);
                connman_device_unref(device);
@@@ -3555,16 -2079,6 +3592,16 @@@ static struct connman_device_driver wif
        .scan           = wifi_scan,
        .stop_scan      = wifi_stop_scan,
        .set_regdom     = wifi_set_regdom,
 +#if defined TIZEN_EXT
 +      .specific_scan  = wifi_specific_scan,
 +      .set_mac_policy           = wifi_set_mac_policy,
 +      .set_preassoc_mac_policy  = wifi_set_preassoc_mac_policy,
 +      .set_random_mac_lifetime  = wifi_set_random_mac_lifetime,
 +#endif
 +#if defined TIZEN_EXT_WIFI_MESH
 +      .abort_scan     = mesh_abort_scan,
 +      .mesh_specific_scan     = mesh_specific_scan,
 +#endif
  };
  
  static void system_ready(void)
@@@ -3584,9 -2098,6 +3621,9 @@@ static void system_killed(void
  
  static int network_probe(struct connman_network *network)
  {
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        DBG("network %p", network);
  
        return 0;
@@@ -3607,77 -2118,15 +3644,77 @@@ static void network_remove(struct connm
                return;
  
        wifi->network = NULL;
 +
 +#if defined TIZEN_EXT
 +      wifi->disconnecting = false;
 +
 +      if (wifi->pending_network == network)
 +              wifi->pending_network = NULL;
 +
 +      if (wifi->scan_pending_network == network)
 +              wifi->scan_pending_network = NULL;
 +#endif
  }
  
  static void connect_callback(int result, GSupplicantInterface *interface,
                                                        void *user_data)
  {
 +#if defined TIZEN_EXT
 +      GList *list;
 +      struct wifi_data *wifi;
 +#endif
        struct connman_network *network = user_data;
  
        DBG("network %p result %d", network, result);
  
 +#if defined TIZEN_EXT
 +      const char *ifname = g_supplicant_interface_get_ifname(interface);
 +      set_connman_bssid(RESET_BSSID, NULL, ifname);
 +
 +      for (list = iface_list; list; list = list->next) {
 +              wifi = list->data;
 +
 +              if (wifi && wifi->network == network)
 +                      goto found;
 +      }
 +
 +      /* wifi_data may be invalid because wifi is already disabled */
 +      return;
 +
 +found:
 +      if (connman_network_get_bool(network, "WiFi.Roaming")) {
 +              if (result < 0 ) {
 +                      connman_network_set_bool(network, "WiFi.Roaming", false);
 +                      connman_network_set_string(network,
 +                                      "WiFi.RoamingCurBSSID", NULL);
 +              } else {
 +                      char bssid_buff[WIFI_BSSID_STR_LEN] = {0,};
 +                      char *bssid_str = bssid_buff;
 +                      unsigned char *bssid;
 +                      const char *cur_bssid;
 +
 +                      bssid = g_supplicant_interface_get_add_network_bssid(interface);
 +                      if (!bssid) {
 +                              connman_network_set_bool(network, "WiFi.Roaming", false);
 +                              connman_network_set_string(network,
 +                                              "WiFi.RoamingCurBSSID", NULL);
 +                      } else {
 +                              snprintf(bssid_str,
 +                                              WIFI_BSSID_STR_LEN,
 +                                              MACSTR, MAC2STR(bssid));
 +
 +                              connman_network_set_string(network,
 +                                              "WiFi.RoamingDstBSSID", bssid_str);
 +
 +                              cur_bssid = connman_network_get_string(network,
 +                                              "WiFi.RoamingCurBSSID");
 +
 +                              __connman_technology_notify_roaming_state(ifname,
 +                                              "started", cur_bssid, bssid_str);
 +                      }
 +              }
 +      }
 +#endif
        if (result == -ENOKEY) {
                connman_network_set_error(network,
                                        CONNMAN_NETWORK_ERROR_INVALID_KEY);
@@@ -3703,65 -2152,21 +3740,65 @@@ static GSupplicantSecurity network_secu
                return G_SUPPLICANT_SECURITY_PSK;
        else if (g_str_equal(security, "ieee8021x"))
                return G_SUPPLICANT_SECURITY_IEEE8021X;
 +#if defined TIZEN_EXT
 +      else if (g_str_equal(security, "ft_psk") == TRUE)
 +              return G_SUPPLICANT_SECURITY_FT_PSK;
 +      else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
 +              return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
 +      else if (g_str_equal(security, "sae"))
 +              return G_SUPPLICANT_SECURITY_SAE;
 +      else if (g_str_equal(security, "owe"))
 +              return G_SUPPLICANT_SECURITY_OWE;
 +      else if (g_str_equal(security, "dpp"))
 +              return G_SUPPLICANT_SECURITY_DPP;
 +#endif
  
        return G_SUPPLICANT_SECURITY_UNKNOWN;
  }
  
 +#if defined TIZEN_EXT
 +static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security)
 +{
 +      if (security == NULL)
 +              return G_SUPPLICANT_EAP_KEYMGMT_NONE;
 +
 +      if (g_str_equal(security, "FT") == TRUE)
 +              return G_SUPPLICANT_EAP_KEYMGMT_FT;
 +      else if (g_str_equal(security, "CCKM") == TRUE)
 +              return G_SUPPLICANT_EAP_KEYMGMT_CCKM;
 +
 +      return G_SUPPLICANT_EAP_KEYMGMT_NONE;
 +}
 +#endif
 +
  static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
  {
        const char *security;
 +#if defined TIZEN_EXT
 +      const void *ssid_data;
 +#endif
  
        memset(ssid, 0, sizeof(*ssid));
        ssid->mode = G_SUPPLICANT_MODE_INFRA;
 +#if defined TIZEN_EXT
 +      ssid_data = connman_network_get_blob(network, "WiFi.SSID",
 +                                              &ssid->ssid_len);
 +      ssid->ssid = g_try_malloc0(ssid->ssid_len);
 +
 +      if (!ssid->ssid)
 +              ssid->ssid_len = 0;
 +      else
 +              memcpy(ssid->ssid, ssid_data, ssid->ssid_len);
 +#else
        ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
                                                &ssid->ssid_len);
 +#endif
        ssid->scan_ssid = 1;
        security = connman_network_get_string(network, "WiFi.Security");
        ssid->security = network_security(security);
 +#if defined TIZEN_EXT
 +      ssid->ieee80211w = 1;
 +#endif
        ssid->passphrase = connman_network_get_string(network,
                                                "WiFi.Passphrase");
  
  
        ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
        ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
 +#if defined TIZEN_EXT
 +      ssid->connector = connman_network_get_string(network,
 +                                                      "WiFi.Connector");
 +      ssid->c_sign_key = connman_network_get_string(network,
 +                                                      "WiFi.CSignKey");
 +      ssid->net_access_key = connman_network_get_string(network,
 +                                              "WiFi.NetAccessKey");
 +#endif
 +
 +#if defined TIZEN_EXT
 +      const char *ifname = connman_device_get_string(
 +                      connman_network_get_device(network), "Interface");
 +      if (set_connman_bssid(CHECK_BSSID, NULL, ifname) == 6) {
 +              ssid->bssid_for_connect_len = 6;
 +              set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect, ifname);
 +              DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
 +                      ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
 +                      ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
 +                      ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
 +      } else {
 +              ssid->freq = connman_network_get_frequency(network);
 +      }
 +
 +      GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
 +      if (bssid_list && g_slist_length(bssid_list) > 1) {
 +
 +              /* If there are more than one bssid,
 +               * the user-specified bssid is tried only once at the beginning.
 +               * After that, the bssids in the list are tried in order.
 +               */
 +              if (set_connman_bssid(CHECK_BSSID, NULL, ifname) == 6) {
 +                      set_connman_bssid(RESET_BSSID, NULL, ifname);
 +                      goto done;
 +              }
 +
 +              GSList *list;
 +              char buff[MAC_ADDRESS_LENGTH];
 +              for (list = bssid_list; list; list = list->next) {
 +                      struct connman_bssids * bssids = (struct connman_bssids *)list->data;
 +
 +                      g_snprintf(buff, MAC_ADDRESS_LENGTH, "%02x:%02x:%02x:%02x:%02x:%02x",
 +                                      bssids->bssid[0], bssids->bssid[1], bssids->bssid[2],
 +                                      bssids->bssid[3], bssids->bssid[4], bssids->bssid[5]);
 +                      buff[MAC_ADDRESS_LENGTH - 1] = '\0';
 +
 +                      gchar *curr_bssid = g_strdup((const gchar *)buff);
 +
 +                      if (g_hash_table_contains(failed_bssids, curr_bssid)) {
 +                              DBG("bssid match, try next bssid");
 +                              g_free(curr_bssid);
 +                              continue;
 +                      } else {
 +                              g_hash_table_add(failed_bssids, curr_bssid);
 +
 +                              memcpy(buff_bssid, bssids->bssid, WIFI_BSSID_LEN_MAX);
 +                              ssid->bssid = buff_bssid;
 +                              ssid->freq = (unsigned int)bssids->frequency;
 +                              break;
 +                      }
 +              }
 +
 +              if (!list) {
 +                      ssid->bssid = connman_network_get_bssid(network);
 +                      g_hash_table_remove_all(failed_bssids);
 +              }
 +      } else
 +              ssid->bssid = connman_network_get_bssid(network);
 +
 +done:
 +      ssid->eap_keymgmt = network_eap_keymgmt(
 +                      connman_network_get_string(network, "WiFi.KeymgmtType"));
 +      ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
 +
 +      if(g_strcmp0(ssid->eap, "fast") == 0)
 +              ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
 +
 +      ssid->keymgmt = connman_network_get_keymgmt(network);
 +#endif
  
        if (connman_setting_get_bool("BackgroundScanning"))
                ssid->bgscan = BGSCAN_DEFAULT;
@@@ -3916,16 -2243,10 +3953,16 @@@ static int network_connect(struct connm
  
        if (wifi->disconnecting) {
                wifi->pending_network = network;
 +#if defined TIZEN_EXT
 +              g_free(ssid->ssid);
 +#endif
                g_free(ssid);
        } else {
                wifi->network = connman_network_ref(network);
                wifi->retries = 0;
 +#if defined TIZEN_EXT
 +              wifi->scan_pending_network = NULL;
 +#endif
  
                return g_supplicant_interface_connect(interface, ssid,
                                                connect_callback, network);
  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);
  
        if (!wifi || !wifi->interface)
                return -ENODEV;
  
 +#if defined TIZEN_EXT
 +      if (connman_network_get_associating(network) == true) {
 +              connman_network_clear_associating(network);
 +              connman_network_set_bool(network, "WiFi.UseWPS", false);
 +      } else {
 +              service = connman_service_lookup_from_network(network);
 +
 +              if (service != NULL &&
 +                      (__connman_service_is_connected_state(service,
 +                                      CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
 +                      __connman_service_is_connected_state(service,
 +                                      CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
 +                      (connman_service_get_favorite(service) == false))
 +                                      __connman_service_set_passphrase(service, NULL);
 +      }
 +
 +      if (wifi->pending_network == network)
 +              wifi->pending_network = NULL;
 +
 +      if (wifi->scan_pending_network == network)
 +              wifi->scan_pending_network = NULL;
 +
 +#endif
        connman_network_set_associating(network, false);
  
        if (wifi->disconnecting)
  
        wifi->disconnecting = true;
  
- #if defined TIZEN_EXT
-       err = g_supplicant_interface_disconnect(wifi->interface,
-                                               disconnect_callback, network);
- #else
-       err = g_supplicant_interface_disconnect(wifi->interface,
-                                               disconnect_callback, wifi);
- #endif
+       dd = g_malloc0(sizeof(*dd));
+       dd->wifi = wifi;
+       dd->network = network;
  
-       if (err < 0)
+       err = g_supplicant_interface_disconnect(wifi->interface,
+                                               disconnect_callback, dd);
+       if (err < 0) {
                wifi->disconnecting = false;
+               g_free(dd);
+       }
  
        return err;
  }
  
 +#if defined TIZEN_EXT
 +static void set_connection_mode(struct connman_network *network,
 +              int linkspeed)
 +{
 +      ieee80211_modes_e phy_mode;
 +      connection_mode_e conn_mode;
 +
 +      phy_mode = connman_network_get_phy_mode(network);
 +      switch (phy_mode) {
 +      case IEEE80211_MODE_B:
 +              if (linkspeed > 0 && linkspeed <= 11)
 +                      conn_mode = CONNECTION_MODE_IEEE80211B;
 +              else
 +                      conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
 +
 +              break;
 +      case IEEE80211_MODE_BG:
 +              if (linkspeed > 0 && linkspeed <= 11)
 +                      conn_mode = CONNECTION_MODE_IEEE80211B;
 +              else if (linkspeed > 11 && linkspeed <= 54)
 +                      conn_mode = CONNECTION_MODE_IEEE80211G;
 +              else
 +                      conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
 +
 +              break;
 +      case IEEE80211_MODE_BGN:
 +              if (linkspeed > 0 && linkspeed <= 11)
 +                      conn_mode = CONNECTION_MODE_IEEE80211B;
 +              else if (linkspeed > 11 && linkspeed <= 54)
 +                      conn_mode = CONNECTION_MODE_IEEE80211G;
 +              else if (linkspeed > 54 && linkspeed <= 450)
 +                      conn_mode = CONNECTION_MODE_IEEE80211N;
 +              else
 +                      conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
 +
 +              break;
 +      case IEEE80211_MODE_A:
 +              if (linkspeed > 0 && linkspeed <= 54)
 +                      conn_mode = CONNECTION_MODE_IEEE80211A;
 +              else
 +                      conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
 +
 +              break;
 +      case IEEE80211_MODE_AN:
 +              if (linkspeed > 0 && linkspeed <= 54)
 +                      conn_mode = CONNECTION_MODE_IEEE80211A;
 +              else if (linkspeed > 54 && linkspeed <= 450)
 +                      conn_mode = CONNECTION_MODE_IEEE80211N;
 +              else
 +                      conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
 +
 +              break;
 +      case IEEE80211_MODE_ANAC:
 +              if (linkspeed > 0 && linkspeed <= 54)
 +                      conn_mode = CONNECTION_MODE_IEEE80211A;
 +              else if (linkspeed > 54 && linkspeed <= 450)
 +                      conn_mode = CONNECTION_MODE_IEEE80211N;
 +              else if (linkspeed > 450 && linkspeed <= 1300)
 +                      conn_mode = CONNECTION_MODE_IEEE80211AC;
 +              else
 +                      conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
 +
 +              break;
 +      default:
 +                      conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
 +              break;
 +      }
 +
 +      DBG("connection mode(%d)", conn_mode);
 +      connman_network_set_connection_mode(network, conn_mode);
 +}
 +
 +static void signalpoll_callback(int result, int maxspeed, int strength,
 +                              int snr, void *user_data)
 +{
 +      char bssid_buff[WIFI_BSSID_STR_LEN] = {0,};
 +      char *bssid_str = bssid_buff;
 +      unsigned char *bssid;
 +      struct timespec curr_time = {0};
 +      __time_t roam_scan_time;
 +      const char *interface = NULL;
 +      struct connman_device *device;
 +      struct connman_network *network = user_data;
 +      uint16_t freq = connman_network_get_frequency(network);
 +
 +      if (result != 0) {
 +              DBG("Failed to get maxspeed from signalpoll !");
 +              connman_network_unref(network);
 +              return;
 +      }
 +
 +      strength += 120;
 +      if (strength > 100)
 +              strength = 100;
 +
 +      DBG("freq = %u, maxspeed = %d, strength = %d, snr = %d", freq, maxspeed, strength, snr);
 +
 +      connman_network_set_strength(network, (uint8_t)strength);
 +      connman_network_set_snr(network, snr);
 +      connman_network_set_maxspeed(network, maxspeed);
 +      set_connection_mode(network, maxspeed);
 +
 +      clock_gettime(CLOCK_MONOTONIC, &curr_time);
 +      roam_scan_time = connman_network_get_roam_scan_time(network);
 +      if (curr_time.tv_sec <= roam_scan_time + ROAM_SCAN_INTERVAL)
 +              goto done;
 +
 +      if (need_bss_transition(freq, snr, strength)) {
 +              device = connman_network_get_device(network);
 +              if (!device)
 +                      goto done;
 +
 +              interface = connman_device_get_string(device, "Interface");
 +              bssid = connman_network_get_bssid(network);
 +              snprintf(bssid_str, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bssid));
 +              __connman_technology_notify_roaming_state(interface, "required", bssid_str, NULL);
 +
 +              if (connman_setting_get_bool("WifiRoamingScan") == false)
 +                      goto done;
 +
 +              throw_wifi_scan(device, scan_callback);
 +              connman_network_set_roam_scan_time(network, curr_time.tv_sec);
 +      }
 +
 +done:
 +      connman_network_unref(network);
 +}
 +
 +static int network_signalpoll(struct wifi_data *wifi)
 +{
 +      GSupplicantInterface *interface;
 +      struct connman_network *network;
 +
 +      if (!wifi || !wifi->network)
 +              return -ENODEV;
 +
 +      wifi->network = connman_network_ref(wifi->network);
 +
 +      interface = wifi->interface;
 +      network = wifi->network;
 +
 +      DBG("network %p", network);
 +
 +      return g_supplicant_interface_signalpoll(interface, signalpoll_callback, network);
 +}
 +
 +static gboolean autosignalpoll_timeout(gpointer data)
 +{
 +      struct wifi_data *wifi = data;
 +
 +      if (!wifi || !wifi->automaxspeed_timeout) {
 +              DBG("automaxspeed_timeout is found to be zero. i.e. currently in disconnected state. !!");
 +              return FALSE;
 +      }
 +
 +      int ret = network_signalpoll(wifi);
 +      if (ret < 0) {
 +              DBG("Fail to get max speed !!");
 +              wifi->automaxspeed_timeout = 0;
 +
 +              if (wifi->network)
 +                      connman_network_unref(wifi->network);
 +
 +              return FALSE;
 +      }
 +
 +      return TRUE;
 +}
 +#endif
 +
  static struct connman_network_driver network_driver = {
        .name           = "wifi",
        .type           = CONNMAN_NETWORK_TYPE_WIFI,
@@@ -4234,19 -2345,6 +4285,19 @@@ static void interface_added(GSupplicant
  {
        const char *ifname = g_supplicant_interface_get_ifname(interface);
        const char *driver = g_supplicant_interface_get_driver(interface);
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      /*
 +       * Note: If supplicant interface's driver is wired then skip it,
 +       * because it meanti only for ethernet not Wi-Fi.
 +       */
 +      if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
 +              return;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
 +#if defined TIZEN_EXT
 +      bool is_5_0_ghz_supported = g_supplicant_interface_get_is_5_0_ghz_supported(interface);
 +#endif
 +
        struct wifi_data *wifi;
  
        wifi = g_supplicant_interface_get_data(interface);
        }
  
        connman_device_set_powered(wifi->device, true);
 +#if defined TIZEN_EXT
 +      connman_device_set_wifi_5ghz_supported(wifi->device, is_5_0_ghz_supported);
 +      /* Max number of SSIDs supported by wlan chipset that can be scanned */
 +      int max_scan_ssids = g_supplicant_interface_get_max_scan_ssids(interface);
 +      connman_device_set_max_scan_ssids(wifi->device, max_scan_ssids);
 +#endif
  }
  
  static bool is_idle(struct wifi_data *wifi)
@@@ -4342,6 -2434,7 +4393,7 @@@ static bool handle_wps_completion(GSupp
        if (wps) {
                const unsigned char *ssid, *wps_ssid;
                unsigned int ssid_len, wps_ssid_len;
+               struct disconnect_data *dd;
                const char *wps_key;
  
                /* Checking if we got associated with requested
  
                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;
                }
  
                wps_key = g_supplicant_interface_get_wps_key(interface);
 +#if defined TIZEN_EXT
 +              /* Check the passphrase and encrypt it
 +               */
 +               int ret;
 +               gchar *passphrase = g_strdup(wps_key);
 +
 +               connman_network_set_string(network, "WiFi.PinWPS", NULL);
 +
 +               if (check_passphrase_ext(network, passphrase) < 0) {
 +                       DBG("[WPS] Invalid passphrase");
 +                       g_free(passphrase);
 +                       return true;
 +               }
 +
 +               ret = send_encryption_request(passphrase, network);
 +
 +               g_free(passphrase);
 +
 +               if (!ret)
 +                       DBG("[WPS] Encryption request succeeded");
 +               else
 +                       DBG("[WPS] Encryption request failed %d", ret);
 +
 +#else
                connman_network_set_string(network, "WiFi.Passphrase",
                                        wps_key);
  
                connman_network_set_string(network, "WiFi.PinWPS", NULL);
 +#endif
        }
  
        return true;
@@@ -4407,11 -2471,7 +4459,11 @@@ static bool handle_assoc_status_code(GS
                                       struct wifi_data *wifi)
  {
        if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING &&
 +#if defined TIZEN_EXT
 +                      wifi->assoc_code > 0 &&
 +#else
                        wifi->assoc_code == ASSOC_STATUS_NO_CLIENT &&
 +#endif
                        wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) {
                wifi->load_shaping_retries ++;
                return TRUE;
@@@ -4424,34 -2484,15 +4476,34 @@@ 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)
                return false;
 +#endif
  
        service = connman_service_lookup_from_network(network);
        if (!service)
        return false;
  }
  
 +#if defined TIZEN_EXT
 +static bool handle_wifi_assoc_retry(struct connman_network *network,
 +                                      struct wifi_data *wifi)
 +{
 +      const char *security;
 +
 +      if (!wifi->network || wifi->connected || wifi->disconnecting ||
 +                      connman_network_get_connecting(network) != true) {
 +              wifi->assoc_retry_count = 0;
 +              return false;
 +      }
 +
 +      if (wifi->state != G_SUPPLICANT_STATE_AUTHENTICATING &&
 +                      wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
 +                      wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
 +              wifi->assoc_retry_count = 0;
 +              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->assoc_retry_count = 0;
 +              return false;
 +      }
 +
 +      if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
 +              wifi->assoc_retry_count = 0;
 +
 +              /* Honestly it's not an invalid-key error,
 +               * however QA team recommends that the invalid-key error
 +               * might be better to display for user experience.
 +               */
 +              switch (wifi->state) {
 +              case G_SUPPLICANT_STATE_AUTHENTICATING:
 +                      connman_network_set_error(network, CONNMAN_NETWORK_ERROR_AUTHENTICATE_FAIL);
 +                      break;
 +              case G_SUPPLICANT_STATE_ASSOCIATED:
 +                      connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
 +                      break;
 +              default:
 +                      connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
 +                      break;
 +              }
 +
 +              return false;
 +      }
 +
 +      return true;
 +}
 +#endif
 +
  static void interface_state(GSupplicantInterface *interface)
  {
        struct connman_network *network;
        struct connman_device *device;
        struct wifi_data *wifi;
        GSupplicantState state = g_supplicant_interface_get_state(interface);
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      /*
 +       * Note: If supplicant interface's driver is wired then skip it,
 +       * because it meanti only for ethernet not Wi-Fi.
 +       */
 +      if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
 +              return;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
        bool wps;
        bool old_connected;
  
  
        switch (state) {
        case G_SUPPLICANT_STATE_SCANNING:
 +#if defined TIZEN_EXT
 +              if (wifi->automaxspeed_timeout != 0) {
 +                      g_source_remove(wifi->automaxspeed_timeout);
 +                      wifi->automaxspeed_timeout = 0;
 +                      DBG("Remove signalpoll timer!!");
 +              }
 +#endif
                if (wifi->connected)
                        connman_network_set_connected(network, false);
  
  
        case G_SUPPLICANT_STATE_AUTHENTICATING:
        case G_SUPPLICANT_STATE_ASSOCIATING:
 +#if defined TIZEN_EXT
 +              reset_autoscan(device);
 +#else
                stop_autoscan(device);
 +#endif
  
                if (!wifi->connected)
                        connman_network_set_associating(network, true);
                break;
  
        case G_SUPPLICANT_STATE_COMPLETED:
 +#if defined TIZEN_EXT
 +              /* though it should be already reset: */
 +              reset_autoscan(device);
 +
 +              wifi->assoc_retry_count = 0;
 +
 +              wifi->scan_pending_network = NULL;
 +
 +              /* should be cleared scanning flag */
 +              bool 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);
 +              }
 +
 +              if (!wifi->automaxspeed_timeout) {
 +                      DBG("Going to start signalpoll timer!!");
 +                      int ret = network_signalpoll(wifi);
 +                      if (ret < 0)
 +                              DBG("Fail to get max speed !!");
 +                      else
 +                              wifi->automaxspeed_timeout = g_timeout_add_seconds(10, autosignalpoll_timeout, wifi);
 +              }
 +
 +              g_hash_table_remove_all(failed_bssids);
 +#else
                /* though it should be already stopped: */
                stop_autoscan(device);
 +#endif
  
                if (!handle_wps_completion(interface, network, device, wifi))
                        break;
                break;
  
        case G_SUPPLICANT_STATE_DISCONNECTED:
 +#if defined TIZEN_EXT
 +              connman_network_set_strength(network, 0);
 +              connman_network_set_maxspeed(network, 0);
 +
 +              if (wifi->automaxspeed_timeout != 0) {
 +                      g_source_remove(wifi->automaxspeed_timeout);
 +                      wifi->automaxspeed_timeout = 0;
 +                      DBG("Remove signalpoll timer!!");
 +              }
 +#endif
                /*
                 * If we're in one of the idle modes, we have
                 * not started association yet and thus setting
                if (is_idle(wifi))
                        break;
  
 +#if defined TIZEN_EXT
 +              if (handle_assoc_status_code(interface, wifi)) {
 +                      const char *group = connman_network_get_group(network);
 +                      GSupplicantNetwork *supplicant_network;
 +                      GSList *bssid_list = NULL;
 +                      guint bssid_length = 0;
 +
 +                      if (group) {
 +                              supplicant_network = g_supplicant_interface_get_network(interface, group);
 +
 +                              connman_network_set_assoc_reject_table(network,
 +                                      g_supplicant_network_get_assoc_reject_table(supplicant_network));
 +
 +                              g_supplicant_network_update_assoc_reject(interface, supplicant_network);
 +                      }
 +
 +                      bssid_list = (GSList *)connman_network_get_bssid_list(network);
 +                      if (bssid_list)
 +                              bssid_length = g_slist_length(bssid_list);
 +
 +                      if (bssid_length > 1 && bssid_length > g_hash_table_size(failed_bssids)) {
 +                              network_connect(network);
 +                              break;
 +                      }
 +
 +                      wifi->load_shaping_retries = 0;
 +              }
 +
 +              g_hash_table_remove_all(failed_bssids);
 +#else
                if (handle_assoc_status_code(interface, wifi))
                        break;
 +#endif
  
                /* If previous state was 4way-handshake, then
                 * it's either: psk was incorrect and thus we retry
  
                /* 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);
                        break;
                }
  
 +#if defined TIZEN_EXT
 +              /* Some of Wi-Fi networks are not comply Wi-Fi specification.
 +               * Retry association until its retry count is expired */
 +              if (handle_wifi_assoc_retry(network, wifi) == true) {
 +                      throw_wifi_scan(wifi->device, scan_callback);
 +                      wifi->scan_pending_network = wifi->network;
 +                      break;
 +              }
 +
 +              if(wifi->disconnect_code > 0){
 +                      DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
 +                      connman_network_set_disconnect_reason(network, wifi->disconnect_code);
 +              }
 +#endif
 +
                if (network != wifi->pending_network) {
                        connman_network_set_connected(network, false);
                        connman_network_set_associating(network, false);
                break;
  
        case G_SUPPLICANT_STATE_INACTIVE:
 +#if defined TIZEN_EXT
 +              if (handle_wps_completion(interface, network, device, wifi) == false)
 +                      break;
 +#endif
                connman_network_set_associating(network, false);
                start_autoscan(device);
  
@@@ -4808,35 -2685,11 +4861,35 @@@ static void interface_removed(GSupplica
  {
        const char *ifname = g_supplicant_interface_get_ifname(interface);
        struct wifi_data *wifi;
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      /*
 +       * Note: If supplicant interface's driver is wired then skip it,
 +       * because it meanti only for ethernet not Wi-Fi.
 +       */
 +      if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
 +              return;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
  
        DBG("ifname %s", ifname);
  
        wifi = g_supplicant_interface_get_data(interface);
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +      if (wifi && wifi->mesh_interface) {
 +              DBG("Notify mesh interface remove");
 +              connman_mesh_notify_interface_remove(true);
 +              struct wifi_mesh_info *mesh_info = wifi->mesh_info;
 +              g_free(mesh_info->parent_ifname);
 +              g_free(mesh_info->ifname);
 +              g_free(mesh_info->identifier);
 +              g_free(mesh_info);
 +              wifi->mesh_interface = false;
 +              wifi->mesh_info = NULL;
 +              return;
 +      }
 +#endif
 +
        if (wifi)
                wifi->interface = NULL;
  
        connman_device_set_powered(wifi->device, false);
  
        check_p2p_technology();
 +#if defined TIZEN_EXT_WIFI_MESH
 +      check_mesh_technology();
 +#endif
  }
  
  static void set_device_type(const char *type, char dev_type[17])
@@@ -4885,15 -2735,6 +4938,15 @@@ static void p2p_support(GSupplicantInte
  {
        char dev_type[17] = {};
        const char *hostname;
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      /*
 +       * Note: If supplicant interface's driver is wired then skip it,
 +       * because it meanti only for ethernet not Wi-Fi.
 +       */
 +      if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
 +              return;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
  
        DBG("");
  
  
  static void scan_started(GSupplicantInterface *interface)
  {
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      /*
 +       * Note: If supplicant interface's driver is wired then skip it,
 +       * because it meanti only for ethernet not Wi-Fi.
 +       */
 +      if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
 +              return;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
        DBG("");
  }
  
  static void scan_finished(GSupplicantInterface *interface)
  {
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      /*
 +       * Note: If supplicant interface's driver is wired then skip it,
 +       * because it meanti only for ethernet not Wi-Fi.
 +       */
 +      if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
 +              return;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
 +#if defined TIZEN_EXT
 +      struct wifi_data *wifi;
 +      bool is_associating = false;
 +      static bool is_scanning = true;
 +#endif
 +
        DBG("");
 +
 +#if defined TIZEN_EXT
 +      wifi = g_supplicant_interface_get_data(interface);
 +      if (wifi && wifi->scan_pending_network) {
 +              network_connect(wifi->scan_pending_network);
 +              wifi->scan_pending_network = NULL;
 +      }
 +
 +      //service state - associating
 +      if(!wifi || !wifi->network)
 +              return;
 +
 +      is_associating = connman_network_get_associating(wifi->network);
 +      if(is_associating && is_scanning){
 +              is_scanning = false;
 +              DBG("send scan for connecting");
 +              throw_wifi_scan(wifi->device, scan_callback);
 +
 +              return;
 +      }
 +      is_scanning = true;
 +
 +      //go scan
 +
 +#endif
  }
  
  static void ap_create_fail(GSupplicantInterface *interface)
  {
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      /*
 +       * Note: If supplicant interface's driver is wired then skip it,
 +       * because it meanti only for ethernet not Wi-Fi.
 +       */
 +      if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
 +              return;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
        struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
        int ret;
  
@@@ -5019,158 -2802,12 +5072,158 @@@ static unsigned char calculate_strength
        unsigned char strength;
  
        strength = 120 + g_supplicant_network_get_signal(supplicant_network);
 +#if !defined TIZEN_EXT
        if (strength > 100)
                strength = 100;
 +#endif
  
        return strength;
  }
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
 +{
 +      GSupplicantInterface *interface;
 +      struct wifi_data *wifi;
 +      const char *name, *security;
 +      struct connman_mesh *connman_mesh;
 +      struct wifi_mesh_info *mesh_info;
 +      const unsigned char *bssid;
 +      const char *identifier;
 +      char *address;
 +      uint16_t frequency;
 +      int ret;
 +
 +      interface = g_supplicant_network_get_interface(supplicant_network);
 +      wifi = g_supplicant_interface_get_data(interface);
 +      if (!wifi || !wifi->mesh_interface) {
 +              DBG("Virtual Mesh interface not created");
 +              return;
 +      }
 +
 +      bssid = g_supplicant_network_get_bssid(supplicant_network);
 +      address = g_malloc0(19);
 +      snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
 +                                                               bssid[2], bssid[3], bssid[4], bssid[5]);
 +
 +      identifier = g_supplicant_network_get_identifier(supplicant_network);
 +      name = g_supplicant_network_get_name(supplicant_network);
 +      security = g_supplicant_network_get_security(supplicant_network);
 +      frequency = g_supplicant_network_get_frequency(supplicant_network);
 +
 +      mesh_info = wifi->mesh_info;
 +      connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
 +      if (connman_mesh)
 +              goto done;
 +
 +      DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
 +                                      security);
 +      connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
 +      connman_mesh_set_name(connman_mesh, name);
 +      connman_mesh_set_security(connman_mesh, security);
 +      connman_mesh_set_frequency(connman_mesh, frequency);
 +      connman_mesh_set_address(connman_mesh, address);
 +      connman_mesh_set_index(connman_mesh, mesh_info->index);
 +      connman_mesh_set_strength(connman_mesh,
 +                                              calculate_strength(supplicant_network));
 +      connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
 +
 +      ret = connman_mesh_register(connman_mesh);
 +      if (ret == -EALREADY)
 +              DBG("Mesh Peer is already registered");
 +
 +done:
 +      g_free(address);
 +}
 +
 +static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
 +{
 +      GSupplicantInterface *interface;
 +      struct wifi_data *wifi;
 +      struct connman_mesh *connman_mesh;
 +      struct wifi_mesh_info *mesh_info;
 +      const char *identifier;
 +
 +      interface = g_supplicant_network_get_interface(supplicant_network);
 +      wifi = g_supplicant_interface_get_data(interface);
 +      if (!wifi || !wifi->mesh_interface) {
 +              DBG("Virtual Mesh interface not created");
 +              return;
 +      }
 +
 +      identifier = g_supplicant_network_get_identifier(supplicant_network);
 +      if (!identifier) {
 +              DBG("Failed to get Mesh Peer identifier");
 +              return;
 +      }
 +
 +      mesh_info = wifi->mesh_info;
 +      connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
 +      if (connman_mesh) {
 +              /* Do not unregister connected mesh peer */
 +              if (connman_mesh_peer_is_connected_state(connman_mesh)) {
 +                      DBG("Mesh Peer %s is connected", identifier);
 +                      return;
 +              }
 +              DBG("Mesh Peer identifier %s removed", identifier);
 +              connman_mesh_unregister(connman_mesh);
 +      }
 +}
 +#endif
 +
 +
 +#if defined TIZEN_EXT
 +static GSList *get_supported_security_list(unsigned int keymgmt,
 +                                      bool owe_transition_mode,
 +                                      GSupplicantNetwork *supplicant_network)
 +{
 +      GSList *sec_list = NULL;
 +      dbus_bool_t privacy = g_supplicant_network_get_privacy(supplicant_network);
 +      const char *enc_mode = g_supplicant_network_get_enc_mode(supplicant_network);
 +
 +      if (keymgmt &
 +                      (G_SUPPLICANT_KEYMGMT_WPA_EAP |
 +                                      G_SUPPLICANT_KEYMGMT_WPA_EAP_256))
 +              sec_list = g_slist_prepend (sec_list, "ieee8021x");
 +      else if (keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_EAP)
 +              sec_list = g_slist_prepend (sec_list, "ft_ieee8021x");
 +
 +      if (sec_list)
 +              return sec_list;
 +
 +      if (keymgmt &
 +                      (G_SUPPLICANT_KEYMGMT_WPA_PSK |
 +                                      G_SUPPLICANT_KEYMGMT_WPA_PSK_256)) {
 +              if (!g_strcmp0(enc_mode, "aes"))
 +                      sec_list = g_slist_prepend (sec_list, "rsn");
 +              else if (!g_strcmp0(enc_mode, "tkip"))
 +                      sec_list = g_slist_prepend (sec_list, "psk");
 +              else if (!g_strcmp0(enc_mode, "mixed")) {
 +                      sec_list = g_slist_prepend (sec_list, "psk");
 +                      sec_list = g_slist_prepend (sec_list, "rsn");
 +              }
 +      } else if (keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_PSK)
 +              sec_list = g_slist_prepend (sec_list, "ft_psk");
 +
 +      if (keymgmt & G_SUPPLICANT_KEYMGMT_SAE)
 +              sec_list = g_slist_prepend (sec_list, "sae");
 +      if (keymgmt & G_SUPPLICANT_KEYMGMT_OWE || owe_transition_mode)
 +              sec_list = g_slist_prepend (sec_list, "owe");
 +      if (keymgmt & G_SUPPLICANT_KEYMGMT_DPP)
 +              sec_list = g_slist_prepend (sec_list, "dpp");
 +
 +      if (sec_list)
 +              return sec_list;
 +
 +      if (privacy)
 +              sec_list = g_slist_prepend (sec_list, "wep");
 +      else
 +              sec_list = g_slist_prepend (sec_list, "none");
 +
 +      return sec_list;
 +}
 +#endif
 +
  static void network_added(GSupplicantNetwork *supplicant_network)
  {
        struct connman_network *network;
        bool wps_ready;
        bool wps_advertizing;
  
 +#if defined TIZEN_EXT
 +      bool owe_transition_mode;
 +      const unsigned char *transition_mode_ssid;
 +      const unsigned char *transition_mode_bssid;
 +      unsigned int transition_mode_ssid_len;
 +      unsigned int keymgmt;
 +      GSList *vsie_list = NULL;
 +      GSList *sec_list = NULL;
 +      const unsigned char *country_code;
 +      ieee80211_modes_e phy_mode;
 +#endif
 +
        mode = g_supplicant_network_get_mode(supplicant_network);
        identifier = g_supplicant_network_get_identifier(supplicant_network);
 -
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        DBG("%s", identifier);
  
        if (!g_strcmp0(mode, "adhoc"))
                return;
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +      if (!g_strcmp0(mode, "mesh")) {
 +              mesh_peer_added(supplicant_network);
 +              return;
 +      }
 +#endif
 +
        interface = g_supplicant_network_get_interface(supplicant_network);
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      /*
 +       * Note: If supplicant interface's driver is wired then skip it,
 +       * because it meanti only for ethernet not Wi-Fi.
 +       */
 +      if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
 +              return;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
        wifi = g_supplicant_interface_get_data(interface);
        name = g_supplicant_network_get_name(supplicant_network);
        security = g_supplicant_network_get_security(supplicant_network);
  
        connman_network_set_blob(network, "WiFi.SSID",
                                                ssid, ssid_len);
 +#if defined TIZEN_EXT
 +      vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
 +      if (vsie_list)
 +              connman_network_set_vsie_list(network, vsie_list);
 +      else
 +              DBG("vsie_list is NULL");
 +      country_code = g_supplicant_network_get_countrycode(supplicant_network);
 +      connman_network_set_countrycode(network, country_code);
 +      phy_mode = g_supplicant_network_get_phy_mode(supplicant_network);
 +      connman_network_set_phy_mode(network, phy_mode);
 +#endif
        connman_network_set_string(network, "WiFi.Security", security);
        connman_network_set_strength(network,
                                calculate_strength(supplicant_network));
                 * If so, we decide to use WPS by default */
                if (wps_ready && wps_pbc &&
                                                wps_advertizing)
 +#if !defined TIZEN_EXT
                        connman_network_set_bool(network, "WiFi.UseWPS", true);
 +#else
 +                      DBG("wps is activating by ap but ignore it.");
 +#endif
        }
  
        connman_network_set_frequency(network,
                        g_supplicant_network_get_frequency(supplicant_network));
  
 +#if defined TIZEN_EXT
 +      keymgmt = g_supplicant_network_get_keymgmt(supplicant_network);
 +      connman_network_set_bssid(network,
 +                      g_supplicant_network_get_bssid(supplicant_network));
 +      owe_transition_mode = (bool)g_supplicant_network_get_transition_mode(supplicant_network);
 +      connman_network_set_bool(network, "WiFi.TRANSITION_MODE", owe_transition_mode);
 +      if (owe_transition_mode) {
 +              transition_mode_ssid = (unsigned char *)g_supplicant_network_get_transition_mode_ssid(supplicant_network, &transition_mode_ssid_len);
 +              connman_network_set_blob(network, "WiFi.TRANSITION_MODE_SSID",
 +                                                      transition_mode_ssid, transition_mode_ssid_len);
 +              transition_mode_bssid = g_supplicant_network_get_transition_mode_bssid(supplicant_network);
 +              connman_network_set_transition_mode_bssid(network, transition_mode_bssid);
 +      }
 +
 +      sec_list = get_supported_security_list(keymgmt,
 +                      owe_transition_mode, supplicant_network);
 +
 +      connman_network_set_sec_list(network, sec_list);
 +      connman_network_set_maxrate(network,
 +                      g_supplicant_network_get_maxrate(supplicant_network));
 +      connman_network_set_enc_mode(network,
 +                      g_supplicant_network_get_enc_mode(supplicant_network));
 +      connman_network_set_rsn_mode(network,
 +                      g_supplicant_network_get_rsn_mode(supplicant_network));
 +      connman_network_set_bool(network, "WiFi.PMFRequired",
 +                      (bool)g_supplicant_network_is_pmf_required(supplicant_network));
 +      connman_network_set_keymgmt(network, keymgmt);
 +      connman_network_set_bool(network, "WiFi.HS20AP",
 +                      g_supplicant_network_is_hs20AP(supplicant_network));
 +      connman_network_set_bssid_list(network,
 +                      (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
 +      connman_network_set_last_connected_bssid(network,
 +                      g_supplicant_network_get_last_connected_bssid(supplicant_network));
 +      connman_network_set_assoc_reject_table(network,
 +                      g_supplicant_network_get_assoc_reject_table(supplicant_network));
 +#endif
        connman_network_set_available(network, true);
        connman_network_set_string(network, "WiFi.Mode", mode);
  
 +#if defined TIZEN_EXT
 +      if (group)
 +#else
        if (ssid)
 +#endif
                connman_network_set_group(network, group);
  
 +#if defined TIZEN_EXT
 +      g_supplicant_network_set_last_connected_bssid(supplicant_network,
 +                      connman_network_get_last_connected_bssid(network));
 +#endif
 +
 +#if defined TIZEN_EXT
 +      if (wifi_first_scan == true)
 +              found_with_first_scan = true;
 +#endif
 +
        if (wifi->hidden && ssid) {
 +#if defined TIZEN_EXT
 +              if (network_security(wifi->hidden->security) ==
 +                      network_security(security) &&
 +#else
                if (!g_strcmp0(wifi->hidden->security, security) &&
 +#endif
                                wifi->hidden->ssid_len == ssid_len &&
                                !memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
                        connman_network_connect_hidden(network,
@@@ -5377,25 -2914,7 +5430,25 @@@ static void network_removed(GSupplicant
        const char *name, *identifier;
        struct connman_network *connman_network;
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +      const char *mode;
 +      mode = g_supplicant_network_get_mode(network);
 +      if (!g_strcmp0(mode, "mesh")) {
 +              mesh_peer_removed(network);
 +              return;
 +      }
 +#endif
 +
        interface = g_supplicant_network_get_interface(network);
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      /*
 +       * Note: If supplicant interface's driver is wired then skip it,
 +       * because it meanti only for ethernet not Wi-Fi.
 +       */
 +      if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
 +              return;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
        wifi = g_supplicant_interface_get_data(interface);
        identifier = g_supplicant_network_get_identifier(network);
        name = g_supplicant_network_get_name(network);
        if (!connman_network)
                return;
  
 +#if defined TIZEN_EXT
 +      if (connman_network == wifi->scan_pending_network)
 +              wifi->scan_pending_network = NULL;
 +
 +      if (connman_network == wifi->pending_network)
 +              wifi->pending_network = NULL;
 +
 +      if(connman_network_get_connecting(connman_network) == true){
 +              connman_network_set_connected(connman_network, false);
 +      }
 +#endif
 +
        wifi->networks = g_slist_remove(wifi->networks, connman_network);
  
        connman_device_remove_network(wifi->device, connman_network);
@@@ -5435,36 -2942,12 +5488,36 @@@ static void network_changed(GSupplicant
        struct connman_network *connman_network;
        bool update_needed;
  
 +#if defined TIZEN_EXT
 +      const unsigned char *bssid;
 +      unsigned int maxrate;
 +      uint16_t frequency;
 +      bool wps;
 +      const unsigned char *country_code;
 +      ieee80211_modes_e phy_mode;
 +      GSList *bssid_list;
 +#endif
 +
        interface = g_supplicant_network_get_interface(network);
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      /*
 +       * Note: If supplicant interface's driver is wired then skip it,
 +       * because it meanti only for ethernet not Wi-Fi.
 +       */
 +      if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
 +              return;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
        wifi = g_supplicant_interface_get_data(interface);
        identifier = g_supplicant_network_get_identifier(network);
        name = g_supplicant_network_get_name(network);
  
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +              DBG("name %s property %s", name, property);
 +#else
        DBG("name %s", name);
 +#endif
  
        if (!wifi)
                return;
                connman_network_set_strength(connman_network,
                                        calculate_strength(network));
                update_needed = true;
 -      } else
 +      }
 +#if defined TIZEN_EXT && defined TIZEN_EXT_INS
 +      else if (g_str_equal(property, "LastConnectedBSSID")) {
 +              const char *ident, *group;
 +              char *service_ident;
 +              bool need_save;
 +
 +              ident = connman_device_get_ident(wifi->device);
 +              group = connman_network_get_group(connman_network);
 +              if (ident && group) {
 +                      service_ident = g_strdup_printf("%s_%s_%s",
 +                              __connman_network_get_type(connman_network), ident, group);
 +
 +                      need_save = connman_device_set_last_connected_ident(wifi->device, service_ident);
 +                      if (need_save)
 +                              connman_device_save_last_connected(wifi->device);
 +
 +                      g_free(service_ident);
 +              }
 +
 +              connman_network_set_last_connected_bssid(connman_network,
 +                                      g_supplicant_network_get_last_connected_bssid(network));
 +
 +              update_needed = true;
 +      }
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
 +#if defined TIZEN_EXT
 +      else if (g_str_equal(property, "UpdateAssocReject")) {
 +              connman_network_set_assoc_reject_table(connman_network,
 +                                      g_supplicant_network_get_assoc_reject_table(network));
 +              update_needed = true;
 +      }
 +#endif
 +      else
                update_needed = false;
  
        if (update_needed)
                connman_network_update(connman_network);
 +
 +#if defined TIZEN_EXT
 +      bssid = g_supplicant_network_get_bssid(network);
 +      maxrate = g_supplicant_network_get_maxrate(network);
 +      frequency = g_supplicant_network_get_frequency(network);
 +      wps = g_supplicant_network_get_wps(network);
 +      phy_mode = g_supplicant_network_get_phy_mode(network);
 +
 +      connman_network_set_bssid(connman_network, bssid);
 +      connman_network_set_maxrate(connman_network, maxrate);
 +      connman_network_set_frequency(connman_network, frequency);
 +      connman_network_set_bool(connman_network, "WiFi.WPS", wps);
 +      country_code = g_supplicant_network_get_countrycode(network);
 +      connman_network_set_countrycode(connman_network, country_code);
 +      bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
 +      connman_network_set_bssid_list(connman_network, bssid_list);
 +      connman_network_set_phy_mode(connman_network, phy_mode);
 +
 +      if (g_str_equal(property, "CheckMultiBssidConnect") &&
 +                      connman_network_get_associating(connman_network))
 +              network_connect(connman_network);
 +#endif
  }
  
  static void network_associated(GSupplicantNetwork *network)
        interface = g_supplicant_network_get_interface(network);
        if (!interface)
                return;
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      /*
 +       * Note: If supplicant interface's driver is wired then skip it,
 +       * because it meanti only for ethernet not Wi-Fi.
 +       */
 +      if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
 +              return;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
  
        wifi = g_supplicant_interface_get_data(interface);
        if (!wifi)
        if (wifi->network) {
                if (wifi->network == connman_network)
                        return;
 -
 +#if TIZEN_EXT
 +              unsigned int ssid_len;
 +              DBG("network1 ssid[%s] , OWE[%d],ssid[%s]",
 +                      (char *)connman_network_get_blob(wifi->network,"WiFi.SSID", &ssid_len),
 +                      connman_network_get_bool(wifi->network,"WiFi.TRANSITION_MODE"),
 +                      (char *)connman_network_get_blob(wifi->network,"WiFi.TRANSITION_MODE_SSID", &ssid_len));
 +
 +              DBG("network1 ssid[%s], OWE[%d], ssid[%s]",
 +                      (char *)connman_network_get_blob(connman_network,"WiFi.SSID",&ssid_len),
 +                      connman_network_get_bool(connman_network,"WiFi.TRANSITION_MODE"),
 +                      (char *)connman_network_get_blob(connman_network,"WiFi.TRANSITION_MODE_SSID", &ssid_len));
 +              if (connman_network_check_transition_mode(wifi->network, connman_network)) {//OWE trasition mode check
 +                      DBG("OWE transition mode is TRUE");
 +                      return;
 +              }
 +#endif
                /*
                 * This should never happen, we got associated with
                 * a network different than the one we were expecting.
  static void sta_authorized(GSupplicantInterface *interface,
                                        const char *addr)
  {
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      /*
 +       * Note: If supplicant interface's driver is wired then skip it,
 +       * because it meanti only for ethernet not Wi-Fi.
 +       */
 +      if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
 +              return;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
        struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
  
        DBG("wifi %p station %s authorized", wifi, addr);
  static void sta_deauthorized(GSupplicantInterface *interface,
                                        const char *addr)
  {
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      /*
 +       * Note: If supplicant interface's driver is wired then skip it,
 +       * because it meanti only for ethernet not Wi-Fi.
 +       */
 +      if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
 +              return;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
        struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
  
        DBG("wifi %p station %s deauthorized", wifi, addr);
@@@ -5714,10 -3100,6 +5767,10 @@@ static void peer_found(GSupplicantPeer 
        const char *identifier, *name;
        int ret;
  
 +#if defined TIZEN_EXT
 +      if (!wifi)
 +              return;
 +#endif
        identifier = g_supplicant_peer_get_identifier(peer);
        name = g_supplicant_peer_get_name(peer);
  
@@@ -5863,11 -3245,6 +5916,11 @@@ static void peer_request(GSupplicantPee
        struct connman_peer *connman_peer;
        const char *identifier;
  
 +#if defined TIZEN_EXT
 +      if (!wifi)
 +              return;
 +#endif
 +
        identifier = g_supplicant_peer_get_identifier(peer);
  
        DBG("ident: %s", identifier);
        connman_peer_request_connection(connman_peer);
  }
  
 +#if defined TIZEN_EXT
 +static void system_power_off(void)
 +{
 +      GList *list;
 +      struct wifi_data *wifi;
 +      struct connman_service *service;
 +      struct connman_ipconfig *ipconfig_ipv4;
 +
 +      if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
 +              for (list = iface_list; list; list = list->next) {
 +                      wifi = list->data;
 +
 +                      if (wifi->network != NULL) {
 +                              service = connman_service_lookup_from_network(wifi->network);
 +                              ipconfig_ipv4 = __connman_service_get_ip4config(service);
 +                              __connman_dhcp_stop(ipconfig_ipv4);
 +                      }
 +              }
 +      }
 +}
 +
 +static void network_merged(GSupplicantNetwork *network)
 +{
 +      GSupplicantInterface *interface;
 +      GSupplicantState state;
 +      struct wifi_data *wifi;
 +      const char *identifier;
 +      struct connman_network *connman_network;
 +      bool ishs20AP = 0;
 +      char *temp = NULL;
 +
 +      interface = g_supplicant_network_get_interface(network);
 +      if (!interface)
 +              return;
 +
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      /*
 +       * Note: If supplicant interface's driver is wired then skip it,
 +       * because it meanti only for ethernet not Wi-Fi.
 +       */
 +      if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
 +              return;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
 +      state = g_supplicant_interface_get_state(interface);
 +      if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
 +              return;
 +
 +      wifi = g_supplicant_interface_get_data(interface);
 +      if (!wifi)
 +              return;
 +
 +      identifier = g_supplicant_network_get_identifier(network);
 +
 +      connman_network = connman_device_get_network(wifi->device, identifier);
 +      if (!connman_network)
 +              return;
 +
 +      DBG("merged identifier %s", identifier);
 +
 +      if (wifi->connected == FALSE) {
 +              switch (state) {
 +              case G_SUPPLICANT_STATE_AUTHENTICATING:
 +              case G_SUPPLICANT_STATE_ASSOCIATING:
 +              case G_SUPPLICANT_STATE_ASSOCIATED:
 +              case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
 +              case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
 +                      connman_network_set_associating(connman_network, TRUE);
 +                      break;
 +              case G_SUPPLICANT_STATE_COMPLETED:
 +                      connman_network_set_connected(connman_network, TRUE);
 +                      break;
 +              default:
 +                      DBG("Not handled the state : %d", state);
 +                      break;
 +              }
 +      }
 +
 +      ishs20AP = g_supplicant_network_is_hs20AP(network);
 +
 +      if (ishs20AP &&
 +              g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
 +              temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
 +              connman_network_set_string(connman_network, "WiFi.EAP",
 +                              temp);
 +              connman_network_set_string(connman_network, "WiFi.Identity",
 +                              g_supplicant_network_get_identity(network));
 +              connman_network_set_string(connman_network, "WiFi.Phase2",
 +                              g_supplicant_network_get_phase2(network));
 +
 +              g_free(temp);
 +      }
 +
 +      wifi->network = connman_network;
 +}
 +
 +static void assoc_failed(void *user_data)
 +{
 +      struct connman_network *network = user_data;
 +      connman_network_set_associating(network, false);
 +}
 +
 +static void scan_done(GSupplicantInterface *interface)
 +{
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      /*
 +       * Note: If supplicant interface's driver is wired then skip it,
 +       * because it meanti only for ethernet not Wi-Fi.
 +       */
 +      if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
 +              return;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
 +      GList *list;
 +      int scan_type = CONNMAN_SCAN_TYPE_WPA_SUPPLICANT;
 +      struct wifi_data *wifi;
 +      bool scanning;
 +
 +      for (list = iface_list; list; list = list->next) {
 +              wifi = list->data;
 +
 +              if (interface == wifi->interface) {
 +                      scanning = connman_device_get_scanning(wifi->device,
 +                                      CONNMAN_SERVICE_TYPE_WIFI);
 +                      if (!scanning)
 +                              __connman_technology_notify_scan_done(
 +                                              connman_device_get_string(wifi->device, "Interface"), scan_type);
 +                      break;
 +              }
 +      }
 +}
 +#endif
 +
  static void debug(const char *str)
  {
 +#if defined TIZEN_EXT
 +      if (connman_setting_get_bool("ConnmanSupplicantDebug"))
 +#else
        if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
 +#endif
                connman_debug("%s", str);
  }
  
  static void disconnect_reasoncode(GSupplicantInterface *interface,
                                int reasoncode)
  {
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      /*
 +       * Note: If supplicant interface's driver is wired then skip it,
 +       * because it meanti only for ethernet not Wi-Fi.
 +       */
 +      if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
 +              return;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
        struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
  
        if (wifi != NULL) {
  
  static void assoc_status_code(GSupplicantInterface *interface, int status_code)
  {
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      /*
 +       * Note: If supplicant interface's driver is wired then skip it,
 +       * because it meanti only for ethernet not Wi-Fi.
 +       */
 +      if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
 +              return;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
        struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
  
        if (wifi != NULL) {
        }
  }
  
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +static GSupplicantCallbacks callbacks = {
 +#else /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
  static const GSupplicantCallbacks callbacks = {
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
        .system_ready           = system_ready,
        .system_killed          = system_killed,
        .interface_added        = interface_added,
        .peer_lost              = peer_lost,
        .peer_changed           = peer_changed,
        .peer_request           = peer_request,
 +#if defined TIZEN_EXT
 +      .system_power_off       = system_power_off,
 +      .network_merged         = network_merged,
 +      .assoc_failed           = assoc_failed,
 +      .scan_done              = scan_done,
 +#endif
        .debug                  = debug,
        .disconnect_reasoncode  = disconnect_reasoncode,
        .assoc_status_code      = assoc_status_code,
 +#if defined TIZEN_EXT_WIFI_MESH
 +      .mesh_support           = mesh_support,
 +      .mesh_group_started = mesh_group_started,
 +      .mesh_group_removed = mesh_group_removed,
 +      .mesh_peer_connected = mesh_peer_connected,
 +      .mesh_peer_disconnected = mesh_peer_disconnected,
 +#endif
  };
  
  
@@@ -6123,11 -3328,7 +6176,11 @@@ static GSupplicantSSID *ssid_ap_init(co
                return NULL;
  
        ap->mode = G_SUPPLICANT_MODE_MASTER;
 +#if defined TIZEN_EXT
 +      ap->ssid = (void *) ssid;
 +#else
        ap->ssid = ssid;
 +#endif
        ap->ssid_len = strlen(ssid);
        ap->scan_ssid = 0;
        ap->freq = 2412;
@@@ -6212,7 -3413,7 +6265,7 @@@ static void sta_remove_callback(int res
                                        void *user_data)
  {
        struct wifi_tethering_info *info = user_data;
-       const char *driver = connman_option_get_string("wifi");
+       const char *driver = connman_setting_get_string("wifi");
  
        DBG("ifname %s result %d ", info->ifname, result);
  
        info->wifi->interface = NULL;
  
        g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
 +#ifdef TIZEN_EXT
 +                      0, 0, 60,
 +#endif /* TIZEN_EXT */
                                                ap_create_callback,
                                                        info);
  }
@@@ -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,
@@@ -6461,13 -3632,6 +6514,13 @@@ static int wifi_init(void
                return err;
        }
  
 +#if defined TIZEN_EXT
 +      failed_bssids = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
 +#endif
 +
 +#if defined TIZEN_EXT && defined TIZEN_EXT_INS
 +      supp_ins_init();
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
        return 0;
  }
  
@@@ -6480,10 -3644,6 +6533,10 @@@ static void wifi_exit(void
        g_supplicant_unregister(&callbacks);
  
        connman_network_driver_unregister(&network_driver);
 +
 +#if defined TIZEN_EXT
 +      g_hash_table_unref(failed_bssids);
 +#endif
  }
  
  CONNMAN_PLUGIN_DEFINE(wifi, "WiFi interface plugin", VERSION,
diff --combined src/bridge.c
index cd2d9ce,df19a6a..df19a6a
mode 100755,100644..100755
@@@ -122,7 -122,8 +122,8 @@@ int __connman_bridge_enable(const char 
  
        err = __connman_inet_modify_address(RTM_NEWADDR,
                                NLM_F_REPLACE | NLM_F_ACK, index, AF_INET,
-                               ip_address, NULL, prefix_len, broadcast);
+                               ip_address, NULL, prefix_len, broadcast,
+                               false);
        if (err < 0)
                return err;
  
diff --combined src/clock.c
index 40729b2,906538a..58a52c0
mode 100755,100644..100755
@@@ -39,9 -39,6 +39,9 @@@ static enum time_updates time_updates_c
  static enum timezone_updates timezone_updates_config = TIMEZONE_UPDATES_AUTO;
  
  static char *timezone_config = NULL;
 +#if defined TIZEN_EXT
 +static bool time_updated = false;
 +#endif
  
  static const char *time_updates2string(enum time_updates value)
  {
@@@ -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);
  
  
        connman_dbus_dict_open(&array, &dict);
  
 +#if defined TIZEN_EXT
 +      connman_dbus_dict_append_basic(&dict, "TimeUpdated",
 +                                              DBUS_TYPE_BOOLEAN,
 +                                              &val);
 +#endif
 +
        if (gettimeofday(&tv, NULL) == 0) {
                dbus_uint64_t val = tv.tv_sec;
  
        connman_dbus_dict_append_array(&dict, "Timeservers",
                                DBUS_TYPE_STRING, append_timeservers, NULL);
  
+       is_synced = __connman_timeserver_is_synced();
+       connman_dbus_dict_append_basic(&dict, "TimeserverSynced",
+                                       DBUS_TYPE_BOOLEAN, &is_synced);
        connman_dbus_dict_close(&array, &dict);
  
        return reply;
@@@ -253,11 -246,6 +258,11 @@@ static DBusMessage *set_property(DBusCo
        type = dbus_message_iter_get_arg_type(&value);
  
        if (g_str_equal(name, "Time")) {
 +#if defined TIZEN_EXT
 +              /* Tizen updates time (ntp) by system service */
 +
 +              return __connman_error_permission_denied(msg);
 +#else
                struct timeval tv;
                dbus_uint64_t newval;
  
                if (settimeofday(&tv, NULL) < 0)
                        return __connman_error_invalid_arguments(msg);
  
+               __connman_timeserver_set_synced(false);
                connman_dbus_property_changed_basic(CONNMAN_MANAGER_PATH,
                                CONNMAN_CLOCK_INTERFACE, "Time",
                                DBUS_TYPE_UINT64, &newval);
 +#endif
        } else if (g_str_equal(name, "TimeUpdates")) {
                const char *strval;
                enum time_updates newval;
                connman_dbus_property_changed_basic(CONNMAN_MANAGER_PATH,
                                CONNMAN_CLOCK_INTERFACE, "TimeUpdates",
                                DBUS_TYPE_STRING, &strval);
+               if (newval == TIME_UPDATES_AUTO) {
+                       struct connman_service *service;
+                       service = connman_service_get_default();
+                       __connman_timeserver_conf_update(service);
+               }
        } else if (g_str_equal(name, "Timezone")) {
                const char *strval;
  
                connman_dbus_property_changed_array(CONNMAN_MANAGER_PATH,
                                CONNMAN_CLOCK_INTERFACE, "Timeservers",
                                DBUS_TYPE_STRING, append_timeservers, NULL);
+       } else if (g_str_equal(name, "TimeserverSynced")) {
+               return __connman_error_permission_denied(msg);
        } else
                return __connman_error_invalid_property(msg);
  
@@@ -404,13 -401,6 +419,13 @@@ static const GDBusSignalTable clock_sig
  
  static DBusConnection *connection = NULL;
  
 +#if defined TIZEN_EXT
 +void __connman_clock_set_time_updated(bool updated)
 +{
 +      time_updated = updated;
 +}
 +#endif
 +
  void __connman_clock_update_timezone(void)
  {
        DBG("");
diff --combined src/connection.c
index 6036db3,9d2c696..33f6103
mode 100755,100644..100755
@@@ -674,15 -674,8 +674,15 @@@ static void connection_newgateway(int i
        }
  
        if (!found) {
 +#if defined TIZEN_EXT
 +              if (data->ipv4_gateway != NULL){
 +                      set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV4);
 +                      connman_check_proxy_setup_and_wispr_start(data->service);
 +              }
 +#else
                if (data->ipv4_gateway)
                        set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV4);
 +#endif
  
                if (data->ipv6_gateway)
                        set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV6);
@@@ -810,32 -803,6 +810,32 @@@ static void add_host_route(int family, 
        }
  }
  
 +#if defined TIZEN_EXT
 +static bool __connman_service_is_not_cellular_internet_profile(
 +              struct connman_service *cellular)
 +{
 +      char *suffix;
 +      const char *path;
 +      const char internet_suffix[] = "_1";
 +      const char prepaid_internet_suffix[] = "_3";
 +
 +      if (connman_service_get_type(cellular) != CONNMAN_SERVICE_TYPE_CELLULAR)
 +              return FALSE;
 +
 +      path = __connman_service_get_path(cellular);
 +
 +      suffix = strrchr(path, '_');
 +
 +      if (g_strcmp0(suffix, internet_suffix) != 0 &&
 +                      g_strcmp0(suffix, prepaid_internet_suffix) != 0) {
 +              DBG("not internet service profile: %s", path);
 +              return TRUE;
 +      }
 +
 +      return FALSE;
 +}
 +#endif
 +
  int __connman_connection_gateway_add(struct connman_service *service,
                                        const char *gateway,
                                        enum connman_ipconfig_type type,
        if (!gateway && type == CONNMAN_IPCONFIG_TYPE_IPV6)
                gateway = "::";
  
 +#if defined TIZEN_EXT
 +      if (__connman_service_is_not_cellular_internet_profile(service) == TRUE) {
 +              /* not internet service should not be default gateway */
 +
 +              DBG("no internet service %p index %d gateway %s vpn ip %s type %d",
 +                      service, index, gateway, peer, type);
 +
 +              if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
 +                      add_host_route(AF_INET, index, gateway, service_type);
 +                      __connman_service_nameserver_add_routes(service, gateway);
 +                      type4 = CONNMAN_IPCONFIG_TYPE_IPV4;
 +              }
 +
 +              if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
 +                      add_host_route(AF_INET6, index, gateway, service_type);
 +                      __connman_service_nameserver_add_routes(service, gateway);
 +                      type6 = CONNMAN_IPCONFIG_TYPE_IPV6;
 +              }
 +
 +              goto done;
 +      }
 +#endif
        DBG("service %p index %d gateway %s vpn ip %s type %d",
                service, index, gateway, peer, type);
  
        }
  
        if (!active_gateway) {
 +#if defined TIZEN_EXT
 +              if(new_gateway->ipv4_gateway)
 +                      DBG("ConnMan, Set default gateway[%s], active[%d]",
 +                              new_gateway->ipv4_gateway->gateway,
 +                              new_gateway->ipv4_gateway->active);
 +#endif
                set_default_gateway(new_gateway, type);
                goto done;
        }
@@@ -1049,9 -988,6 +1049,9 @@@ bool __connman_connection_update_gatewa
        bool updated = false;
        GHashTableIter iter;
        gpointer value, key;
 +#if defined TIZEN_EXT
 +      static struct gateway_data *old_default = NULL;
 +#endif
  
        if (!gateway_hash)
                return updated;
                }
        }
  
 +#if defined TIZEN_EXT
 +      if (updated == false && old_default != default_gateway) {
 +              updated = true;
 +              old_default = default_gateway;
 +      }
 +#endif
        /*
         * Set default gateway if it has been updated or if it has not been
         * set as active yet.
@@@ -1136,6 -1066,29 +1136,29 @@@ int __connman_connection_get_vpn_index(
        return -1;
  }
  
+ int __connman_connection_get_vpn_phy_index(int vpn_index)
+ {
+       GHashTableIter iter;
+       gpointer value, key;
+       g_hash_table_iter_init(&iter, gateway_hash);
+       while (g_hash_table_iter_next(&iter, &key, &value)) {
+               struct gateway_data *data = value;
+               if (data->index != vpn_index)
+                       continue;
+               if (data->ipv4_gateway)
+                       return data->ipv4_gateway->vpn_phy_index;
+               if (data->ipv6_gateway)
+                       return data->ipv6_gateway->vpn_phy_index;
+       }
+       return -1;
+ }
  int __connman_connection_init(void)
  {
        int err;
diff --combined src/connman.h
index e92f2b1,6817608..18c4fe0
mode 100755,100644..100755
  #include <glib.h>
  
  #define CONNMAN_API_SUBJECT_TO_CHANGE
 +#if defined TIZEN_EXT
 +#define WIFI_COUNTRY_CODE_LEN 2
 +#define WIFI_PHY_MODE_LEN 18
 +#define GIO_SOCKET_RETRY_COUNT 3
 +#endif
  
  #include <connman/dbus.h>
  
@@@ -59,10 -54,6 +59,10 @@@ DBusMessage *__connman_error_operation_
  DBusMessage *__connman_error_operation_timeout(DBusMessage *msg);
  DBusMessage *__connman_error_invalid_service(DBusMessage *msg);
  DBusMessage *__connman_error_invalid_property(DBusMessage *msg);
 +#if defined TIZEN_EXT_WIFI_MESH
 +DBusMessage *__connman_error_invalid_command(DBusMessage *msg);
 +DBusMessage *__connman_error_scan_abort_failed(DBusMessage *msg);
 +#endif
  DBusMessage *__connman_error_operation_canceled(DBusMessage *msg);
  
  int __connman_manager_init(void);
@@@ -79,9 -70,6 +79,9 @@@ int __connman_clock_init(void)
  void __connman_clock_cleanup(void);
  
  void __connman_clock_update_timezone(void);
 +#if defined TIZEN_EXT
 +void __connman_clock_set_time_updated(bool updated);
 +#endif
  
  int __connman_timezone_init(void);
  void __connman_timezone_cleanup(void);
@@@ -150,8 -138,6 +150,6 @@@ void __connman_log_enable(struct connma
  
  #include <connman/backtrace.h>
  
- #include <connman/option.h>
  #include <connman/setting.h>
  
  #include <connman/plugin.h>
@@@ -171,7 -157,8 +169,8 @@@ int __connman_inet_modify_address(int c
                                const char *address,
                                const char *peer,
                                unsigned char prefixlen,
-                               const char *broadcast);
+                               const char *broadcast,
+                               bool is_p2p);
  int __connman_inet_get_interface_address(int index, int family, void *address);
  int __connman_inet_get_interface_ll_address(int index, int family, void *address);
  int __connman_inet_get_interface_mac_address(int index, uint8_t *mac_address);
@@@ -188,9 -175,6 +187,9 @@@ int __connman_inet_ipv6_send_rs(int ind
                        __connman_inet_rs_cb_t callback, void *user_data);
  int __connman_inet_ipv6_send_ra(int index, struct in6_addr *src_addr,
                                GSList *prefixes, int router_lifetime);
 +#if defined TIZEN_EXT
 +void __connman_network_set_auto_ipv6_gateway(char *gateway, void *user_data);
 +#endif
  
  typedef void (*__connman_inet_ns_cb_t) (struct nd_neighbor_advert *reply,
                                        unsigned int length,
@@@ -284,10 -268,6 +283,10 @@@ GKeyFile *__connman_storage_open_global
  GKeyFile *__connman_storage_load_global(void);
  int __connman_storage_save_global(GKeyFile *keyfile);
  void __connman_storage_delete_global(void);
 +#if defined TIZEN_EXT
 +GKeyFile *__connman_storage_load_ins(void);
 +int __connman_storage_save_ins(GKeyFile *keyfile);
 +#endif
  
  GKeyFile *__connman_storage_load_config(const char *ident);
  GKeyFile *__connman_storage_load_provider_config(const char *ident);
@@@ -321,6 -301,7 +320,7 @@@ struct connman_ipaddress 
        char *peer;
        char *broadcast;
        char *gateway;
+       bool is_p2p; /* P2P connection or VPN, broadcast is excluded. */
  };
  
  struct connman_ipconfig_ops {
@@@ -397,11 -378,6 +397,11 @@@ const char *__connman_ipconfig_get_broa
  void __connman_ipconfig_set_broadcast(struct connman_ipconfig *ipconfig, const char *broadcast);
  const char *__connman_ipconfig_get_gateway(struct connman_ipconfig *ipconfig);
  void __connman_ipconfig_set_gateway(struct connman_ipconfig *ipconfig, const char *gateway);
 +
 +#if defined TIZEN_EXT
 +void __connman_ipconfig_set_dhcp_lease_duration(struct connman_ipconfig *ipconfig, int dhcp_lease_duration);
 +#endif
 +
  unsigned char __connman_ipconfig_get_prefixlen(struct connman_ipconfig *ipconfig);
  void __connman_ipconfig_set_prefixlen(struct connman_ipconfig *ipconfig, unsigned char prefixlen);
  
@@@ -432,15 -408,7 +432,15 @@@ enum connman_ipconfig_method __connman_
  int __connman_ipconfig_address_add(struct connman_ipconfig *ipconfig);
  int __connman_ipconfig_address_remove(struct connman_ipconfig *ipconfig);
  int __connman_ipconfig_address_unset(struct connman_ipconfig *ipconfig);
 +#if defined TIZEN_EXT
 +/*
 + * Description: __connman_service_lookup_from_index cannot find correct service
 + *              e.g. same interface or same APN of cellular profile
 + */
 +int __connman_ipconfig_gateway_add(struct connman_ipconfig *ipconfig, struct connman_service *service);
 +#else
  int __connman_ipconfig_gateway_add(struct connman_ipconfig *ipconfig);
 +#endif
  void __connman_ipconfig_gateway_remove(struct connman_ipconfig *ipconfig);
  
  int __connman_ipconfig_set_proxy_autoconfig(struct connman_ipconfig *ipconfig,
@@@ -481,7 -449,11 +481,11 @@@ char **__connman_timeserver_system_get(
  GSList *__connman_timeserver_add_list(GSList *server_list,
                const char *timeserver);
  GSList *__connman_timeserver_get_all(struct connman_service *service);
- int __connman_timeserver_sync(struct connman_service *service);
+ void __connman_timeserver_sync(struct connman_service *service);
+ void __connman_timeserver_conf_update(struct connman_service *service);
+ bool __connman_timeserver_is_synced(void);
+ void __connman_timeserver_set_synced(bool status);
  
  enum __connman_dhcpv6_status {
        CONNMAN_DHCPV6_STATUS_FAIL     = 0,
        CONNMAN_DHCPV6_STATUS_RESTART  = 2,
  };
  
 +#if defined TIZEN_EXT
 +void set_dhcp_discover_timeout(int timeout_value);
 +void set_dhcp_discover_retry_count(int retry_count);
 +#endif
 +
  typedef void (* dhcpv6_cb) (struct connman_network *network,
                        enum __connman_dhcpv6_status status, gpointer data);
  
@@@ -539,6 -506,7 +543,7 @@@ int __connman_connection_gateway_add(st
  void __connman_connection_gateway_remove(struct connman_service *service,
                                        enum connman_ipconfig_type type);
  int __connman_connection_get_vpn_index(int phy_index);
+ int __connman_connection_get_vpn_phy_index(int vpn_index);
  
  bool __connman_connection_update_gateway(void);
  
@@@ -592,18 -560,6 +597,18 @@@ void __connman_technology_remove_interf
  void __connman_technology_notify_regdom_by_device(struct connman_device *device,
                                                int result, const char *alpha2);
  
 +#if defined TIZEN_EXT
 +enum bssid_type {
 +      CHECK_BSSID = 0,
 +      GET_BSSID   = 1,
 +      SET_BSSID   = 2,
 +      RESET_BSSID = 3,
 +};
 +
 +int set_connman_bssid(enum bssid_type mode, char *bssid, const char *ifname);
 +void technology_save_device(struct connman_device *device);
 +#endif
 +
  #include <connman/device.h>
  
  int __connman_device_init(const char *device, const char *nodevice);
@@@ -620,12 -576,6 +625,12 @@@ int __connman_device_request_hidden_sca
                                const char *identity, const char *passphrase,
                                const char *security, void *user_data);
  void __connman_device_stop_scan(enum connman_service_type type);
 +#if defined TIZEN_EXT
 +int __connman_device_request_specific_scan(enum connman_service_type type,
 +                              const char *ifname, int scan_type, GSList *specific_scan_list);
 +int connman_device_request_device_scan(enum connman_service_type type,
 +                              const char * ifname, bool force_full_scan);
 +#endif
  
  bool __connman_device_isfiltered(const char *devname);
  
@@@ -645,13 -595,6 +650,13 @@@ int __connman_rfkill_init(void)
  void __connman_rfkill_cleanup(void);
  int __connman_rfkill_block(enum connman_service_type type, bool block);
  
 +#if defined TIZEN_EXT
 +char *index2ident(int index, const char *prefix);
 +char *index2addr(int index);
 +char *_get_wifi_ident(void);
 +char *_get_wifi_addr(void);
 +#endif
 +
  #include <connman/network.h>
  
  int __connman_network_init(void);
@@@ -671,6 -614,7 +676,7 @@@ const char *__connman_network_get_type(
  const char *__connman_network_get_group(struct connman_network *network);
  const char *__connman_network_get_ident(struct connman_network *network);
  bool __connman_network_get_weakness(struct connman_network *network);
+ bool __connman_network_native_autoconnect(struct connman_network *network);
  
  int __connman_config_init();
  void __connman_config_cleanup(void);
@@@ -718,6 -662,8 +724,8 @@@ void __connman_provider_list(DBusMessag
  bool __connman_provider_is_immutable(struct connman_provider *provider);
  int __connman_provider_create_and_connect(DBusMessage *msg);
  const char * __connman_provider_get_ident(struct connman_provider *provider);
+ const char * __connman_provider_get_transport_ident(
+                                       struct connman_provider *provider);
  int __connman_provider_indicate_state(struct connman_provider *provider,
                                        enum connman_provider_state state);
  int __connman_provider_indicate_error(struct connman_provider *provider,
@@@ -732,21 -678,11 +740,23 @@@ int __connman_provider_init(void)
  
  int __connman_service_init(void);
  void __connman_service_cleanup(void);
+ int __connman_service_move(struct connman_service *service,
+                               struct connman_service *target, bool before);
  int __connman_service_load_modifiable(struct connman_service *service);
  
  void __connman_service_list_struct(DBusMessageIter *iter);
 +#if defined TIZEN_EXT_INS
 +void __connman_ins_list_struct(DBusMessageIter *iter);
 +#endif
 +
 +#if defined TIZEN_EXT
 +int connman_service_get_ipv6_dns_method(struct connman_service *service);
 +enum connman_dnsconfig_method {
 +      CONNMAN_DNSCONFIG_METHOD_UNKNOWN = 0,
 +      CONNMAN_DNSCONFIG_METHOD_MANUAL  = 1,
 +      CONNMAN_DNSCONFIG_METHOD_DHCP    = 2,
 +};
 +#endif
  
  int __connman_service_compare(const struct connman_service *a,
                                        const struct connman_service *b);
@@@ -755,9 -691,6 +765,9 @@@ struct connman_service *__connman_servi
  struct connman_service *__connman_service_create_from_network(struct connman_network *network);
  struct connman_service *__connman_service_create_from_provider(struct connman_provider *provider);
  bool __connman_service_index_is_default(int index);
 +#if defined TIZEN_EXT
 +void __connman_service_notify_strength_changed(struct connman_network *network);
 +#endif
  void __connman_service_update_from_network(struct connman_network *network);
  void __connman_service_remove_from_network(struct connman_network *network);
  void __connman_service_read_ip4config(struct connman_service *service);
@@@ -781,10 -714,6 +791,10 @@@ struct connman_network *__connman_servi
  enum connman_service_security __connman_service_get_security(struct connman_service *service);
  const char *__connman_service_get_phase2(struct connman_service *service);
  bool __connman_service_wps_enabled(struct connman_service *service);
 +#if defined TIZEN_EXT
 +void __connman_service_set_storage_reload(struct connman_service *service,
 +                                              bool storage_reload);
 +#endif
  int __connman_service_set_favorite(struct connman_service *service,
                                                bool favorite);
  int __connman_service_set_favorite_delayed(struct connman_service *service,
@@@ -801,8 -730,9 +811,9 @@@ int __connman_service_set_mdns(struct c
  
  void __connman_service_set_string(struct connman_service *service,
                                        const char *key, const char *value);
- int __connman_service_online_check_failed(struct connman_service *service,
-                                       enum connman_ipconfig_type type);
+ void __connman_service_online_check(struct connman_service *service,
+                                       enum connman_ipconfig_type type,
+                                       bool success);
  int __connman_service_ipconfig_indicate_state(struct connman_service *service,
                                        enum connman_service_state new_state,
                                        enum connman_ipconfig_type type);
@@@ -810,10 -740,6 +821,10 @@@ enum connman_service_state __connman_se
                                        struct connman_service *service,
                                        enum connman_ipconfig_type type);
  
 +#if defined TIZEN_EXT
 +void connman_check_proxy_setup_and_wispr_start(struct connman_service *service);
 +#endif
 +
  int __connman_service_indicate_error(struct connman_service *service,
                                        enum connman_service_error error);
  int __connman_service_clear_error(struct connman_service *service);
@@@ -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,
@@@ -853,19 -767,10 +863,19 @@@ const char *__connman_service_type2stri
  enum connman_service_type __connman_service_string2type(const char *str);
  enum connman_service_security __connman_service_string2security(const char *str);
  
 +#if defined TIZEN_EXT
 +int __connman_service_nameserver_append(struct connman_service *service,
 +                              const char *nameserver, bool is_auto,
 +                              enum connman_ipconfig_type type);
 +int __connman_service_nameserver_remove(struct connman_service *service,
 +                              const char *nameserver, bool is_auto,
 +                              enum connman_ipconfig_type type);
 +#else
  int __connman_service_nameserver_append(struct connman_service *service,
                                const char *nameserver, bool is_auto);
  int __connman_service_nameserver_remove(struct connman_service *service,
                                const char *nameserver, bool is_auto);
 +#endif
  void __connman_service_nameserver_clear(struct connman_service *service);
  void __connman_service_nameserver_add_routes(struct connman_service *service,
                                                const char *gw);
@@@ -881,20 -786,12 +891,23 @@@ void __connman_service_timeserver_chang
                GSList *ts_list);
  void __connman_service_set_pac(struct connman_service *service,
                                        const char *pac);
 +#if defined TIZEN_EXT
 +/*
 + * Returns profile count if there is any connected profiles
 + * that use same interface
 + */
 +int __connman_service_get_connected_count_of_iface(struct connman_service *service);
 +void __connman_service_set_proxy(struct connman_service *service,
 +                                       const char *proxies);
 +int check_passphrase_ext(struct connman_network *network,
 +                                      const char *passphrase);
 +#endif
  bool __connman_service_is_hidden(struct connman_service *service);
  bool __connman_service_is_split_routing(struct connman_service *service);
  bool __connman_service_index_is_split_routing(int index);
+ void __connman_service_set_split_routing(struct connman_service *service,
+                                               bool split_routing);
+ void __connman_service_split_routing_changed(struct connman_service *service);
  int __connman_service_get_index(struct connman_service *service);
  void __connman_service_set_hidden(struct connman_service *service);
  void __connman_service_set_hostname(struct connman_service *service,
@@@ -963,30 -860,6 +976,30 @@@ int __connman_peer_service_unregister(c
                                        const unsigned char *query,
                                        int query_length, int version);
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +#include <connman/mesh.h>
 +
 +int __connman_mesh_init(void);
 +void __connman_mesh_cleanup(void);
 +bool __connman_technology_get_connected(enum connman_service_type type);
 +void __connman_technology_mesh_interface_create_finished(
 +                                              enum connman_service_type type, bool success,
 +                                              const char *error);
 +void __connman_technology_mesh_interface_remove_finished(
 +                                              enum connman_service_type type, bool success);
 +void __connman_mesh_peer_list_struct(DBusMessageIter *array);
 +void __connman_mesh_connected_peer_list_struct(DBusMessageIter *array);
 +void __connman_mesh_disconnected_peer_list_struct(DBusMessageIter *array);
 +int __connman_mesh_dhcp_start(struct connman_ipconfig *ipconfig,
 +                      dhcp_cb callback, gpointer user_data);
 +int __connman_device_abort_scan(enum connman_service_type type);
 +void __connman_technology_notify_abort_scan(enum connman_service_type type,
 +                                              int result);
 +int __connman_device_request_mesh_specific_scan(enum connman_service_type type,
 +                              const char *name, unsigned int freq);
 +void __connman_mesh_auto_connect(void);
 +#endif /* TIZEN_EXT_WIFI_MESH */
 +
  #include <connman/session.h>
  
  void __connman_service_mark_dirty();
@@@ -1020,29 -893,16 +1033,29 @@@ const char *__connman_notifier_get_stat
  
  #include <connman/rtnl.h>
  
 +#if defined TIZEN_EXT
 +int __connman_rtnl_init(int retry_count);
 +#else
  int __connman_rtnl_init(void);
 +#endif
  void __connman_rtnl_start(void);
  void __connman_rtnl_cleanup(void);
  
 +#if defined TIZEN_EXT
 +void __connman_wifi_vsie_list_struct(DBusMessageIter *iter);
 +#endif
 +
  enum connman_device_type __connman_rtnl_get_device_type(int index);
  unsigned int __connman_rtnl_update_interval_add(unsigned int interval);
  unsigned int __connman_rtnl_update_interval_remove(unsigned int interval);
  int __connman_rtnl_request_update(void);
  int __connman_rtnl_send(const void *buf, size_t len);
  
 +#if defined TIZEN_EXT
 +void rtnl_nameserver_add_all(struct connman_service *service,
 +                      enum connman_ipconfig_type type);
 +#endif
 +
  bool __connman_session_policy_autoconnect(enum connman_service_connect_reason reason);
  
  int __connman_session_create(DBusMessage *msg);
@@@ -1230,12 -1090,3 +1243,12 @@@ int __connman_util_get_random(uint64_t 
  unsigned int __connman_util_random_delay_ms(unsigned int secs);
  int __connman_util_init(void);
  void __connman_util_cleanup(void);
 +
 +#ifdef TIZEN_EXT
 +__attribute__ ((unused)) static int __tizentvextension = -1;
 +#define TIZEN_TV_EXT (__builtin_expect(__tizentvextension != -1, 1) ? \
 +      __tizentvextension : \
 +      (__tizentvextension = connman_setting_get_bool("TizenTVExtension")))
 +#else /* TIZEN_EXT */
 +#define TIZEN_TV_EXT (0) /* Always False */
 +#endif /* TIZEN_EXT */
diff --combined src/dbus.c
index d80a46c,c454a58..c454a58
mode 100755,100644..100755
@@@ -246,9 -246,7 +246,7 @@@ dbus_bool_t connman_dbus_property_chang
        dbus_message_iter_init_append(signal, &iter);
        connman_dbus_property_append_basic(&iter, key, type, val);
  
-       g_dbus_send_message(connection, signal);
-       return TRUE;
+       return g_dbus_send_message(connection, signal);
  }
  
  dbus_bool_t connman_dbus_property_changed_dict(const char *path,
        dbus_message_iter_init_append(signal, &iter);
        connman_dbus_property_append_dict(&iter, key, function, user_data);
  
-       g_dbus_send_message(connection, signal);
-       return TRUE;
+       return g_dbus_send_message(connection, signal);
  }
  
  dbus_bool_t connman_dbus_property_changed_array(const char *path,
        connman_dbus_property_append_array(&iter, key, type,
                                                function, user_data);
  
-       g_dbus_send_message(connection, signal);
-       return TRUE;
+       return g_dbus_send_message(connection, signal);
  }
  
  dbus_bool_t connman_dbus_setting_changed_basic(const char *owner,
  
        connman_dbus_dict_close(&array, &dict);
  
-       g_dbus_send_message(connection, msg);
-       return TRUE;
+       return g_dbus_send_message(connection, msg);
  }
  
  dbus_bool_t connman_dbus_setting_changed_dict(const char *owner,
  
        connman_dbus_dict_close(&array, &dict);
  
-       g_dbus_send_message(connection, msg);
-       return TRUE;
+       return g_dbus_send_message(connection, msg);
  }
  
  dbus_bool_t connman_dbus_setting_changed_array(const char *owner,
  
        connman_dbus_dict_close(&array, &dict);
  
-       g_dbus_send_message(connection, msg);
-       return TRUE;
+       return g_dbus_send_message(connection, msg);
  }
  
  dbus_bool_t __connman_dbus_append_objpath_dict_array(DBusMessage *msg,
diff --combined src/device.c
index 0c3eea9,264c5e2..5116900
mode 100755,100644..100755
@@@ -38,10 -38,6 +38,10 @@@ static GSList *device_list = NULL
  static gchar **device_filter = NULL;
  static gchar **nodevice_filter = NULL;
  
 +#if defined TIZEN_EXT
 +static DBusConnection *connection;
 +#endif
 +
  enum connman_pending_type {
        PENDING_NONE    = 0,
        PENDING_ENABLE  = 1,
@@@ -72,39 -68,10 +72,39 @@@ struct connman_device 
        char *last_network;
        struct connman_network *network;
        GHashTable *networks;
 +#if defined TIZEN_EXT
 +      time_t last_user_selection_time;
 +      char *last_user_selection_ident;
 +      char *last_connected_ident;
 +      GList *pending_reply_list; /* List of DBusMessage* for async reply to multiple
 +                                  * device power dbus calls, which are made before
 +                                  * connman_device_set_powered().
 +                                  */
 +      int max_scan_ssids;
 +      bool is_5_0_ghz_supported;
 +      unsigned int mac_policy;
 +      unsigned int preassoc_mac_policy;
 +      unsigned int random_mac_lifetime;
 +#endif
  };
  
 +#if defined TIZEN_EXT
 +static void __clear_pending_trigger(gpointer data, gpointer user_data)
 +{
 +      DBusMessage *msg = (DBusMessage *)data;
 +      dbus_message_unref(msg);
 +}
 +#endif
 +
  static void clear_pending_trigger(struct connman_device *device)
  {
 +#if defined TIZEN_EXT
 +      if (device->pending_reply_list) {
 +              g_list_foreach(device->pending_reply_list, __clear_pending_trigger, NULL);
 +              g_list_free(device->pending_reply_list);
 +              device->pending_reply_list = NULL;
 +      }
 +#endif
        if (device->pending_timeout > 0) {
                g_source_remove(device->pending_timeout);
                device->pending_timeout = 0;
@@@ -199,11 -166,6 +199,11 @@@ static bool device_has_service_type(str
        if (device_service_type == CONNMAN_SERVICE_TYPE_UNKNOWN)
                return true;
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +      if (device_service_type == CONNMAN_SERVICE_TYPE_MESH)
 +              return service_type != CONNMAN_SERVICE_TYPE_MESH;
 +#endif
 +
        if (device_service_type == CONNMAN_SERVICE_TYPE_WIFI) {
                return service_type == CONNMAN_SERVICE_TYPE_WIFI ||
                        service_type == CONNMAN_SERVICE_TYPE_P2P;
        return service_type == device_service_type;
  }
  
 +#if defined TIZEN_EXT
 +static void __device_pending_reset(gpointer data, gpointer user_data)
 +{
 +      DBusMessage *msg = (DBusMessage *)data;
 +      DBusMessage *reply;
 +
 +      reply = __connman_error_failed(msg, ETIMEDOUT);
 +      if (reply)
 +              g_dbus_send_message(connection, reply);
 +
 +      dbus_message_unref(msg);
 +}
 +#endif
 +
  static gboolean device_pending_reset(gpointer user_data)
  {
        struct connman_device *device = user_data;
  
        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;
@@@ -289,22 -227,15 +287,22 @@@ int __connman_device_enable(struct conn
        if (err == -EALREADY) {
                /* If device is already powered, but connman is not updated */
                connman_device_set_powered(device, true);
 +#ifdef TIZEN_EXT
 +              if (device->type == CONNMAN_DEVICE_TYPE_WIFI) {
 +                      device->driver->set_mac_policy(device, device->mac_policy);
 +                      device->driver->set_preassoc_mac_policy(device, device->preassoc_mac_policy);
 +                      device->driver->set_random_mac_lifetime(device, device->random_mac_lifetime);
 +              }
 +#endif /* TIZEN_EXT */
                goto done;
        }
        /*
         * if err == -EINPROGRESS, then the DBus call to the respective daemon
-        * was successful. We set a 10 sec timeout so if the daemon never
+        * was successful. We set a 4 sec timeout so if the daemon never
         * returns a reply, we would reset the pending request.
         */
        if (err == -EINPROGRESS)
-               device->pending_timeout = g_timeout_add_seconds(10,
+               device->pending_timeout = g_timeout_add_seconds(4,
                                        device_pending_reset, device);
  done:
        return err;
@@@ -487,65 -418,9 +485,65 @@@ static void device_destruct(struct conn
  
        g_free(device->last_network);
  
 +#if defined TIZEN_EXT
 +      g_free(device->last_user_selection_ident);
 +      g_free(device->last_connected_ident);
 +#endif
 +
        g_free(device);
  }
  
 +#if defined TIZEN_EXT
 +static void device_send_changed(const char *ifname, enum connman_service_type type,
 +                                                              const char *key, bool state)
 +{
 +      DBusMessage *signal;
 +      DBusMessageIter iter, dict;
 +      dbus_bool_t value = state;
 +      const char *tech_path = connman_techonology_get_path(type);
 +
 +      if (!tech_path || !ifname)
 +              return;
 +
 +      DBG("%s %s %s", ifname, key, state ? "TRUE" : "FALSE");
 +
 +      signal = dbus_message_new_signal(tech_path,
 +                      CONNMAN_TECHNOLOGY_INTERFACE, "DeviceChanged");
 +      if (!signal)
 +              return;
 +
 +      dbus_message_iter_init_append(signal, &iter);
 +
 +      connman_dbus_dict_open(&iter, &dict);
 +      connman_dbus_dict_append_basic(&dict, "Ifname",
 +                                      DBUS_TYPE_STRING,
 +                                      &ifname);
 +      connman_dbus_dict_append_basic(&dict, key,
 +                                      DBUS_TYPE_BOOLEAN,
 +                                      &value);
 +      connman_dbus_dict_close(&iter, &dict);
 +
 +      dbus_connection_send(connection, signal, NULL);
 +      dbus_message_unref(signal);
 +}
 +
 +static void __device_send_reply(gpointer data, gpointer user_data)
 +{
 +      DBusMessage *msg = (DBusMessage *)data;
 +      g_dbus_send_reply(connection, msg, DBUS_TYPE_INVALID);
 +      dbus_message_unref(msg);
 +}
 +
 +static void device_send_reply(struct connman_device *device)
 +{
 +      if (device->pending_reply_list) {
 +              g_list_foreach(device->pending_reply_list, __device_send_reply, NULL);
 +              g_list_free(device->pending_reply_list);
 +              device->pending_reply_list = NULL;
 +      }
 +}
 +#endif
 +
  /**
   * connman_device_create:
   * @node: device node name (for example an address)
@@@ -693,11 -568,6 +691,11 @@@ void connman_device_set_interface(struc
  void connman_device_set_ident(struct connman_device *device,
                                                        const char *ident)
  {
 +#ifdef TIZEN_EXT
 +      if (device->ident && device->powered)
 +              return;
 +      else
 +#endif
        g_free(device->ident);
        device->ident = g_strdup(ident);
  }
@@@ -726,10 -596,6 +724,10 @@@ int connman_device_set_powered(struct c
        if (device->powered == powered)
                return -EALREADY;
  
 +#if defined TIZEN_EXT
 +      device_send_reply(device);
 +#endif
 +
        clear_pending_trigger(device);
  
        device->powered_pending = PENDING_NONE;
  
        type = __connman_device_get_service_type(device);
  
 +#if defined TIZEN_EXT
 +      device_send_changed(device->interface, type, "Powered", powered);
 +      technology_save_device(device);
 +#endif
 +
        if (!device->powered) {
                __connman_technology_disabled(type);
                return 0;
@@@ -830,196 -691,6 +828,196 @@@ int connman_device_reconnect_service(st
        return 0;
  }
  
 +#if defined TIZEN_EXT
 +bool connman_device_set_last_user_selection_time(struct connman_device *device,
 +                                              time_t time)
 +{
 +      if (device->last_user_selection_time != time) {
 +              device->last_user_selection_time = time;
 +              return true;
 +      }
 +
 +      return false;
 +}
 +
 +time_t connman_device_get_last_user_selection_time(struct connman_device *device)
 +{
 +      return device->last_user_selection_time;
 +}
 +
 +bool connman_device_set_last_user_selection_ident(struct connman_device *device,
 +                                              const char *ident)
 +{
 +      if (g_strcmp0(device->last_user_selection_ident, ident) != 0) {
 +              g_free(device->last_user_selection_ident);
 +              device->last_user_selection_ident = g_strdup(ident);
 +
 +              return true;
 +      }
 +
 +      return false;
 +}
 +
 +const char *connman_device_get_last_user_selection_ident(struct connman_device *device)
 +{
 +      return device->last_user_selection_ident;
 +}
 +
 +bool connman_device_set_last_connected_ident(struct connman_device *device,
 +                                              const char *ident)
 +{
 +      if (g_strcmp0(device->last_connected_ident, ident) != 0) {
 +              g_free(device->last_connected_ident);
 +              device->last_connected_ident = g_strdup(ident);
 +
 +              return true;
 +      }
 +
 +      return false;
 +}
 +
 +const char *connman_device_get_last_connected_ident(struct connman_device *device)
 +{
 +      return device->last_connected_ident;
 +}
 +#endif
 +
 +#if defined TIZEN_EXT && defined TIZEN_EXT_INS
 +void connman_device_save_last_user_selection(struct connman_device *device)
 +{
 +      GKeyFile *keyfile;
 +      gchar *get_str;
 +      gchar *selection_str;
 +
 +      keyfile = __connman_storage_load_ins();
 +
 +      selection_str = g_strdup_printf("%s:%ld",
 +                      device->last_user_selection_ident, device->last_user_selection_time);
 +
 +      if (!keyfile) {
 +              keyfile = g_key_file_new();
 +
 +              g_key_file_set_string(keyfile, device->interface, "LastUserSelection", selection_str);
 +              DBG("%s", selection_str);
 +              __connman_storage_save_ins(keyfile);
 +
 +      } else {
 +              get_str = g_key_file_get_string(keyfile, device->interface, "LastUserSelection", NULL);
 +              if (!get_str || g_strcmp0(get_str, selection_str) != 0) {
 +                      g_key_file_set_string(keyfile, device->interface, "LastUserSelection", selection_str);
 +                      DBG("%s -> %s", get_str, selection_str);
 +                      __connman_storage_save_ins(keyfile);
 +              }
 +
 +              g_free(get_str);
 +      }
 +
 +      g_free(selection_str);
 +      g_key_file_free(keyfile);
 +}
 +
 +void connman_device_load_last_user_selection(struct connman_device *device)
 +{
 +      GKeyFile *keyfile;
 +      gchar *get_str;
 +      char **selection_str;
 +
 +      keyfile = __connman_storage_load_ins();
 +      if (!keyfile)
 +              return;
 +
 +      get_str = g_key_file_get_string(keyfile, device->interface, "LastUserSelection", NULL);
 +      if (get_str) {
 +              selection_str = g_strsplit(get_str, ":", 0);
 +              if (selection_str) {
 +                      time_t ref_time;
 +                      struct tm* timeinfo;
 +                      time_t last_user_selection_time;
 +
 +                      /* Only events that occur within 8 hours are counted. */
 +                      ref_time = time(NULL);
 +                      timeinfo = localtime(&ref_time);
 +                      timeinfo->tm_hour -= 8;
 +                      ref_time = mktime(timeinfo);
 +
 +                      last_user_selection_time = strtol(selection_str[1], NULL, 10);
 +
 +                      if (last_user_selection_time > ref_time) {
 +                              if (g_strcmp0(selection_str[0], device->last_user_selection_ident) != 0) {
 +                                      g_free(device->last_user_selection_ident);
 +                                      device->last_user_selection_ident = g_strdup(selection_str[0]);
 +                              }
 +
 +                              device->last_user_selection_time = last_user_selection_time;
 +
 +                              DBG("%s %ld", device->last_user_selection_ident, device->last_user_selection_time);
 +                      }
 +
 +                      g_strfreev(selection_str);
 +              }
 +
 +              g_free(get_str);
 +      }
 +
 +      g_key_file_free(keyfile);
 +}
 +
 +void connman_device_save_last_connected(struct connman_device *device)
 +{
 +      GKeyFile *keyfile;
 +      gchar *get_str;
 +
 +      if (!device->last_connected_ident)
 +              return;
 +
 +      keyfile = __connman_storage_load_ins();
 +
 +      if (!keyfile) {
 +              keyfile = g_key_file_new();
 +
 +              g_key_file_set_string(keyfile, device->interface, "LastConnected", device->last_connected_ident);
 +              DBG("%s", device->last_connected_ident);
 +              __connman_storage_save_ins(keyfile);
 +
 +      } else {
 +              get_str = g_key_file_get_string(keyfile, device->interface, "LastConnected", NULL);
 +              if (!get_str || g_strcmp0(get_str, device->last_connected_ident) != 0) {
 +                      g_key_file_set_string(keyfile, device->interface, "LastConnected", device->last_connected_ident);
 +                      DBG("%s -> %s", get_str, device->last_connected_ident);
 +                      __connman_storage_save_ins(keyfile);
 +              }
 +
 +              g_free(get_str);
 +      }
 +
 +      g_key_file_free(keyfile);
 +}
 +
 +void connman_device_load_last_connected(struct connman_device *device)
 +{
 +      GKeyFile *keyfile;
 +      gchar *get_str;
 +
 +      keyfile = __connman_storage_load_ins();
 +      if (!keyfile)
 +              return;
 +
 +      get_str = g_key_file_get_string(keyfile, device->interface, "LastConnected", NULL);
 +      if (get_str) {
 +              if (g_strcmp0(get_str, device->last_connected_ident) != 0) {
 +                      g_free(device->last_connected_ident);
 +                      device->last_connected_ident = g_strdup(get_str);
 +              }
 +
 +              DBG("%s", device->last_connected_ident);
 +
 +              g_free(get_str);
 +      }
 +
 +      g_key_file_free(keyfile);
 +}
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
 +
  static void mark_network_available(gpointer key, gpointer value,
                                                        gpointer user_data)
  {
@@@ -1120,11 -791,6 +1118,11 @@@ int connman_device_set_scanning(struct 
  
        __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +      if (type == CONNMAN_SERVICE_TYPE_MESH)
 +              __connman_mesh_auto_connect();
 +#endif
 +
        return 0;
  }
  
@@@ -1142,11 -808,6 +1140,11 @@@ int connman_device_set_string(struct co
        DBG("device %p key %s value %s", device, key, value);
  
        if (g_str_equal(key, "Address")) {
 +#ifdef TIZEN_EXT
 +              if (device->address && device->powered)
 +                      return 0;
 +              else
 +#endif
                g_free(device->address);
                device->address = g_strdup(value);
        } else if (g_str_equal(key, "Name")) {
  const char *connman_device_get_string(struct connman_device *device,
                                                        const char *key)
  {
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        DBG("device %p key %s", device, key);
  
        if (g_str_equal(key, "Address"))
@@@ -1205,9 -863,7 +1203,9 @@@ int connman_device_add_network(struct c
                                        struct connman_network *network)
  {
        const char *identifier = connman_network_get_identifier(network);
 -
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        DBG("device %p network %p", device, network);
  
        if (!identifier)
  struct connman_network *connman_device_get_network(struct connman_device *device,
                                                        const char *identifier)
  {
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        DBG("device %p identifier %s", device, identifier);
  
        return g_hash_table_lookup(device->networks, identifier);
  }
  
 +#if defined TIZEN_EXT
 +struct connman_network *connman_device_get_default_network(
 +                                                      struct connman_device *device)
 +{
 +      return device->network;
 +}
 +
 +void connman_device_set_pending_reply(struct connman_device *device,
 +                                                      DBusMessage *msg)
 +{
 +      device->pending_reply_list = g_list_prepend(device->pending_reply_list, dbus_message_ref(msg));
 +}
 +
 +void connman_device_send_connected_signal(struct connman_device *device,
 +                                                      bool connected)
 +{
 +      enum connman_service_type type;
 +
 +      if (!device)
 +              return;
 +
 +      type = __connman_device_get_service_type(device);
 +      device_send_changed(device->interface, type, "Connected", connected);
 +}
 +
 +void connman_device_set_max_scan_ssids(struct connman_device *device,
 +                                                      int max_scan_ssids)
 +{
 +      device->max_scan_ssids = max_scan_ssids;
 +}
 +
 +int connman_device_get_max_scan_ssids(struct connman_device *device)
 +{
 +      return device->max_scan_ssids;
 +}
 +
 +void connman_device_set_wifi_5ghz_supported(struct connman_device *device,
 +                                                      bool is_5_0_ghz_supported)
 +{
 +      device->is_5_0_ghz_supported = is_5_0_ghz_supported;
 +}
 +
 +bool connman_device_get_wifi_5ghz_supported(struct connman_device *device)
 +{
 +      return device->is_5_0_ghz_supported;
 +}
 +#endif
 +
  /**
   * connman_device_remove_network:
   * @device: device structure
@@@ -1485,225 -1090,6 +1483,225 @@@ void connman_device_regdom_notify(struc
        __connman_technology_notify_regdom_by_device(device, result, alpha2);
  }
  
 +#if defined TIZEN_EXT
 +static int device_specific_scan(enum connman_service_type type,
 +                              struct connman_device *device,
 +                              int scan_type, GSList *specific_scan_list)
 +{
 +      if (!device->driver || !device->driver->specific_scan)
 +              return -EOPNOTSUPP;
 +
 +      if (!device->powered)
 +              return -ENOLINK;
 +
 +      return device->driver->specific_scan(type, device, scan_type,
 +                      specific_scan_list, NULL);
 +}
 +
 +int __connman_device_request_specific_scan(enum connman_service_type type,
 +                              const char *ifname, int scan_type, GSList *specific_scan_list)
 +{
 +      bool success = false;
 +      int last_err = -ENOSYS;
 +      GSList *list;
 +      int err;
 +
 +      switch (type) {
 +      case CONNMAN_SERVICE_TYPE_UNKNOWN:
 +      case CONNMAN_SERVICE_TYPE_SYSTEM:
 +      case CONNMAN_SERVICE_TYPE_ETHERNET:
 +      case CONNMAN_SERVICE_TYPE_BLUETOOTH:
 +      case CONNMAN_SERVICE_TYPE_CELLULAR:
 +      case CONNMAN_SERVICE_TYPE_GPS:
 +      case CONNMAN_SERVICE_TYPE_VPN:
 +      case CONNMAN_SERVICE_TYPE_GADGET:
 +              return -EOPNOTSUPP;
 +      case CONNMAN_SERVICE_TYPE_WIFI:
 +      case CONNMAN_SERVICE_TYPE_P2P:
 +#if defined TIZEN_EXT_WIFI_MESH
 +      case CONNMAN_SERVICE_TYPE_MESH:
 +#endif
 +              break;
 +      }
 +
 +      for (list = device_list; list; list = list->next) {
 +              struct connman_device *device = list->data;
 +              enum connman_service_type service_type =
 +                      __connman_device_get_service_type(device);
 +
 +              if (service_type != CONNMAN_SERVICE_TYPE_UNKNOWN) {
 +                      if (type == CONNMAN_SERVICE_TYPE_P2P) {
 +                              if (service_type != CONNMAN_SERVICE_TYPE_WIFI)
 +                                      continue;
 +                      } else if (service_type != type)
 +                              continue;
 +              }
 +
 +              if (ifname && g_strcmp0(device->interface, ifname) != 0)
 +                      continue;
 +
 +              err = device_specific_scan(type, device, scan_type, specific_scan_list);
 +              if (err == 0 || err == -EINPROGRESS) {
 +                      success = true;
 +              } else {
 +                      last_err = err;
 +                      DBG("device %p err %d", device, err);
 +              }
 +      }
 +
 +      if (success)
 +              return 0;
 +
 +      return last_err;
 +}
 +
 +int connman_device_request_device_scan(enum connman_service_type type,
 +                              const char * ifname, bool force_full_scan)
 +{
 +      bool success = false;
 +      int last_err = -ENOSYS;
 +      GSList *list;
 +      int err;
 +
 +      switch (type) {
 +      case CONNMAN_SERVICE_TYPE_UNKNOWN:
 +      case CONNMAN_SERVICE_TYPE_SYSTEM:
 +      case CONNMAN_SERVICE_TYPE_ETHERNET:
 +      case CONNMAN_SERVICE_TYPE_BLUETOOTH:
 +      case CONNMAN_SERVICE_TYPE_CELLULAR:
 +      case CONNMAN_SERVICE_TYPE_GPS:
 +      case CONNMAN_SERVICE_TYPE_VPN:
 +      case CONNMAN_SERVICE_TYPE_GADGET:
 +              return -EOPNOTSUPP;
 +      case CONNMAN_SERVICE_TYPE_WIFI:
 +      case CONNMAN_SERVICE_TYPE_P2P:
 +#if defined TIZEN_EXT_WIFI_MESH
 +      case CONNMAN_SERVICE_TYPE_MESH:
 +#endif
 +              break;
 +      }
 +
 +      for (list = device_list; list; list = list->next) {
 +              struct connman_device *device = list->data;
 +
 +              if (!device_has_service_type(device, type))
 +                      continue;
 +
 +              if (g_strcmp0(device->interface, ifname) != 0)
 +                      continue;
 +
 +              err = device_scan(type, device, force_full_scan);
 +
 +              if (err == 0 || err == -EINPROGRESS) {
 +                      success = true;
 +              } else {
 +                      last_err = err;
 +                      DBG("device %p err %d", device, err);
 +              }
 +              break;
 +      }
 +
 +      if (success)
 +              return 0;
 +
 +      return last_err;
 +}
 +
 +#if defined TIZEN_EXT_WIFI_MESH
 +static int device_abort_scan(enum connman_service_type type,
 +                              struct connman_device *device)
 +{
 +      if (!device->driver || !device->driver->scan)
 +              return -EOPNOTSUPP;
 +
 +      if (!device->powered)
 +              return -ENOLINK;
 +
 +      return device->driver->abort_scan(type, device);
 +}
 +
 +int __connman_device_abort_scan(enum connman_service_type type)
 +{
 +      GSList *list;
 +      int err = -EINVAL;
 +
 +      if (type != CONNMAN_SERVICE_TYPE_MESH)
 +              return -EINVAL;
 +
 +      for (list = device_list; list; list = list->next) {
 +              struct connman_device *device = list->data;
 +              enum connman_service_type service_type =
 +                      __connman_device_get_service_type(device);
 +
 +              if (service_type != CONNMAN_SERVICE_TYPE_UNKNOWN) {
 +                      if (type == CONNMAN_SERVICE_TYPE_MESH)
 +                              if (service_type != CONNMAN_SERVICE_TYPE_WIFI)
 +                                      continue;
 +
 +                      if (!device->scanning) {
 +                              err = -EEXIST;
 +                              continue;
 +                      }
 +
 +                      err = device_abort_scan(type, device);
 +              }
 +      }
 +      return err;
 +}
 +
 +static int device_mesh_specific_scan(enum connman_service_type type,
 +                              struct connman_device *device, const char *name,
 +                              unsigned int freq)
 +{
 +      if (!device->driver || !device->driver->mesh_specific_scan)
 +              return -EOPNOTSUPP;
 +
 +      if (!device->powered)
 +              return -ENOLINK;
 +
 +      return device->driver->mesh_specific_scan(type, device, name, freq, NULL);
 +}
 +
 +int __connman_device_request_mesh_specific_scan(enum connman_service_type type,
 +                                              const char *name,
 +                                              unsigned int freq)
 +{
 +      bool success = false;
 +      int last_err = -ENOSYS;
 +      GSList *list;
 +      int err;
 +
 +      if (type != CONNMAN_SERVICE_TYPE_MESH)
 +              return -EINVAL;
 +
 +      for (list = device_list; list; list = list->next) {
 +              struct connman_device *device = list->data;
 +              enum connman_service_type service_type =
 +                      __connman_device_get_service_type(device);
 +
 +              if (service_type != CONNMAN_SERVICE_TYPE_UNKNOWN) {
 +                      if (type == CONNMAN_SERVICE_TYPE_MESH)
 +                              if (service_type != CONNMAN_SERVICE_TYPE_WIFI)
 +                                      continue;
 +              }
 +
 +              err = device_mesh_specific_scan(type, device, name, freq);
 +              if (err == 0 || err == -EALREADY || err == -EINPROGRESS) {
 +                      success = true;
 +              } else {
 +                      last_err = err;
 +                      DBG("device %p err %d", device, err);
 +              }
 +      }
 +
 +      if (success)
 +              return 0;
 +
 +      return last_err;
 +}
 +#endif /* TIZEN_EXT_WIFI_MESH */
 +#endif
 +
  static int connman_device_request_scan(enum connman_service_type type,
                                        bool force_full_scan)
  {
                return -EOPNOTSUPP;
        case CONNMAN_SERVICE_TYPE_WIFI:
        case CONNMAN_SERVICE_TYPE_P2P:
 +#if defined TIZEN_EXT_WIFI_MESH
 +      case CONNMAN_SERVICE_TYPE_MESH:
 +#endif
                break;
        }
  
                        continue;
  
                err = device_scan(type, device, force_full_scan);
 +#if defined TIZEN_EXT
 +              /* When Scan is already in progress then return Error so that
 +               * wifi-manager can block the scan-done signal to be sent to
 +               * application and start requested scan after scan already in progress
 +               * is completed then notify to application about the scan event */
 +              if (err == 0 || err == -EINPROGRESS) {
 +#else
                if (err == 0 || err == -EALREADY || err == -EINPROGRESS) {
 +#endif
                        success = true;
                } else {
                        last_err = err;
@@@ -1808,92 -1183,7 +1806,92 @@@ void __connman_device_stop_scan(enum co
        }
  }
  
 +#if defined TIZEN_EXT
 +#define WIFI_MAC "/opt/etc/.mac.info"
 +#define MAC_ADDR_LEN 18
 +
 +char *_get_wifi_addr(void)
 +{
 +      FILE *fp = NULL;
 +      char* rv = 0;
 +      char wifi_mac[MAC_ADDR_LEN + 1];
 +      char *str;
 +
 +      fp = fopen(WIFI_MAC, "r");
 +      if (!fp){
 +              connman_error("[%s] not present", WIFI_MAC);
 +              return NULL;
 +      }
 +
 +      rv = fgets(wifi_mac, MAC_ADDR_LEN, fp);
 +      if (!rv) {
 +              connman_error("Failed to get wifi mac address");
 +              fclose(fp);
 +              return NULL;
 +      }
 +
 +      str = g_try_malloc0(MAC_ADDR_LEN);
 +      if (!str) {
 +              connman_error("memory allocation failed");
 +              fclose(fp);
 +              return NULL;
 +      }
 +
 +      snprintf(str, MAC_ADDR_LEN, "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c",
 +                      g_ascii_tolower(wifi_mac[0]), g_ascii_tolower(wifi_mac[1]),
 +                      g_ascii_tolower(wifi_mac[3]), g_ascii_tolower(wifi_mac[4]),
 +                      g_ascii_tolower(wifi_mac[6]), g_ascii_tolower(wifi_mac[7]),
 +                      g_ascii_tolower(wifi_mac[9]), g_ascii_tolower(wifi_mac[10]),
 +                      g_ascii_tolower(wifi_mac[12]), g_ascii_tolower(wifi_mac[13]),
 +                      g_ascii_tolower(wifi_mac[15]), g_ascii_tolower(wifi_mac[16]));
 +      fclose(fp);
 +      return str;
 +}
 +
 +char *_get_wifi_ident(void)
 +{
 +      FILE *fp = NULL;
 +      char* rv = 0;
 +      char wifi_mac[MAC_ADDR_LEN + 1];
 +      char *str;
 +
 +      fp = fopen(WIFI_MAC, "r");
 +      if (!fp){
 +              connman_error("[%s] not present", WIFI_MAC);
 +              return NULL;
 +      }
 +
 +      rv = fgets(wifi_mac, MAC_ADDR_LEN, fp);
 +      if (!rv) {
 +              connman_error("Failed to get wifi mac address");
 +              fclose(fp);
 +              return NULL;
 +      }
 +
 +      str = g_try_malloc0(MAC_ADDR_LEN);
 +      if (!str) {
 +              connman_error("memory allocation failed");
 +              fclose(fp);
 +              return NULL;
 +      }
 +
 +      snprintf(str, MAC_ADDR_LEN, "%c%c%c%c%c%c%c%c%c%c%c%c",
 +                      g_ascii_tolower(wifi_mac[0]), g_ascii_tolower(wifi_mac[1]),
 +                      g_ascii_tolower(wifi_mac[3]), g_ascii_tolower(wifi_mac[4]),
 +                      g_ascii_tolower(wifi_mac[6]), g_ascii_tolower(wifi_mac[7]),
 +                      g_ascii_tolower(wifi_mac[9]), g_ascii_tolower(wifi_mac[10]),
 +                      g_ascii_tolower(wifi_mac[12]), g_ascii_tolower(wifi_mac[13]),
 +                      g_ascii_tolower(wifi_mac[15]), g_ascii_tolower(wifi_mac[16]));
 +      fclose(fp);
 +      return str;
 +}
 +#endif
 +
 +#if defined TIZEN_EXT
 +char *index2ident(int index, const char *prefix)
 +#else
  static char *index2ident(int index, const char *prefix)
 +#endif
  {
        struct ifreq ifr;
        struct ether_addr eth;
        return str;
  }
  
 +#if defined TIZEN_EXT
 +char *index2addr(int index)
 +#else
  static char *index2addr(int index)
 +#endif
  {
        struct ifreq ifr;
        struct ether_addr eth;
@@@ -2052,10 -1338,6 +2050,10 @@@ struct connman_device *connman_device_c
  
        connman_device_set_index(device, index);
        connman_device_set_interface(device, devname);
 +#if defined TIZEN_EXT && defined TIZEN_EXT_INS
 +      connman_device_load_last_connected(device);
 +      connman_device_load_last_user_selection(device);
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
  
        if (ident) {
                connman_device_set_ident(device, ident);
@@@ -2187,9 -1469,6 +2185,9 @@@ static void cleanup_devices(void
  
                DBG("cleaning up %s index %d", interfaces[i], index);
  
 +#if defined TIZEN_EXT
 +              if (strcmp(interfaces[i], "wlan0") != 0)
 +#endif
                connman_inet_ifdown(index);
  
                /*
@@@ -2205,10 -1484,6 +2203,10 @@@ int __connman_device_init(const char *d
  {
        DBG("");
  
 +#if defined TIZEN_EXT
 +      connection = connman_dbus_get_connection();
 +#endif
 +
        if (device)
                device_filter = g_strsplit(device, ",", -1);
  
@@@ -2226,86 -1501,4 +2224,86 @@@ void __connman_device_cleanup(void
  
        g_strfreev(nodevice_filter);
        g_strfreev(device_filter);
 +
 +#if defined TIZEN_EXT
 +      dbus_connection_unref(connection);
 +#endif
 +}
 +
 +#ifdef TIZEN_EXT
 +void connman_device_mac_policy_notify(struct connman_device *device,
 +                                      int result, unsigned int policy)
 +{
 +      device->mac_policy = policy;
 +      __connman_technology_notify_mac_policy_by_device(device, result, policy);
 +}
 +
 +int connman_device_set_mac_policy(struct connman_device *device,
 +                                      unsigned int policy)
 +{
 +      int err = 0;
 +
 +      if (!device || !device->driver || !device->driver->set_mac_policy)
 +              return -EOPNOTSUPP;
 +
 +      device->mac_policy = policy;
 +      err = device->driver->set_mac_policy(device, policy);
 +      return err;
 +}
 +
 +unsigned int connman_device_get_mac_policy(struct connman_device *device)
 +{
 +      return device->mac_policy;
 +}
 +
 +void connman_device_preassoc_mac_policy_notify(struct connman_device *device,
 +                                      int result, unsigned int policy)
 +{
 +      device->preassoc_mac_policy = policy;
 +      __connman_technology_notify_preassoc_mac_policy_by_device(device, result, policy);
 +}
 +
 +int connman_device_set_preassoc_mac_policy(struct connman_device *device,
 +                                      unsigned int policy)
 +{
 +      int err = 0;
 +
 +      if (!device || !device->driver || !device->driver->set_preassoc_mac_policy)
 +              return -EOPNOTSUPP;
 +
 +      device->preassoc_mac_policy = policy;
 +      err = device->driver->set_preassoc_mac_policy(device, policy);
 +      return err;
 +}
 +
 +unsigned int connman_device_get_preassoc_mac_policy(struct connman_device *device)
 +{
 +      return device->preassoc_mac_policy;
 +}
 +
 +void connman_device_random_mac_lifetime_notify(struct connman_device *device,
 +                                      int result, unsigned int lifetime)
 +{
 +      device->random_mac_lifetime = lifetime;
 +      __connman_technology_notify_random_mac_lifetime_by_device(device, result, lifetime);
  }
 +
 +int connman_device_set_random_mac_lifetime(struct connman_device *device,
 +                                      unsigned int lifetime)
 +{
 +      int err = 0;
 +
 +      if (!device || !device->driver || !device->driver->set_random_mac_lifetime)
 +              return -EOPNOTSUPP;
 +
 +      device->random_mac_lifetime = lifetime;
 +      err = device->driver->set_random_mac_lifetime(device, lifetime);
 +      return err;
 +}
 +
 +unsigned int connman_device_get_random_mac_lifetime(struct connman_device *device)
 +{
 +      return device->random_mac_lifetime;
 +}
 +
 +#endif
diff --combined src/dhcp.c
@@@ -67,9 -67,6 +67,9 @@@ static GHashTable *ipconfig_table
  
  static void dhcp_free(struct connman_dhcp *dhcp)
  {
 +#if defined TIZEN_EXT
 +      DBG("dhcp_free [%p]", dhcp);
 +#endif
        g_strfreev(dhcp->nameservers);
        g_strfreev(dhcp->timeservers);
        g_free(dhcp->pac);
        dhcp->pac = NULL;
  
        g_free(dhcp);
 +#if defined TIZEN_EXT
 +      dhcp = NULL;
 +#endif
  }
  
  static void ipv4ll_stop_client(struct connman_dhcp *dhcp)
  {
 +#if defined TIZEN_EXT
 +      DBG("dhcp [%p] ipv4ll_client [%p]", dhcp, dhcp->ipv4ll_client);
 +#endif
        if (!dhcp->ipv4ll_client)
                return;
  
@@@ -128,14 -119,8 +128,14 @@@ static bool apply_dhcp_invalidate_on_ne
        }
        if (dhcp->nameservers) {
                for (i = 0; dhcp->nameservers[i]; i++) {
 +#if defined TIZEN_EXT
 +                      __connman_service_nameserver_remove(service,
 +                                      dhcp->nameservers[i], false,
 +                                      CONNMAN_IPCONFIG_TYPE_IPV4);
 +#else
                        __connman_service_nameserver_remove(service,
                                                dhcp->nameservers[i], false);
 +#endif
                }
                g_strfreev(dhcp->nameservers);
                dhcp->nameservers = NULL;
@@@ -208,10 -193,6 +208,10 @@@ static int ipv4ll_start_client(struct c
        int index;
        int err;
  
 +#if defined TIZEN_EXT
 +      DBG("dhcp %p", dhcp);
 +#endif
 +
        if (dhcp->ipv4ll_client)
                return -EALREADY;
  
        if (error != G_DHCP_CLIENT_ERROR_NONE)
                return -EINVAL;
  
 +#if !defined TIZEN_EXT
        if (getenv("CONNMAN_DHCP_DEBUG")) {
 +#endif
                dhcp->ipv4ll_debug_prefix = g_strdup_printf("IPv4LL index %d",
                                                        index);
                g_dhcp_client_set_debug(ipv4ll_client, dhcp_debug,
                                        dhcp->ipv4ll_debug_prefix);
 +#if !defined TIZEN_EXT
        }
 +#endif
  
        g_dhcp_client_set_id(ipv4ll_client);
  
@@@ -266,10 -243,6 +266,10 @@@ static gboolean dhcp_retry_cb(gpointer 
  
        dhcp->timeout = 0;
  
 +#if defined TIZEN_EXT
 +      DBG("dhcp %p", dhcp);
 +      DBG("dhcp->timeout %d", dhcp->timeout);
 +#endif
        g_dhcp_client_start(dhcp->dhcp_client,
                        __connman_ipconfig_get_dhcp_address(dhcp->ipconfig));
  
@@@ -284,14 -257,6 +284,14 @@@ static void no_lease_cb(GDHCPClient *dh
        DBG("No lease available ipv4ll %d client %p", dhcp->ipv4ll_running,
                dhcp->ipv4ll_client);
  
 +#if defined TIZEN_EXT
 +      if (connman_setting_get_bool("EnableAutoIp") == false) {
 +              DBG("link-local address autoconfiguration is disabled.");
 +              if (dhcp->network)
 +                      __connman_network_disconnect(dhcp->network);
 +              return;
 +      }
 +#endif
        if (dhcp->timeout > 0)
                g_source_remove(dhcp->timeout);
  
@@@ -417,32 -382,18 +417,32 @@@ static bool apply_lease_available_on_ne
  
        if (!compare_string_arrays(nameservers, dhcp->nameservers)) {
                if (dhcp->nameservers) {
 +#if defined TIZEN_EXT
 +                      for (i = 0; dhcp->nameservers[i] != NULL; i++) {
 +                              __connman_service_nameserver_remove(service,
 +                                              dhcp->nameservers[i], false,
 +                                              CONNMAN_IPCONFIG_TYPE_IPV4);
 +                      }
 +#else
                        for (i = 0; dhcp->nameservers[i]; i++) {
                                __connman_service_nameserver_remove(service,
                                                dhcp->nameservers[i], false);
                        }
 +#endif
                        g_strfreev(dhcp->nameservers);
                }
  
                dhcp->nameservers = nameservers;
  
                for (i = 0; dhcp->nameservers && dhcp->nameservers[i]; i++) {
 +#if defined TIZEN_EXT
 +                      __connman_service_nameserver_append(service,
 +                                              dhcp->nameservers[i], false,
 +                                              CONNMAN_IPCONFIG_TYPE_IPV4);
 +#else
                        __connman_service_nameserver_append(service,
                                                dhcp->nameservers[i], false);
 +#endif
                }
        } else {
                g_strfreev(nameservers);
@@@ -507,10 -458,6 +507,10 @@@ static void lease_available_cb(GDHCPCli
        __connman_ipconfig_set_dhcp_address(dhcp->ipconfig, address);
        DBG("last address %s", address);
  
 +#if defined TIZEN_EXT
 +      int dhcp_lease_duration = g_dhcp_client_get_dhcp_lease_duration(dhcp_client);
 +#endif
 +
        option = g_dhcp_client_get_option(dhcp_client, G_DHCP_SUBNET);
        if (option)
                netmask = g_strdup(option->data);
        __connman_ipconfig_set_method(dhcp->ipconfig,
                                                CONNMAN_IPCONFIG_METHOD_DHCP);
  
 +#if defined TIZEN_EXT
 +      __connman_ipconfig_set_dhcp_lease_duration(dhcp->ipconfig, dhcp_lease_duration);
 +#endif
 +
        /*
         * Notify IPv4.Configuration's method moved back to DHCP.
         *
@@@ -637,25 -580,14 +637,25 @@@ static int dhcp_initialize(struct connm
  
        dhcp_client = g_dhcp_client_new(G_DHCP_IPV4, index, &error);
        if (error != G_DHCP_CLIENT_ERROR_NONE)
 +#if defined TIZEN_EXT
 +      {
 +              DBG("failed g_dhcp_client_new(%d), index(%d)", error, index);
 +#endif
                return -EINVAL;
 +#if defined TIZEN_EXT
 +      }
 +#endif
  
 +#if !defined TIZEN_EXT
        if (getenv("CONNMAN_DHCP_DEBUG")) {
 +#endif
                dhcp->dhcp_debug_prefix = g_strdup_printf("DHCP index %d",
                                                        index);
                g_dhcp_client_set_debug(dhcp_client, dhcp_debug,
                                        dhcp->dhcp_debug_prefix);
 +#if !defined TIZEN_EXT
        }
 +#endif
  
        g_dhcp_client_set_id(dhcp_client);
  
        g_dhcp_client_set_request(dhcp_client, G_DHCP_ROUTER);
        g_dhcp_client_set_request(dhcp_client, G_DHCP_SUBNET);
  
-       vendor_class_id = connman_option_get_string("VendorClassID");
+       vendor_class_id = connman_setting_get_string("VendorClassID");
        if (vendor_class_id)
                g_dhcp_client_set_send(dhcp_client, G_DHCP_VENDOR_CLASS_ID,
                                        vendor_class_id);
@@@ -739,48 -671,11 +739,48 @@@ char *__connman_dhcp_get_server_address
        return g_dhcp_client_get_server_address(dhcp->dhcp_client);
  }
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +int __connman_mesh_dhcp_start(struct connman_ipconfig *ipconfig,
 +                      dhcp_cb callback, gpointer user_data)
 +{
 +      struct connman_dhcp *dhcp;
 +      int err;
 +
 +      DBG("");
 +
 +      dhcp = g_hash_table_lookup(ipconfig_table, ipconfig);
 +      if (!dhcp) {
 +
 +              dhcp = g_try_new0(struct connman_dhcp, 1);
 +              if (!dhcp)
 +                      return -ENOMEM;
 +
 +              dhcp->ipconfig = ipconfig;
 +              __connman_ipconfig_ref(ipconfig);
 +
 +              err = dhcp_initialize(dhcp);
 +
 +              if (err < 0) {
 +                      g_free(dhcp);
 +                      return err;
 +              }
 +
 +              g_hash_table_insert(ipconfig_table, ipconfig, dhcp);
 +      }
 +
 +      dhcp->callback = callback;
 +      dhcp->user_data = user_data;
 +      return g_dhcp_client_start(dhcp->dhcp_client, NULL);
 +}
 +#endif
 +
  int __connman_dhcp_start(struct connman_ipconfig *ipconfig,
                        struct connman_network *network, dhcp_cb callback,
                        gpointer user_data)
  {
 +#if !defined TIZEN_EXT
        const char *last_addr = NULL;
 +#endif
        struct connman_dhcp *dhcp;
        int err;
  
                        return -EINVAL;
        }
  
 +#if !defined TIZEN_EXT
        last_addr = __connman_ipconfig_get_dhcp_address(ipconfig);
 +#endif
  
        dhcp = g_hash_table_lookup(ipconfig_table, ipconfig);
        if (!dhcp) {
        dhcp->callback = callback;
        dhcp->user_data = user_data;
  
 +#if defined TIZEN_EXT
 +      DBG("Start DHCP with DHCPDISCOVER request");
 +
 +      return g_dhcp_client_start(dhcp->dhcp_client, NULL);
 +#else
        return g_dhcp_client_start(dhcp->dhcp_client, last_addr);
 +#endif
  }
  
  void __connman_dhcp_stop(struct connman_ipconfig *ipconfig)
diff --combined src/dhcpv6.c
index 4c07c76,8b68359..ba54b89
mode 100755,100644..100755
@@@ -197,23 -197,10 +197,23 @@@ static int set_duid(struct connman_serv
        int duid_len;
  
        ident = connman_service_get_identifier(service);
 +#if defined TIZEN_EXT
 +      if(ident != NULL)
 +              DBG("ident : %s", ident);
 +#endif
  
        keyfile = connman_storage_load_service(ident);
 +
 +#if defined TIZEN_EXT
 +      if (!keyfile) {
 +              keyfile = g_key_file_new();
 +              if (!keyfile)
 +                      return -EIO;
 +      }
 +#else
        if (!keyfile)
                return -EINVAL;
 +#endif
  
        hex_duid = g_key_file_get_string(keyfile, ident, "IPv6.DHCP.DUID",
                                        NULL);
@@@ -335,19 -322,9 +335,19 @@@ static void info_req_cb(GDHCPClient *dh
        if (!compare_string_arrays(nameservers, dhcp->nameservers)) {
                if (dhcp->nameservers) {
                        for (i = 0; dhcp->nameservers[i]; i++)
 +#if defined TIZEN_EXT
 +                      {
 +                              __connman_service_nameserver_remove(service,
 +                                              dhcp->nameservers[i], false,
 +                                              CONNMAN_IPCONFIG_TYPE_IPV6);
 +#else
                                __connman_service_nameserver_remove(service,
                                                        dhcp->nameservers[i],
                                                        false);
 +#endif
 +#if defined TIZEN_EXT
 +                      }
 +#endif
                        g_strfreev(dhcp->nameservers);
                }
  
  
                for (i = 0; dhcp->nameservers &&
                                        dhcp->nameservers[i]; i++)
 +#if defined TIZEN_EXT
 +              {
 +                      __connman_service_nameserver_append(service,
 +                                              dhcp->nameservers[i], false,
 +                                              CONNMAN_IPCONFIG_TYPE_IPV6);
 +#else
                        __connman_service_nameserver_append(service,
                                                dhcp->nameservers[i],
                                                false);
 +#endif
 +#if defined TIZEN_EXT
 +              }
 +#endif
        } else
                g_strfreev(nameservers);
  
@@@ -425,9 -392,7 +425,9 @@@ static int dhcpv6_info_request(struct c
                return -EINVAL;
        }
  
 +#if !defined TIZEN_EXT
        if (getenv("CONNMAN_DHCPV6_DEBUG"))
 +#endif
                g_dhcp_client_set_debug(dhcp_client, dhcpv6_debug, "DHCPv6");
  
        service = connman_service_lookup_from_network(dhcp->network);
@@@ -552,19 -517,9 +552,19 @@@ static int set_other_addresses(GDHCPCli
        if (!compare_string_arrays(nameservers, dhcp->nameservers)) {
                if (dhcp->nameservers) {
                        for (i = 0; dhcp->nameservers[i]; i++)
 +#if defined TIZEN_EXT
 +                      {
 +                              __connman_service_nameserver_remove(service,
 +                                              dhcp->nameservers[i],
 +                                              false, CONNMAN_IPCONFIG_TYPE_IPV6);
 +#else
                                __connman_service_nameserver_remove(service,
                                                        dhcp->nameservers[i],
                                                        false);
 +#endif
 +#if defined TIZEN_EXT
 +                      }
 +#endif
                        g_strfreev(dhcp->nameservers);
                }
  
  
                for (i = 0; dhcp->nameservers &&
                                        dhcp->nameservers[i]; i++)
 +#if defined TIZEN_EXT
 +              {
 +                      __connman_service_nameserver_append(service,
 +                                      dhcp->nameservers[i],
 +                                      false, CONNMAN_IPCONFIG_TYPE_IPV6);
 +#else
                        __connman_service_nameserver_append(service,
                                                        dhcp->nameservers[i],
                                                        false);
 +#endif
 +#if defined TIZEN_EXT
 +              }
 +#endif
        } else
                g_strfreev(nameservers);
  
@@@ -693,9 -638,6 +693,9 @@@ static void set_address(int ifindex, st
                /* Is this prefix part of the subnet we are suppose to use? */
                prefix_len = check_ipv6_addr_prefix(prefixes, address);
  
 +#if defined TIZEN_EXT
 +              char *gateway = g_strdup(__connman_ipconfig_get_gateway(ipconfig));
 +#endif
                __connman_ipconfig_address_remove(ipconfig);
                __connman_ipconfig_set_local(ipconfig, address);
                __connman_ipconfig_set_prefixlen(ipconfig, prefix_len);
                DBG("new address %s/%d", address, prefix_len);
  
                __connman_ipconfig_set_dhcp_address(ipconfig, address);
 +#if defined TIZEN_EXT
 +              DBG("Set gateway %s", gateway);
 +              __connman_ipconfig_set_gateway(ipconfig, gateway);
 +              g_free(gateway);
 +#endif
                __connman_service_save(
                        __connman_service_lookup_from_index(ifindex));
        }
@@@ -1008,7 -945,7 +1008,7 @@@ static void do_dad(GDHCPClient *dhcp_cl
  
                ref_own_address(user_data);
  
-               if (inet_pton(AF_INET6, address, &addr) < 0) {
+               if (inet_pton(AF_INET6, address, &addr) != 1) {
                        DBG("Invalid IPv6 address %s %d/%s", address,
                                -errno, strerror(errno));
                        goto fail;
@@@ -1776,9 -1713,7 +1776,9 @@@ static gboolean timeout_solicitation(gp
  static int dhcpv6_solicitation(struct connman_dhcpv6 *dhcp)
  {
        struct connman_service *service;
 +#if !defined TIZEN_EXT
        struct connman_ipconfig *ipconfig_ipv6;
 +#endif
        GDHCPClient *dhcp_client;
        GDHCPClientError error;
        int index, ret;
                return -EINVAL;
        }
  
 +#if !defined TIZEN_EXT
        if (getenv("CONNMAN_DHCPV6_DEBUG"))
 +#endif
                g_dhcp_client_set_debug(dhcp_client, dhcpv6_debug, "DHCPv6");
  
        service = connman_service_lookup_from_network(dhcp->network);
        g_dhcpv6_client_set_oro(dhcp_client, 3, G_DHCPV6_DNS_SERVERS,
                                G_DHCPV6_DOMAIN_LIST, G_DHCPV6_SNTP_SERVERS);
  
 +#if defined TIZEN_EXT
 +      /**
 +        When privacy extension is enabled then connman requests
 +        OPTION_IA_TA (4) from DHCPv6 server. This option is used to request
 +        temporary IPv6 address from DHCPv6 server but we found that DHCPv6
 +        server never provided temporary IPv6 address and connman resend dhcpv6
 +        requests. So always set OPTION_IA_NA in dhcpv6 request to get IPv6
 +        address from DHCPv6 server.
 +       */
 +      dhcp->use_ta = FALSE;
 +#else
        ipconfig_ipv6 = __connman_service_get_ip6config(service);
        dhcp->use_ta = __connman_ipconfig_ipv6_privacy_enabled(ipconfig_ipv6);
 +#endif
  
        g_dhcpv6_client_set_ia(dhcp_client, index,
                        dhcp->use_ta ? G_DHCPV6_IA_TA : G_DHCPV6_IA_NA,
@@@ -2124,9 -2045,7 +2124,9 @@@ static GDHCPClient *create_pd_client(st
                return NULL;
        }
  
 +#if !defined TIZEN_EXT
        if (getenv("CONNMAN_DHCPV6_DEBUG"))
 +#endif
                g_dhcp_client_set_debug(dhcp_client, dhcpv6_debug, "DHCPv6:PD");
  
        service = connman_service_lookup_from_network(dhcp->network);
diff --combined src/dnsproxy.c
index 7956e7f,38dbdd7..18dc648
mode 100755,100644..100755
  
  #include "connman.h"
  
 +#if defined TIZEN_EXT
 +#include <sys/smack.h>
 +#include <systemd/sd-daemon.h>
 +#endif
 +
  #define debug(fmt...) do { } while (0)
  
  #if __BYTE_ORDER == __LITTLE_ENDIAN
@@@ -204,11 -199,7 +204,11 @@@ struct domain_rr 
   * By default the TTL (time-to-live) of the DNS response is used
   * when setting the cache entry life time. The value is in seconds.
   */
 +#if defined TIZEN_EXT
 +#define MAX_CACHE_TTL (60 * 60)
 +#else
  #define MAX_CACHE_TTL (60 * 30)
 +#endif
  /*
   * Also limit the other end, cache at least for 30 seconds.
   */
@@@ -227,22 -218,12 +227,22 @@@ static int cache_size
  static GHashTable *cache;
  static int cache_refcount;
  static GSList *server_list = NULL;
 +#if defined TIZEN_EXT
 +static GSList *server_list_sec = NULL;
 +#endif
  static GSList *request_list = NULL;
  static GHashTable *listener_table = NULL;
  static time_t next_refresh;
  static GHashTable *partial_tcp_req_table;
  static guint cache_timer = 0;
  
 +#if defined TIZEN_EXT
 +static void destroy_server_sec(struct server_data *server);
 +static struct server_data *create_server_sec(int index,
 +              const char *domain, const char *server,
 +              int protocol);
 +#endif
 +
  static guint16 get_id(void)
  {
        uint64_t rand;
@@@ -510,30 -491,22 +510,30 @@@ static void send_response(int sk, unsig
                return;
  
        hdr = (void *) (buf + offset);
 +#if !defined TIZEN_EXT
        if (offset) {
                buf[0] = 0;
                buf[1] = sizeof(*hdr);
        }
 +#endif
  
        debug("id 0x%04x qr %d opcode %d", hdr->id, hdr->qr, hdr->opcode);
  
        hdr->qr = 1;
        hdr->rcode = ns_r_servfail;
  
 +#if !defined TIZEN_EXT
        hdr->qdcount = 0;
 +#endif
        hdr->ancount = 0;
        hdr->nscount = 0;
        hdr->arcount = 0;
  
 +#if defined TIZEN_EXT
 +      err = sendto(sk, buf, len, MSG_NOSIGNAL, to, tolen);
 +#else
        err = sendto(sk, buf, sizeof(*hdr) + offset, MSG_NOSIGNAL, to, tolen);
 +#endif
        if (err < 0) {
                connman_error("Failed to send DNS response to %d: %s",
                                sk, strerror(errno));
@@@ -1679,31 -1652,6 +1679,31 @@@ static int ns_resolv(struct server_dat
                }
        }
  
 +#if defined TIZEN_EXT
 +      if (server->protocol == IPPROTO_UDP) {
 +              GList *domains;
 +              struct server_data *new_server = NULL;
 +
 +              new_server = create_server_sec(server->index, NULL,
 +                                              server->server, IPPROTO_UDP);
 +
 +              if (new_server != NULL) {
 +                      for (domains = server->domains; domains;
 +                                              domains = domains->next) {
 +                              char *dom = domains->data;
 +
 +                              DBG("Adding domain %s to %s",
 +                                              dom, new_server->server);
 +
 +                              new_server->domains = g_list_append(
 +                                              new_server->domains,
 +                                                      g_strdup(dom));
 +                      }
 +
 +                      server = new_server;
 +              }
 +      }
 +#endif
        sk = g_io_channel_unix_get_fd(server->channel);
  
        err = sendto(sk, request, req->request_len, MSG_NOSIGNAL,
@@@ -1819,6 -1767,7 +1819,7 @@@ static char *uncompress(int16_t field_c
                        char **uncompressed_ptr)
  {
        char *uptr = *uncompressed_ptr; /* position in result buffer */
+       char * const uncomp_end = uncompressed + uncomp_len - 1;
  
        debug("count %d ptr %p end %p uptr %p", field_count, ptr, end, uptr);
  
                 * tmp buffer.
                 */
  
-               ulen = strlen(name);
-               strncpy(uptr, name, uncomp_len - (uptr - uncompressed));
+               ulen = strlen(name) + 1;
+               if ((uptr + ulen) > uncomp_end)
+                       goto out;
+               strncpy(uptr, name, ulen);
  
                debug("pos %d ulen %d left %d name %s", pos, ulen,
-                       (int)(uncomp_len - (uptr - uncompressed)), uptr);
+                       (int)(uncomp_end - (uptr + ulen)), uptr);
  
                uptr += ulen;
-               *uptr++ = '\0';
  
                ptr += pos;
  
                 * We copy also the fixed portion of the result (type, class,
                 * ttl, address length and the address)
                 */
+               if ((uptr + NS_RRFIXEDSZ) > uncomp_end) {
+                       debug("uncompressed data too large for buffer");
+                       goto out;
+               }
                memcpy(uptr, ptr, NS_RRFIXEDSZ);
  
                dns_type = uptr[0] << 8 | uptr[1];
                } else if (dns_type == ns_t_a || dns_type == ns_t_aaaa) {
                        dlen = uptr[-2] << 8 | uptr[-1];
  
-                       if (ptr + dlen > end) {
+                       if ((ptr + dlen) > end || (uptr + dlen) > uncomp_end) {
                                debug("data len %d too long", dlen);
                                goto out;
                        }
                         * refresh interval, retry interval, expiration
                         * limit and minimum ttl). They are 20 bytes long.
                         */
+                       if ((uptr + 20) > uncomp_end || (ptr + 20) > end) {
+                               debug("soa record too long");
+                               goto out;
+                       }
                        memcpy(uptr, ptr, 20);
                        uptr += 20;
                        ptr += 20;
@@@ -2177,15 -2135,8 +2187,15 @@@ static int forward_dns_reply(unsigned c
                req->resplen = 0;
  
                req->resp = g_try_malloc(reply_len);
 +#if defined TIZEN_EXT
 +              if (!req->resp) {
 +                      g_free(new_reply);
 +                      return -ENOMEM;
 +              }
 +#else
                if (!req->resp)
                        return -ENOMEM;
 +#endif
  
                memcpy(req->resp, reply, reply_len);
                req->resplen = reply_len;
@@@ -2306,19 -2257,6 +2316,19 @@@ static gboolean udp_server_event(GIOCha
        if (len >= 12)
                forward_dns_reply(buf, len, IPPROTO_UDP, data);
  
 +#if defined TIZEN_EXT
 +      GSList *list;
 +
 +      for (list = server_list_sec; list; list = list->next) {
 +              struct server_data *new_data = list->data;
 +
 +              if (new_data == data) {
 +                      destroy_server_sec(data);
 +                      return TRUE;
 +              }
 +      }
 +#endif
 +
        return TRUE;
  }
  
@@@ -2629,177 -2567,6 +2639,177 @@@ static void enable_fallback(bool enable
        }
  }
  
 +#if defined TIZEN_EXT
 +
 +static void destroy_server_sec(struct server_data *server)
 +{
 +      GList *list;
 +      int fd;
 +
 +      if (server->channel)
 +              fd = g_io_channel_unix_get_fd(server->channel);
 +      else
 +              fd = -1;
 +
 +      DBG("index %d server %s sock %d", server->index, server->server, fd);
 +
 +      server_list_sec = g_slist_remove(server_list_sec, server);
 +
 +      if (fd > 0)
 +              close(fd);
 +
 +      server_destroy_socket(server);
 +
 +      if (server->protocol == IPPROTO_UDP && server->enabled)
 +              DBG("Removing DNS server %s", server->server);
 +
 +      g_free(server->server);
 +      for (list = server->domains; list; list = list->next) {
 +              char *domain = list->data;
 +
 +              server->domains = g_list_remove(server->domains, domain);
 +              g_free(domain);
 +      }
 +      g_free(server->server_addr);
 +
 +      /*
 +       * We do not remove cache right away but delay it few seconds.
 +       * The idea is that when IPv6 DNS server is added via RDNSS, it has a
 +       * lifetime. When the lifetime expires we decrease the refcount so it
 +       * is possible that the cache is then removed. Because a new DNS server
 +       * is usually created almost immediately we would then loose the cache
 +       * without any good reason. The small delay allows the new RDNSS to
 +       * create a new DNS server instance and the refcount does not go to 0.
 +       */
 +      /* TODO: Need to check this */
 +      /* g_timeout_add_seconds(3, try_remove_cache, NULL); */
 +
 +      g_free(server);
 +}
 +
 +static void destroy_all_server_sec()
 +{
 +      GSList *list;
 +
 +      DBG("remove all dns server");
 +
 +      for (list = server_list_sec; list; list = list->next) {
 +              struct server_data *server = list->data;
 +              destroy_server_sec(server);
 +      }
 +      server_list_sec = NULL;
 +}
 +
 +static gboolean sec_udp_idle_timeout(gpointer user_data)
 +{
 +      struct server_data *server = user_data;
 +
 +      DBG("");
 +
 +      if (server == NULL)
 +              return FALSE;
 +
 +      destroy_server_sec(server);
 +
 +      return FALSE;
 +}
 +
 +static struct server_data *create_server_sec(int index,
 +                                      const char *domain, const char *server,
 +                                      int protocol)
 +{
 +      struct server_data *data;
 +      struct addrinfo hints, *rp;
 +      int ret;
 +
 +      DBG("index %d server %s", index, server);
 +
 +      data = g_try_new0(struct server_data, 1);
 +      if (data == NULL) {
 +              connman_error("Failed to allocate server %s data", server);
 +              return NULL;
 +      }
 +
 +      data->index = index;
 +      if (domain)
 +              data->domains = g_list_append(data->domains, g_strdup(domain));
 +      data->server = g_strdup(server);
 +      data->protocol = protocol;
 +
 +      memset(&hints, 0, sizeof(hints));
 +
 +      switch (protocol) {
 +      case IPPROTO_UDP:
 +              hints.ai_socktype = SOCK_DGRAM;
 +              break;
 +
 +      case IPPROTO_TCP:
 +              hints.ai_socktype = SOCK_STREAM;
 +              break;
 +
 +      default:
 +              destroy_server_sec(data);
 +              return NULL;
 +      }
 +      hints.ai_family = AF_UNSPEC;
 +      hints.ai_flags = AI_NUMERICSERV | AI_NUMERICHOST;
 +
 +      ret = getaddrinfo(data->server, "53", &hints, &rp);
 +      if (ret) {
 +              connman_error("Failed to parse server %s address: %s\n",
 +                              data->server, gai_strerror(ret));
 +              freeaddrinfo(rp);
 +              destroy_server_sec(data);
 +              return NULL;
 +      }
 +
 +      /* Do not blindly copy this code elsewhere; it doesn't loop over the
 +         results using ->ai_next as it should. That's OK in *this* case
 +         because it was a numeric lookup; we *know* there's only one. */
 +
 +      data->server_addr_len = rp->ai_addrlen;
 +
 +      switch (rp->ai_family) {
 +      case AF_INET:
 +              data->server_addr = (struct sockaddr *)
 +                                      g_try_new0(struct sockaddr_in, 1);
 +              break;
 +      case AF_INET6:
 +              data->server_addr = (struct sockaddr *)
 +                                      g_try_new0(struct sockaddr_in6, 1);
 +              break;
 +      default:
 +              connman_error("Wrong address family %d", rp->ai_family);
 +              break;
 +      }
 +      if (data->server_addr == NULL) {
 +              freeaddrinfo(rp);
 +              destroy_server_sec(data);
 +              return NULL;
 +      }
 +      memcpy(data->server_addr, rp->ai_addr, rp->ai_addrlen);
 +      freeaddrinfo(rp);
 +
 +      if (server_create_socket(data) != 0) {
 +              destroy_server_sec(data);
 +              return NULL;
 +      }
 +
 +      if (protocol == IPPROTO_UDP) {
 +              /* Enable new servers by default */
 +              data->enabled = TRUE;
 +              DBG("Adding DNS server %s", data->server);
 +
 +              data->timeout = g_timeout_add_seconds(30, sec_udp_idle_timeout,
 +                                                              data);
 +
 +              server_list_sec = g_slist_append(server_list_sec, data);
 +      }
 +
 +      return data;
 +}
 +#endif
 +
  static struct server_data *create_server(int index,
                                        const char *domain, const char *server,
                                        int protocol)
@@@ -3090,10 -2857,6 +3100,10 @@@ int __connman_dnsproxy_remove(int index
        remove_server(index, domain, server, IPPROTO_UDP);
        remove_server(index, domain, server, IPPROTO_TCP);
  
 +#if defined TIZEN_EXT
 +      destroy_all_server_sec();
 +#endif
 +
        return 0;
  }
  
@@@ -3124,6 -2887,7 +3134,7 @@@ static void dnsproxy_default_changed(st
        bool server_enabled = false;
        GSList *list;
        int index;
+       int vpn_index;
  
        DBG("service %p", service);
  
        if (index < 0)
                return;
  
+       /*
+        * In case non-split-routed VPN is set as split routed the DNS servers
+        * the VPN must be enabled as well, when the transport becomes the
+        * default service.
+        */
+       vpn_index = __connman_connection_get_vpn_index(index);
        for (list = server_list; list; list = list->next) {
                struct server_data *data = list->data;
  
                        DBG("Enabling DNS server %s", data->server);
                        data->enabled = true;
                        server_enabled = true;
+               } else if (data->index == vpn_index) {
+                       DBG("Enabling DNS server of VPN %s", data->server);
+                       data->enabled = true;
                } else {
                        DBG("Disabling DNS server %s", data->server);
                        data->enabled = false;
@@@ -3588,23 -3362,6 +3609,23 @@@ static gboolean client_timeout(gpointe
        return FALSE;
  }
  
 +#if defined TIZEN_EXT
 +static void recover_listener(GIOChannel *channel, struct listener_data *ifdata)
 +{
 +      int sk, index;
 +
 +      index = ifdata->index;
 +
 +      sk = g_io_channel_unix_get_fd(channel);
 +      close(sk);
 +
 +      __connman_dnsproxy_remove_listener(index);
 +
 +      if (__connman_dnsproxy_add_listener(index) == 0)
 +              DBG("listener %d successfully recovered", index);
 +}
 +#endif
 +
  static bool tcp_listener_event(GIOChannel *channel, GIOCondition condition,
                                struct listener_data *ifdata, int family,
                                guint *listener_watch)
                condition, channel, ifdata, family);
  
        if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
 +#if defined TIZEN_EXT
 +              connman_error("Error %d with TCP listener channel", condition);
 +
 +              recover_listener(channel, ifdata);
 +#else
                if (*listener_watch > 0)
                        g_source_remove(*listener_watch);
                *listener_watch = 0;
  
                connman_error("Error with TCP listener channel");
 +#endif
  
                return false;
        }
         * The packet length bytes do not contain the total message length,
         * that is the reason to -2 below.
         */
 +#if defined TIZEN_EXT
 +      if (msg_len > (unsigned int)(len - 2)) {
 +#else
        if (msg_len != (unsigned int)(len - 2)) {
 +#endif
                debug("client %d sent %d bytes but expecting %u pending %d",
                        client_sk, len, msg_len + 2, msg_len + 2 - len);
  
@@@ -3782,39 -3529,6 +3803,39 @@@ static gboolean tcp6_listener_event(GIO
                                &ifdata->tcp6_listener_watch);
  }
  
 +#if defined TIZEN_EXT
 +struct request_data * create_request(int sk, unsigned char *buf, size_t len,
 +                                const struct sockaddr *to, socklen_t tolen,
 +                                int protocol)
 +{
 +      struct request_data *req;
 +      req = g_try_new0(struct request_data, 1);
 +      if (!req)
 +              return NULL;
 +      memcpy(&req->sa, to, tolen);
 +      req->sa_len = tolen;
 +      req->client_sk = sk;
 +      req->protocol = protocol;
 +      req->request_len = len;
 +      req->request = g_malloc(len);
 +      memcpy(req->request, buf, len);
 +      return req;
 +
 +}
 +static gboolean send_response_timeout (gpointer user_data)
 +{
 +      struct request_data *req = user_data;
 +
 +      send_response(req->client_sk, req->request,(size_t) req->request_len, (const struct sockaddr *)&req->sa,
 +                             (socklen_t)req->sa_len, req->protocol);
 +      g_free(req->request);
 +      g_free(req);
 +
 +      return FALSE;
 +
 +}
 +#endif
 +
  static bool udp_listener_event(GIOChannel *channel, GIOCondition condition,
                                struct listener_data *ifdata, int family,
                                guint *listener_watch)
        int sk, err, len;
  
        if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
 +#if defined TIZEN_EXT
 +              connman_error("Error %d with UDP listener channel", condition);
 +
 +              recover_listener(channel, ifdata);
 +#else
                connman_error("Error with UDP listener channel");
                *listener_watch = 0;
 +#endif
                return false;
        }
  
  
        err = parse_request(buf, len, query, sizeof(query));
        if (err < 0 || (g_slist_length(server_list) == 0)) {
 +#if defined TIZEN_EXT
 +              /** TEMP Fix
 +              * Reason: In tizen6.0 same code working fine because it seems some delay in 6.0 platform
 +              * where as in tizen6.5 this loop is continuously executing due to this unable to receive
 +              * the response from telephony deamon and wpa_supplicant. To stop continuously execution
 +              * of this code added 10ms delay.
 +              */
 +              req = create_request(sk, buf, len, client_addr,
 +                              *client_addr_len, IPPROTO_UDP);
 +              if(!req)
 +                      return true;;
 +              g_timeout_add(10, send_response_timeout, req);
 +#else
                send_response(sk, buf, len, client_addr,
                                *client_addr_len, IPPROTO_UDP);
 +#endif
                return true;
        }
  
        req->name = g_strdup(query);
        req->request = g_malloc(len);
        memcpy(req->request, buf, len);
 +#if defined TIZEN_EXT
 +      DBG("req %p dstid 0x%04x altid 0x%04x", req, req->dstid, req->altid);
 +      req->timeout = g_timeout_add_seconds(30, request_timeout, req);
 +#else
        req->timeout = g_timeout_add_seconds(5, request_timeout, req);
 +#endif
        request_list = g_slist_append(request_list, req);
  
        return true;
@@@ -3944,24 -3633,14 +3965,24 @@@ static GIOChannel *get_listener(int fam
  {
        GIOChannel *channel;
        const char *proto;
 +#if !defined TIZEN_EXT
        union {
                struct sockaddr sa;
                struct sockaddr_in6 sin6;
                struct sockaddr_in sin;
        } s;
        socklen_t slen;
 +#endif
        int sk, type;
 +#if !defined TIZEN_EXT
        char *interface;
 +#endif
 +#if defined TIZEN_EXT
 +      int option;
 +      int sd_num = 0;
 +      int rv;
 +      int is_socket_inet = 0;
 +#endif
  
        debug("family %d protocol %d index %d", family, protocol, index);
  
        default:
                return NULL;
        }
 +#if defined TIZEN_EXT
 +      sd_num = sd_listen_fds(0);
 +      DBG("socket type(%s) systemd number of fds(%d)", proto, sd_num);
 +      if(sd_num < 1){
 +              DBG("fail to get the fd from systemd");
 +              return NULL;
 +      }
 +
 +      if(protocol == IPPROTO_TCP)
 +              type = SOCK_STREAM;
 +      else
 +              type = SOCK_DGRAM;
 +
 +      for(sk = SD_LISTEN_FDS_START; sk < SD_LISTEN_FDS_START+sd_num; ++sk){
 +              rv = sd_is_socket_inet(sk, family, type, -1, 53);
 +              if(rv > 0){
 +                      DBG("socket fd (%d) is passed by systemd", sk);
 +                      is_socket_inet = 1;
 +                      break;
 +              }
 +      }
  
 +      if (!is_socket_inet) {
 +              DBG("socket fd is not matched what connman requests");
 +              return NULL;
 +      }
 +#else
        sk = socket(family, type, protocol);
        if (sk < 0 && family == AF_INET6 && errno == EAFNOSUPPORT) {
                connman_error("No IPv6 support");
                close(sk);
                return NULL;
        }
 +#endif
  
 +#if defined TIZEN_EXT
 +      /* When ConnMan crashed,
 +       * probably DNS listener cannot bind existing address */
 +      option = 1;
 +      if (setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)) < 0) {
 +              connman_error("Failed to set socket option SO_REUSEADDR");
 +              close(sk);
 +              return NULL;
 +      }
 +#endif
 +#if !defined TIZEN_EXT
        if (bind(sk, &s.sa, slen) < 0) {
                connman_error("Failed to bind %s listener socket", proto);
                close(sk);
                return NULL;
        }
 +#endif
  
        if (protocol == IPPROTO_TCP) {
  
 +#if !defined TIZEN_EXT
                if (listen(sk, 10) < 0) {
                        connman_error("Failed to listen on TCP socket %d/%s",
                                -errno, strerror(errno));
                        return NULL;
                }
  
 +#endif
                fcntl(sk, F_SETFL, O_NONBLOCK);
        }
  
@@@ -4127,68 -3765,40 +4148,68 @@@ static int create_dns_listener(int prot
                ifdata->tcp4_listener_channel = get_listener(AF_INET, protocol,
                                                        ifdata->index);
                if (ifdata->tcp4_listener_channel)
 +#if defined TIZEN_EXT
 +                      ifdata->tcp4_listener_watch =
 +                              g_io_add_watch(ifdata->tcp4_listener_channel,
 +                                      G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
 +                                      tcp4_listener_event, (gpointer)ifdata);
 +#else
                        ifdata->tcp4_listener_watch =
                                g_io_add_watch(ifdata->tcp4_listener_channel,
                                        G_IO_IN, tcp4_listener_event,
                                        (gpointer)ifdata);
 +#endif
                else
                        ret |= TCP_IPv4_FAILED;
  
                ifdata->tcp6_listener_channel = get_listener(AF_INET6, protocol,
                                                        ifdata->index);
                if (ifdata->tcp6_listener_channel)
 +#if defined TIZEN_EXT
 +                      ifdata->tcp6_listener_watch =
 +                              g_io_add_watch(ifdata->tcp6_listener_channel,
 +                                      G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
 +                                      tcp6_listener_event, (gpointer)ifdata);
 +#else
                        ifdata->tcp6_listener_watch =
                                g_io_add_watch(ifdata->tcp6_listener_channel,
                                        G_IO_IN, tcp6_listener_event,
                                        (gpointer)ifdata);
 +#endif
                else
                        ret |= TCP_IPv6_FAILED;
        } else {
                ifdata->udp4_listener_channel = get_listener(AF_INET, protocol,
                                                        ifdata->index);
                if (ifdata->udp4_listener_channel)
 +#if defined TIZEN_EXT
 +                      ifdata->udp4_listener_watch =
 +                              g_io_add_watch(ifdata->udp4_listener_channel,
 +                                      G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
 +                                      udp4_listener_event, (gpointer)ifdata);
 +#else
                        ifdata->udp4_listener_watch =
                                g_io_add_watch(ifdata->udp4_listener_channel,
                                        G_IO_IN, udp4_listener_event,
                                        (gpointer)ifdata);
 +#endif
                else
                        ret |= UDP_IPv4_FAILED;
  
                ifdata->udp6_listener_channel = get_listener(AF_INET6, protocol,
                                                        ifdata->index);
                if (ifdata->udp6_listener_channel)
 +#if defined TIZEN_EXT
 +                      ifdata->udp6_listener_watch =
 +                              g_io_add_watch(ifdata->udp6_listener_channel,
 +                                      G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
 +                                      udp6_listener_event, (gpointer)ifdata);
 +#else
                        ifdata->udp6_listener_watch =
                                g_io_add_watch(ifdata->udp6_listener_channel,
                                        G_IO_IN, udp6_listener_event,
                                        (gpointer)ifdata);
 +#endif
                else
                        ret |= UDP_IPv6_FAILED;
        }
diff --combined src/inet.c
@@@ -79,7 -79,8 +79,8 @@@ int __connman_inet_modify_address(int c
                                const char *address,
                                const char *peer,
                                unsigned char prefixlen,
-                               const char *broadcast)
+                               const char *broadcast,
+                               bool is_p2p)
  {
        uint8_t request[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
                        NLMSG_ALIGN(sizeof(struct ifaddrmsg)) +
@@@ -94,8 -95,9 +95,9 @@@
        int sk, err;
  
        DBG("cmd %#x flags %#x index %d family %d address %s peer %s "
-               "prefixlen %hhu broadcast %s", cmd, flags, index, family,
-               address, peer, prefixlen, broadcast);
+               "prefixlen %hhu broadcast %s p2p %s", cmd, flags, index,
+               family, address, peer, prefixlen, broadcast,
+               is_p2p ? "true" : "false");
  
        if (!address)
                return -EINVAL;
        ifaddrmsg->ifa_index = index;
  
        if (family == AF_INET) {
-               if (inet_pton(AF_INET, address, &ipv4_addr) < 1)
+               if (inet_pton(AF_INET, address, &ipv4_addr) != 1)
                        return -1;
  
-               if (broadcast)
-                       inet_pton(AF_INET, broadcast, &ipv4_bcast);
-               else
-                       ipv4_bcast.s_addr = ipv4_addr.s_addr |
-                               htonl(0xfffffffflu >> prefixlen);
                if (peer) {
-                       if (inet_pton(AF_INET, peer, &ipv4_dest) < 1)
+                       if (inet_pton(AF_INET, peer, &ipv4_dest) != 1)
                                return -1;
  
                        err = __connman_inet_rtnl_addattr_l(header,
                if (err < 0)
                        return err;
  
-               err = __connman_inet_rtnl_addattr_l(header,
-                                               sizeof(request),
-                                               IFA_BROADCAST,
-                                               &ipv4_bcast,
-                                               sizeof(ipv4_bcast));
-               if (err < 0)
-                       return err;
+               /*
+                * Broadcast address must not be added for P2P / VPN as
+                * getifaddrs() cannot interpret destination address.
+                */
+               if (!is_p2p) {
+                       if (broadcast)
+                               inet_pton(AF_INET, broadcast, &ipv4_bcast);
+                       else
+                               ipv4_bcast.s_addr = ipv4_addr.s_addr |
+                                       htonl(0xfffffffflu >> prefixlen);
  
+                       err = __connman_inet_rtnl_addattr_l(header,
+                                                       sizeof(request),
+                                                       IFA_BROADCAST,
+                                                       &ipv4_bcast,
+                                                       sizeof(ipv4_bcast));
+                       if (err < 0)
+                               return err;
+               }
        } else if (family == AF_INET6) {
-               if (inet_pton(AF_INET6, address, &ipv6_addr) < 1)
+               if (inet_pton(AF_INET6, address, &ipv6_addr) != 1)
                        return -1;
  
                err = __connman_inet_rtnl_addattr_l(header,
@@@ -189,85 -196,46 +196,118 @@@ 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;
        struct addrinfo hints;
        struct addrinfo *result = NULL;
-       struct sockaddr_in6 *in6 = NULL;
-       struct sockaddr_in *in4 = NULL;
  
        if (!address || !*address)
                goto out;
                goto out;
  
        if (result) {
-               if (result->ai_family == AF_INET6) {
-                       in6 = (struct sockaddr_in6*)result->ai_addr;
-                       ret = IN6_IS_ADDR_UNSPECIFIED(&in6->sin6_addr);
-               } else if (result->ai_family == AF_INET) {
-                       in4 = (struct sockaddr_in*)result->ai_addr;
-                       ret = in4->sin_addr.s_addr == INADDR_ANY;
-               }
+               ret = is_addr_unspec(result->ai_family, result->ai_addr);
                freeaddrinfo(result);
        }
  
@@@ -435,46 -396,6 +468,46 @@@ done
        return err;
  }
  
 +#if defined TIZEN_EXT
 +void connman_inet_update_device_ident(struct connman_device *device)
 +{
 +      int index;
 +      enum connman_device_type type;
 +      char *ident = NULL, *addr = NULL;
 +
 +      index = connman_device_get_index(device);
 +      type = connman_device_get_type(device);
 +
 +      switch (type) {
 +      case CONNMAN_DEVICE_TYPE_UNKNOWN:
 +              return;
 +      case CONNMAN_DEVICE_TYPE_ETHERNET:
 +      case CONNMAN_DEVICE_TYPE_GADGET:
 +      case CONNMAN_DEVICE_TYPE_WIFI:
 +              addr = index2addr(index);
 +              ident = index2ident(index, NULL);
 +              break;
 +      case CONNMAN_DEVICE_TYPE_CELLULAR:
 +              ident = index2ident(index, NULL);
 +              break;
 +      case CONNMAN_DEVICE_TYPE_BLUETOOTH:
 +      case CONNMAN_DEVICE_TYPE_GPS:
 +      case CONNMAN_DEVICE_TYPE_VENDOR:
 +              break;
 +      }
 +
 +      if (ident != NULL) {
 +              connman_device_set_ident(device, ident);
 +              g_free(ident);
 +      }
 +
 +      if (addr != NULL) {
 +              connman_device_set_string(device, "Address", addr);
 +              g_free(addr);
 +      }
 +}
 +#endif
 +
  bool connman_inet_is_ifup(int index)
  {
        int sk;
@@@ -521,18 -442,20 +554,20 @@@ int connman_inet_set_ipv6_address(int i
        int err;
        unsigned char prefix_len;
        const char *address;
+       bool is_p2p;
  
        if (!ipaddress->local)
                return 0;
  
        prefix_len = ipaddress->prefixlen;
        address = ipaddress->local;
+       is_p2p = ipaddress->is_p2p;
  
        DBG("index %d address %s prefix_len %d", index, address, prefix_len);
  
        err = __connman_inet_modify_address(RTM_NEWADDR,
                                NLM_F_REPLACE | NLM_F_ACK, index, AF_INET6,
-                               address, NULL, prefix_len, NULL);
+                               address, NULL, prefix_len, NULL, is_p2p);
        if (err < 0) {
                connman_error("%s: %s", __func__, strerror(-err));
                return err;
@@@ -546,6 -469,7 +581,7 @@@ int connman_inet_set_address(int index
        int err;
        unsigned char prefix_len;
        const char *address, *broadcast, *peer;
+       bool is_p2p;
  
        if (!ipaddress->local)
                return -1;
        address = ipaddress->local;
        broadcast = ipaddress->broadcast;
        peer = ipaddress->peer;
+       is_p2p = ipaddress->is_p2p;
  
        DBG("index %d address %s prefix_len %d", index, address, prefix_len);
  
        err = __connman_inet_modify_address(RTM_NEWADDR,
                                NLM_F_REPLACE | NLM_F_ACK, index, AF_INET,
-                               address, peer, prefix_len, broadcast);
+                               address, peer, prefix_len, broadcast, is_p2p);
        if (err < 0) {
                connman_error("%s: %s", __func__, strerror(-err));
                return err;
        return 0;
  }
  
- int connman_inet_clear_ipv6_address(int index, const char *address,
-                                                       int prefix_len)
+ int connman_inet_clear_ipv6_address(int index,
+                                       struct connman_ipaddress *ipaddress)
  {
        int err;
+       int prefix_len;
+       const char *address;
+       bool is_p2p;
+       address = ipaddress->local;
+       prefix_len = ipaddress->prefixlen;
+       is_p2p = ipaddress->is_p2p;
  
        DBG("index %d address %s prefix_len %d", index, address, prefix_len);
  
                return -EINVAL;
  
        err = __connman_inet_modify_address(RTM_DELADDR, 0, index, AF_INET6,
-                               address, NULL, prefix_len, NULL);
+                               address, NULL, prefix_len, NULL, is_p2p);
        if (err < 0) {
                connman_error("%s: %s", __func__, strerror(-err));
                return err;
@@@ -593,11 -525,13 +637,13 @@@ int connman_inet_clear_address(int inde
        int err;
        unsigned char prefix_len;
        const char *address, *broadcast, *peer;
+       bool is_p2p;
  
        prefix_len = ipaddress->prefixlen;
        address = ipaddress->local;
        broadcast = ipaddress->broadcast;
        peer = ipaddress->peer;
+       is_p2p = ipaddress->is_p2p;
  
        DBG("index %d address %s prefix_len %d peer %s broadcast %s", index,
                address, prefix_len, peer, broadcast);
                return -EINVAL;
  
        err = __connman_inet_modify_address(RTM_DELADDR, 0, index, AF_INET,
-                               address, peer, prefix_len, broadcast);
+                               address, peer, prefix_len, broadcast, is_p2p);
        if (err < 0) {
                connman_error("%s: %s", __func__, strerror(-err));
                return err;
@@@ -773,7 -707,7 +819,7 @@@ int connman_inet_del_ipv6_network_route
  
        rt.rtmsg_dst_len = prefix_len;
  
-       if (inet_pton(AF_INET6, host, &rt.rtmsg_dst) < 0) {
+       if (inet_pton(AF_INET6, host, &rt.rtmsg_dst) != 1) {
                err = -errno;
                goto out;
        }
@@@ -823,7 -757,7 +869,7 @@@ int connman_inet_add_ipv6_network_route
  
        rt.rtmsg_dst_len = prefix_len;
  
-       if (inet_pton(AF_INET6, host, &rt.rtmsg_dst) < 0) {
+       if (inet_pton(AF_INET6, host, &rt.rtmsg_dst) != 1) {
                err = -errno;
                goto out;
        }
         */
  
        if (gateway && !__connman_inet_is_any_addr(gateway, AF_INET6) &&
-               inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) > 0)
+               inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) == 1)
                rt.rtmsg_flags |= RTF_GATEWAY;
  
        rt.rtmsg_metric = 1;
@@@ -882,7 -816,7 +928,7 @@@ int connman_inet_clear_ipv6_gateway_add
  
        memset(&rt, 0, sizeof(rt));
  
-       if (inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) < 0) {
+       if (inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) != 1) {
                err = -errno;
                goto out;
        }
        return err;
  }
  
- bool connman_inet_compare_subnet(int index, const char *host)
+ #define ADDR_TYPE_MAX 4
+ struct interface_address {
+       int index;
+       int family;
+       bool allow_unspec;
+        /* Applies only to ADDR_TYPE_IPADDR in ipaddrs */
+       bool require_ll;
+       /* Real types must be in_addr for AF_INET and in6_addr for AF_INET6 */
+       void *ipaddrs[ADDR_TYPE_MAX];
+ };
+ enum ipaddr_type {
+       ADDR_TYPE_IPADDR = 0,
+       ADDR_TYPE_NETMASK,
+       ADDR_TYPE_BRDADDR,
+       ADDR_TYPE_DSTADDR
+ };
+ static int get_interface_addresses(struct interface_address *if_addr)
  {
-       struct ifreq ifr;
-       struct in_addr _host_addr;
-       in_addr_t host_addr, netmask_addr, if_addr;
-       struct sockaddr_in *netmask, *addr;
-       int sk;
+       struct ifaddrs *ifaddr;
+       struct ifaddrs *ifa;
+       struct sockaddr *addrs[ADDR_TYPE_MAX] = { 0 };
+       struct sockaddr_in *addr_in;
+       struct sockaddr_in6 *addr_in6;
+       char name[IF_NAMESIZE] = { 0 };
+       size_t len;
+       int err = -ENOENT;
+       int i;
  
-       DBG("host %s", host);
+       if (!if_addr)
+               return -EINVAL;
  
-       if (!host)
-               return false;
+       if (!if_indextoname(if_addr->index, name))
+               return -EINVAL;
  
-       if (inet_aton(host, &_host_addr) == 0)
-               return false;
-       host_addr = _host_addr.s_addr;
+       DBG("index %d interface %s", if_addr->index, name);
  
-       sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
-       if (sk < 0)
-               return false;
+       if (getifaddrs(&ifaddr) < 0) {
+               connman_error("Cannot get addresses err %d/%s", errno,
+                                                       strerror(errno));
+               return -errno;
+       }
  
-       memset(&ifr, 0, sizeof(ifr));
-       ifr.ifr_ifindex = index;
+       for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
+               if (!ifa->ifa_addr)
+                       continue;
  
-       if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
-               close(sk);
-               return false;
+               if (g_strcmp0(ifa->ifa_name, name) ||
+                                       ifa->ifa_addr->sa_family !=
+                                               if_addr->family)
+                       continue;
+               if (if_addr->ipaddrs[ADDR_TYPE_IPADDR]) {
+                       if (!if_addr->allow_unspec && is_addr_unspec(
+                                               if_addr->family,
+                                               ifa->ifa_addr))
+                               continue;
+                       if (if_addr->require_ll && !is_addr_ll(if_addr->family,
+                                               ifa->ifa_addr))
+                               continue;
+                       addrs[ADDR_TYPE_IPADDR] = ifa->ifa_addr;
+               }
+               if (if_addr->ipaddrs[ADDR_TYPE_NETMASK]) {
+                       if (!if_addr->allow_unspec && is_addr_unspec(
+                                               if_addr->family,
+                                               ifa->ifa_netmask))
+                               continue;
+                       addrs[ADDR_TYPE_NETMASK] = ifa->ifa_netmask;
+               }
+               if (if_addr->ipaddrs[ADDR_TYPE_BRDADDR] &&
+                                       (ifa->ifa_flags & IFF_BROADCAST)) {
+                       if (!if_addr->allow_unspec && is_addr_unspec(
+                                               if_addr->family,
+                                               ifa->ifa_ifu.ifu_broadaddr))
+                               continue;
+                       addrs[ADDR_TYPE_BRDADDR] = ifa->ifa_ifu.ifu_broadaddr;
+               }
+               if (if_addr->ipaddrs[ADDR_TYPE_DSTADDR] &&
+                                       (ifa->ifa_flags & IFF_POINTOPOINT)) {
+                       if (!if_addr->allow_unspec && is_addr_unspec(
+                                               if_addr->family,
+                                               ifa->ifa_ifu.ifu_dstaddr))
+                               continue;
+                       addrs[ADDR_TYPE_DSTADDR] = ifa->ifa_ifu.ifu_dstaddr;
+               }
+               err = 0;
+               break;
        }
  
-       if (ioctl(sk, SIOCGIFNETMASK, &ifr) < 0) {
-               close(sk);
-               return false;
+       if (err)
+               goto out;
+       for (i = 0; i < ADDR_TYPE_MAX; i++) {
+               if (!addrs[i])
+                       continue;
+               switch (if_addr->family) {
+               case AF_INET:
+                       len = sizeof(struct in_addr);
+                       addr_in = (struct sockaddr_in*) addrs[i];
+                       memcpy(if_addr->ipaddrs[i], &addr_in->sin_addr, len);
+                       break;
+               case AF_INET6:
+                       len = sizeof(struct in6_addr);
+                       addr_in6 = (struct sockaddr_in6*) addrs[i];
+                       memcpy(if_addr->ipaddrs[i], &addr_in6->sin6_addr, len);
+                       break;
+               default:
+                       err = -EINVAL;
+                       break;
+               }
        }
  
-       netmask = (struct sockaddr_in *)&ifr.ifr_netmask;
-       netmask_addr = netmask->sin_addr.s_addr;
+ out:
+       freeifaddrs(ifaddr);
+       return err;
+ }
  
-       if (ioctl(sk, SIOCGIFADDR, &ifr) < 0) {
-               close(sk);
+ bool connman_inet_compare_subnet(int index, const char *host)
+ {
+       struct interface_address if_addr = { 0 };
+       struct in_addr iaddr = { 0 };
+       struct in_addr imask = { 0 };
+       struct in_addr haddr = { 0 };
+       DBG("host %s", host);
+       if (!host)
                return false;
-       }
  
-       close(sk);
+       if (inet_pton(AF_INET, host, &haddr) != 1)
+               return false;
  
-       addr = (struct sockaddr_in *)&ifr.ifr_addr;
-       if_addr = addr->sin_addr.s_addr;
+       if_addr.index = index;
+       if_addr.family = AF_INET;
+       if_addr.ipaddrs[ADDR_TYPE_IPADDR] = &iaddr;
+       if_addr.ipaddrs[ADDR_TYPE_NETMASK] = &imask;
  
-       return ((if_addr & netmask_addr) == (host_addr & netmask_addr));
+       if (get_interface_addresses(&if_addr))
+               return false;
+       return (iaddr.s_addr & imask.s_addr) == (haddr.s_addr & imask.s_addr);
  }
  
  static bool mem_mask_equal(const void *a, const void *b,
  
  bool connman_inet_compare_ipv6_subnet(int index, const char *host)
  {
-       struct ifaddrs *ifaddr, *ifa;
-       bool rv = false;
-       char name[IF_NAMESIZE];
-       struct in6_addr haddr;
-       if (inet_pton(AF_INET6, host, &haddr) <= 0)
-               return false;
+       struct interface_address addr = { 0 };
+       struct in6_addr iaddr = { 0 };
+       struct in6_addr imask = { 0 };
+       struct in6_addr haddr = { 0 };
  
-       if (!if_indextoname(index, name))
+       if (inet_pton(AF_INET6, host, &haddr) != 1)
                return false;
  
-       DBG("index %d interface %s", index, name);
+       addr.index = index;
+       addr.family = AF_INET6;
+       addr.ipaddrs[ADDR_TYPE_IPADDR] = &iaddr;
+       addr.ipaddrs[ADDR_TYPE_NETMASK] = &imask;
  
-       if (getifaddrs(&ifaddr) < 0) {
-               DBG("Cannot get addresses err %d/%s", errno, strerror(errno));
+       if (get_interface_addresses(&addr))
                return false;
-       }
-       for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
-               struct sockaddr_in6 *iaddr;
-               struct sockaddr_in6 *imask;
-               if (!ifa->ifa_addr)
-                       continue;
-               if (strncmp(ifa->ifa_name, name, IF_NAMESIZE) != 0 ||
-                                       ifa->ifa_addr->sa_family != AF_INET6)
-                       continue;
-               iaddr = (struct sockaddr_in6 *)ifa->ifa_addr;
-               imask = (struct sockaddr_in6 *)ifa->ifa_netmask;
-               rv = mem_mask_equal(&iaddr->sin6_addr, &haddr,
-                                       &imask->sin6_addr,
-                                       sizeof(haddr));
-               goto out;
-       }
  
- out:
-       freeifaddrs(ifaddr);
-       return rv;
+       return mem_mask_equal(&iaddr, &haddr, &imask, sizeof(haddr));
  }
  
  int connman_inet_remove_from_bridge(int index, const char *bridge)
@@@ -1539,36 -1556,6 +1668,36 @@@ static int icmpv6_recv(int fd, struct x
                return -errno;
        }
  
 +#if defined TIZEN_EXT
 +      /* Set Received Source Address from router as IPv6 Gateway Address */
 +      char src_addr[INET6_ADDRSTRLEN];
 +      if(inet_ntop(AF_INET6, &(saddr.sin6_addr), src_addr, INET6_ADDRSTRLEN)
 +                      == NULL)
 +              return -errno;
 +
 +      DBG("Received Source Address %s from router", src_addr);
 +
 +      /* icmpv6_recv() function can be called in two scenarios :
 +       * 1. When __connman_inet_ipv6_send_rs() is called from check_dhcpv6()
 +       * 2. When __connman_inet_ipv6_send_rs() is called from
 +       * __connman_6to4_probe()
 +       * In the second case it is not  required to set DHCPv6 Gateway  Address
 +       * as DHCPv6 was not started and  network structure was not passed as
 +       * user_data. If it is tried  to add Source Address as  Gateway Address
 +       * then it will lead to  crash because of  user_data being ip_address
 +       * instead of network structure. So Adding Gateway Address in case 1st
 +       * case only.
 +       */
 +      char *address = data->user_data;
 +      int err = 0;
 +      unsigned char buffer[sizeof(struct in6_addr)] = {0, };
 +      /* Checking if user_data is an ip_address */
 +      err = inet_pton(AF_INET, address, buffer);
 +      /* Setting Received Source Address from
 +       * router as Gateway Address */
 +      if(err <= 0)
 +              __connman_network_set_auto_ipv6_gateway(src_addr, data->user_data);
 +#endif
        hdr = (struct nd_router_advert *)buf;
        DBG("code %d len %zd hdr %zd", hdr->nd_ra_code, len,
                                sizeof(struct nd_router_advert));
@@@ -1668,9 -1655,6 +1797,9 @@@ static int ndisc_send_unspec(int type, 
        char cbuf[CMSG_SPACE(sizeof(*pinfo))];
        struct iovec iov[2];
        int fd, datalen, ret, iovlen = 1;
 +#if defined TIZEN_EXT
 +      char ebuf[256];
 +#endif
  
        DBG("");
  
        msgh.msg_controllen = cmsg->cmsg_len;
  
        ret = sendmsg(fd, &msgh, 0);
 +#if defined TIZEN_EXT
 +      DBG("sendmsg errno: %d/%s", errno, strerror_r(errno, ebuf, sizeof(ebuf)));
 +#endif
  
        close(fd);
        return ret;
@@@ -2295,98 -2276,156 +2424,156 @@@ GSList *__connman_inet_ipv6_get_prefixe
        return prefixes;
  }
  
static int get_dest_addr(int family, int index, char *buf, int len)
int connman_inet_get_dest_addr(int index, char **dest)
  {
-       struct ifreq ifr;
-       void *addr;
-       int sk;
+       struct interface_address if_addr = { 0 };
+       struct in_addr dstaddr = { 0 };
+       char buf[INET_ADDRSTRLEN] = { 0 };
+       int err;
  
-       sk = socket(family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
-       if (sk < 0)
-               return -errno;
+       if (!dest)
+               return -EINVAL;
  
-       memset(&ifr, 0, sizeof(ifr));
-       ifr.ifr_ifindex = index;
+       if_addr.index = index;
+       if_addr.family = AF_INET;
+       if_addr.allow_unspec = true;
+       if_addr.ipaddrs[ADDR_TYPE_DSTADDR] = &dstaddr;
  
-       if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
-               DBG("SIOCGIFNAME (%d/%s)", errno, strerror(errno));
-               close(sk);
-               return -errno;
-       }
+       err = get_interface_addresses(&if_addr);
+       if (err)
+               return err;
  
-       if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
-               DBG("SIOCGIFFLAGS (%d/%s)", errno, strerror(errno));
-               close(sk);
-               return -errno;
-       }
+       if (inet_ntop(AF_INET, &dstaddr, buf, INET_ADDRSTRLEN))
+               *dest = g_strdup(buf);
  
-       if ((ifr.ifr_flags & IFF_POINTOPOINT) == 0) {
-               close(sk);
-               errno = EINVAL;
-               return -errno;
-       }
+       DBG("destination %s", *dest);
  
-       DBG("index %d %s", index, ifr.ifr_name);
+       return *dest && **dest ? 0 : -ENOENT;
+ }
  
-       if (ioctl(sk, SIOCGIFDSTADDR, &ifr) < 0) {
-               connman_error("Get destination address failed (%s)",
-                                                       strerror(errno));
-               close(sk);
-               return -errno;
-       }
+ int connman_inet_ipv6_get_dest_addr(int index, char **dest)
+ {
+       struct interface_address if_addr = { 0 };
+       struct in_addr dstaddr = { 0 };
+       char buf[INET6_ADDRSTRLEN] = { 0 };
+       int err;
  
-       close(sk);
+       if (!dest)
+               return -EINVAL;
  
-       switch (family) {
-       case AF_INET:
-               addr = &((struct sockaddr_in *)&ifr.ifr_dstaddr)->sin_addr;
-               break;
-       case AF_INET6:
-               addr = &((struct sockaddr_in6 *)&ifr.ifr_dstaddr)->sin6_addr;
-               break;
-       default:
-               errno = EINVAL;
-               return -errno;
-       }
+       if_addr.index = index;
+       if_addr.family = AF_INET6;
+       if_addr.allow_unspec = true;
+       if_addr.ipaddrs[ADDR_TYPE_DSTADDR] = &dstaddr;
  
-       if (!inet_ntop(family, addr, buf, len)) {
-               DBG("error %d/%s", errno, strerror(errno));
-               return -errno;
-       }
+       err = get_interface_addresses(&if_addr);
+       if (err)
+               return err;
  
-       return 0;
+       if (inet_ntop(AF_INET6, &dstaddr, buf, INET6_ADDRSTRLEN))
+               *dest = g_strdup(buf);
+       DBG("destination %s", *dest);
+       return *dest && **dest ? 0 : -ENOENT;
  }
  
- int connman_inet_get_dest_addr(int index, char **dest)
+ /* destination is optional */
+ int connman_inet_get_route_addresses(int index, char **network, char **netmask,
+                                                       char **destination)
  {
-       char addr[INET_ADDRSTRLEN];
-       int ret;
+       struct interface_address if_addr = { 0 };
+       struct in_addr addr = { 0 };
+       struct in_addr mask = { 0 };
+       struct in_addr dest = { 0 };
+       struct in_addr nw_addr = { 0 };
+       char buf[INET_ADDRSTRLEN] = { 0 };
+       int err;
  
-       ret = get_dest_addr(PF_INET, index, addr, INET_ADDRSTRLEN);
-       if (ret < 0)
-               return ret;
+       if (!network || !netmask)
+               return -EINVAL;
  
-       *dest = g_strdup(addr);
+       if_addr.index = index;
+       if_addr.family = AF_INET;
+       if_addr.ipaddrs[ADDR_TYPE_IPADDR] = &addr;
+       if_addr.ipaddrs[ADDR_TYPE_NETMASK] = &mask;
+       if_addr.ipaddrs[ADDR_TYPE_DSTADDR] = &dest;
  
-       DBG("destination %s", *dest);
+       err = get_interface_addresses(&if_addr);
+       if (err)
+               return err;
  
-       return 0;
+       nw_addr.s_addr = (addr.s_addr & mask.s_addr);
+       if (inet_ntop(AF_INET, &nw_addr, buf, INET_ADDRSTRLEN))
+               *network = g_strdup(buf);
+       memset(&buf, 0, INET_ADDRSTRLEN);
+       if (inet_ntop(AF_INET, &mask, buf, INET_ADDRSTRLEN))
+               *netmask = g_strdup(buf);
+       if (destination) {
+               memset(&buf, 0, INET_ADDRSTRLEN);
+               if (inet_ntop(AF_INET, &dest, buf, INET_ADDRSTRLEN))
+                       *destination = g_strdup(buf);
+       }
+       DBG("network %s netmask %s destination %s", *network, *netmask,
+                               destination ? *destination : NULL);
+       return *network && **network && *netmask && **netmask ? 0 : -ENOENT;
  }
  
- int connman_inet_ipv6_get_dest_addr(int index, char **dest)
+ int connman_inet_ipv6_get_route_addresses(int index, char **network,
+                                       char **netmask, char **destination)
  {
-       char addr[INET6_ADDRSTRLEN];
-       int ret;
+       struct interface_address if_addr = { 0 };
+       struct in6_addr addr = { 0 };
+       struct in6_addr mask = { 0 };
+       struct in6_addr dest = { 0 };
+       struct in6_addr nw_addr  = { 0 };
+       char buf[INET6_ADDRSTRLEN] = { 0 };
+       int err;
  
-       ret = get_dest_addr(PF_INET6, index, addr, INET6_ADDRSTRLEN);
-       if (ret < 0)
-               return ret;
+       if (!network)
+               return -EINVAL;
  
-       *dest = g_strdup(addr);
+       if_addr.index = index;
+       if_addr.family = AF_INET6;
+       if_addr.ipaddrs[ADDR_TYPE_IPADDR] = &addr;
+       if_addr.ipaddrs[ADDR_TYPE_NETMASK] = &mask;
+       if_addr.ipaddrs[ADDR_TYPE_DSTADDR] = &dest;
  
-       DBG("destination %s", *dest);
+       err = get_interface_addresses(&if_addr);
+       if (err)
+               return err;
  
-       return 0;
+       ipv6_addr_set(&nw_addr, addr.s6_addr32[0] & mask.s6_addr32[0],
+                               addr.s6_addr32[1] & mask.s6_addr32[1],
+                               addr.s6_addr32[2] & mask.s6_addr32[2],
+                               addr.s6_addr32[3] & mask.s6_addr32[3]);
+       if (inet_ntop(AF_INET6, &nw_addr, buf, INET6_ADDRSTRLEN))
+               *network = g_strdup(buf);
+       memset(&buf, 0, INET6_ADDRSTRLEN);
+       if (inet_ntop(AF_INET6, &mask, buf, INET6_ADDRSTRLEN))
+               *netmask = g_strdup(buf);
+       if (destination) {
+               memset(&buf, 0, INET6_ADDRSTRLEN);
+               if (inet_ntop(AF_INET6, &dest, buf, INET6_ADDRSTRLEN))
+                       *destination = g_strdup(buf);
+       }
+       DBG("network %s netmask %s destination %s", *network, *netmask,
+                               destination ? *destination : NULL);
+       return *network && **network && *netmask && **netmask ? 0 : -ENOENT;
  }
  
  int __connman_inet_rtnl_open(struct __connman_inet_rtnl_handle *rth)
@@@ -2983,58 -3022,30 +3170,30 @@@ bool connman_inet_is_ipv6_supported(
        return true;
  }
  
- int __connman_inet_get_interface_address(int index, int family, void *address)
+ /*
+  * Omits checking of the gateway matching the actual gateway IP since both
+  * connmand and vpnd use inet.c, getting the route is via ipconfig and ipconfig
+  * is different for both. Gateway is left here for possible future use.
+  *
+  * Gateway can be NULL and connection.c then assigns 0.0.0.0 address or ::,
+  * depending on IP family.
+  */
+ bool connman_inet_is_default_route(int family, const char *host,
+                               const char *gateway, const char *netmask)
  {
-       struct ifaddrs *ifaddr, *ifa;
-       int err = -ENOENT;
-       char name[IF_NAMESIZE];
-       if (!if_indextoname(index, name))
-               return -EINVAL;
-       DBG("index %d interface %s", index, name);
-       if (getifaddrs(&ifaddr) < 0) {
-               err = -errno;
-               DBG("Cannot get addresses err %d/%s", err, strerror(-err));
-               return err;
-       }
-       for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
-               if (!ifa->ifa_addr)
-                       continue;
-               if (strncmp(ifa->ifa_name, name, IF_NAMESIZE) == 0 &&
-                                       ifa->ifa_addr->sa_family == family) {
-                       if (family == AF_INET) {
-                               struct sockaddr_in *in4 = (struct sockaddr_in *)
-                                       ifa->ifa_addr;
-                               if (in4->sin_addr.s_addr == INADDR_ANY)
-                                       continue;
-                               memcpy(address, &in4->sin_addr,
-                                                       sizeof(struct in_addr));
-                       } else if (family == AF_INET6) {
-                               struct sockaddr_in6 *in6 =
-                                       (struct sockaddr_in6 *)ifa->ifa_addr;
-                               if (memcmp(&in6->sin6_addr, &in6addr_any,
-                                               sizeof(struct in6_addr)) == 0)
-                                       continue;
-                               memcpy(address, &in6->sin6_addr,
-                                               sizeof(struct in6_addr));
+       return __connman_inet_is_any_addr(host, family) &&
+                               __connman_inet_is_any_addr(netmask, family);
+ }
  
-                       } else {
-                               err = -EINVAL;
-                               goto out;
-                       }
+ int __connman_inet_get_interface_address(int index, int family, void *address)
+ {
+       struct interface_address if_addr = { 0 };
  
-                       err = 0;
-                       break;
-               }
-       }
+       if_addr.index = index;
+       if_addr.family = family;
+       if_addr.ipaddrs[ADDR_TYPE_IPADDR] = address;
  
- out:
-       freeifaddrs(ifaddr);
-       return err;
+       return get_interface_addresses(&if_addr);
  }
  
  int __connman_inet_get_interface_mac_address(int index, uint8_t *mac_address)
@@@ -3168,7 -3179,7 +3327,7 @@@ static int iproute_default_modify(int c
  
        ret = inet_pton(family, dst ? dst : gateway, buf);
        g_free(dst);
-       if (ret <= 0)
+       if (ret != 1)
                return -EINVAL;
  
        memset(&rth, 0, sizeof(rth));
@@@ -3243,61 -3254,14 +3402,14 @@@ int __connman_inet_del_subnet_from_tabl
  int __connman_inet_get_interface_ll_address(int index, int family,
                                                                void *address)
  {
-       struct ifaddrs *ifaddr, *ifa;
-       int err = -ENOENT;
-       char name[IF_NAMESIZE];
-       if (!if_indextoname(index, name))
-               return -EINVAL;
-       DBG("index %d interface %s", index, name);
+       struct interface_address if_addr = { 0 };
  
-       if (getifaddrs(&ifaddr) < 0) {
-               err = -errno;
-               DBG("Cannot get addresses err %d/%s", err, strerror(-err));
-               return err;
-       }
+       if_addr.index = index;
+       if_addr.family = family;
+       if_addr.require_ll = true;
+       if_addr.ipaddrs[ADDR_TYPE_IPADDR] = address;
  
-       for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
-               if (!ifa->ifa_addr)
-                       continue;
-               if (strncmp(ifa->ifa_name, name, IF_NAMESIZE) == 0 &&
-                                       ifa->ifa_addr->sa_family == family) {
-                       if (family == AF_INET) {
-                               struct sockaddr_in *in4 = (struct sockaddr_in *)
-                                       ifa->ifa_addr;
-                               if (in4->sin_addr.s_addr == INADDR_ANY)
-                                       continue;
-                               if ((in4->sin_addr.s_addr & IN_CLASSB_NET) !=
-                                               ((in_addr_t) 0xa9fe0000))
-                                       continue;
-                               memcpy(address, &in4->sin_addr,
-                                                       sizeof(struct in_addr));
-                       } else if (family == AF_INET6) {
-                               struct sockaddr_in6 *in6 =
-                                       (struct sockaddr_in6 *)ifa->ifa_addr;
-                               if (memcmp(&in6->sin6_addr, &in6addr_any,
-                                               sizeof(struct in6_addr)) == 0)
-                                       continue;
-                               if (!IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
-                                       continue;
-                               memcpy(address, &in6->sin6_addr,
-                                               sizeof(struct in6_addr));
-                       } else {
-                               err = -EINVAL;
-                               goto out;
-                       }
-                       err = 0;
-                       break;
-               }
-       }
- out:
-       freeifaddrs(ifaddr);
-       return err;
+       return get_interface_addresses(&if_addr);
  }
  
  int __connman_inet_get_address_netmask(int ifindex,
@@@ -3451,7 -3415,7 +3563,7 @@@ static int get_nfs_server_ip(const cha
        addrstr[len] = '\0';
  
        err = inet_pton(AF_INET, addrstr, addr);
-       if (err <= 0) {
+       if (err != 1) {
                connman_error("%s: Cannot convert to numeric addr \"%s\"\n",
                                __func__, addrstr);
                err = -1;
diff --combined src/ipaddress.c
index d63d95c,201d834..201d834
mode 100755,100644..100755
@@@ -70,10 -70,19 +70,19 @@@ struct connman_ipaddress *connman_ipadd
        ipaddress->peer = NULL;
        ipaddress->broadcast = NULL;
        ipaddress->gateway = NULL;
+       ipaddress->is_p2p = false;
  
        return ipaddress;
  }
  
+ void connman_ipaddress_set_p2p(struct connman_ipaddress *ipaddress, bool value)
+ {
+       if (!ipaddress)
+               return;
+       ipaddress->is_p2p = value;
+ }
  void connman_ipaddress_free(struct connman_ipaddress *ipaddress)
  {
        if (!ipaddress)
@@@ -95,7 -104,7 +104,7 @@@ static bool check_ipv6_address(const ch
                return false;
  
        err = inet_pton(AF_INET6, address, buf);
-       if (err > 0)
+       if (err == 1)
                return true;
  
        return false;
@@@ -223,6 -232,7 +232,7 @@@ connman_ipaddress_copy(struct connman_i
        copy->peer = g_strdup(ipaddress->peer);
        copy->broadcast = g_strdup(ipaddress->broadcast);
        copy->gateway = g_strdup(ipaddress->gateway);
+       copy->is_p2p = ipaddress->is_p2p;
  
        return copy;
  }
diff --combined src/ipconfig.c
index 7d4be73,1551826..4a0e4ad
mode 100755,100644..100755
@@@ -52,10 -52,6 +52,10 @@@ struct connman_ipconfig 
        struct connman_ipaddress *address;
        struct connman_ipaddress *system;
  
 +#if defined TIZEN_EXT
 +      int dhcp_lease_duration;
 +#endif
 +
        int ipv6_privacy_config;
        char *last_dhcp_address;
        char **last_dhcpv6_prefixes;
@@@ -262,153 -258,165 +262,165 @@@ static const char *scope2str(unsigned c
        return "";
  }
  
- static bool get_ipv6_state(gchar *ifname)
+ #define PROC_IPV4_CONF_PREFIX "/proc/sys/net/ipv4/conf"
+ #define PROC_IPV6_CONF_PREFIX "/proc/sys/net/ipv6/conf"
+ static int read_conf_value(const char *prefix, const char *ifname,
+                                       const char *suffix, int *value)
  {
-       int disabled;
        gchar *path;
        FILE *f;
-       bool enabled = false;
-       if (!ifname)
-               path = g_strdup("/proc/sys/net/ipv6/conf/all/disable_ipv6");
-       else
-               path = g_strdup_printf(
-                       "/proc/sys/net/ipv6/conf/%s/disable_ipv6", ifname);
+       int err;
  
+       path = g_build_filename(prefix, ifname ? ifname : "all", suffix, NULL);
        if (!path)
-               return enabled;
+               return -ENOMEM;
  
+       errno = 0;
        f = fopen(path, "r");
+       if (!f) {
+               err = -errno;
+       } else {
+               errno = 0; /* Avoid stale errno values with fscanf */
  
-       g_free(path);
+               err = fscanf(f, "%d", value);
+               if (err <= 0 && errno)
+                       err = -errno;
  
-       if (f) {
-               if (fscanf(f, "%d", &disabled) > 0)
-                       enabled = !disabled;
                fclose(f);
        }
  
-       return enabled;
+       if (err <= 0)
+               connman_error("failed to read %s", path);
+       g_free(path);
+       return err;
  }
  
- static void set_ipv6_state(gchar *ifname, bool enable)
+ static int read_ipv4_conf_value(const char *ifname, const char *suffix,
+                                                               int *value)
  {
+       return read_conf_value(PROC_IPV4_CONF_PREFIX, ifname, suffix, value);
+ }
+ static int read_ipv6_conf_value(const char *ifname, const char *suffix,
+                                                               int *value)
+ {
+       return read_conf_value(PROC_IPV6_CONF_PREFIX, ifname, suffix, value);
+ }
+ static int write_conf_value(const char *prefix, const char *ifname,
+                                       const char *suffix, int value) {
        gchar *path;
        FILE *f;
+       int rval;
  
-       if (!ifname)
-               path = g_strdup("/proc/sys/net/ipv6/conf/all/disable_ipv6");
-       else
-               path = g_strdup_printf(
-                       "/proc/sys/net/ipv6/conf/%s/disable_ipv6", ifname);
+       path = g_build_filename(prefix, ifname ? ifname : "all", suffix, NULL);
        if (!path)
-               return;
+               return -ENOMEM;
  
        f = fopen(path, "r+");
+       if (!f) {
+               rval = -errno;
+       } else {
+               rval = fprintf(f, "%d", value);
+               fclose(f);
+       }
+       if (rval <= 0)
+               connman_error("failed to set %s value %d", path, value);
  
        g_free(path);
  
-       if (!f)
-               return;
+       return rval;
+ }
  
-       if (!enable)
-               fprintf(f, "1");
-       else
-               fprintf(f, "0");
+ static int write_ipv4_conf_value(const char *ifname, const char *suffix,
+                                                               int value)
+ {
+       return write_conf_value(PROC_IPV4_CONF_PREFIX, ifname, suffix, value);
+ }
  
-       fclose(f);
+ static int write_ipv6_conf_value(const char *ifname, const char *suffix,
+                                                               int value)
+ {
+       return write_conf_value(PROC_IPV6_CONF_PREFIX, ifname, suffix, value);
  }
  
- static int get_ipv6_privacy(gchar *ifname)
+ static bool get_ipv6_state(gchar *ifname)
  {
-       gchar *path;
-       FILE *f;
-       int value;
+       int disabled;
+       bool enabled = false;
  
-       if (!ifname)
-               return 0;
+       if (read_ipv6_conf_value(ifname, "disable_ipv6", &disabled) > 0)
+               enabled = !disabled;
+       return enabled;
+ }
  
-       path = g_strdup_printf("/proc/sys/net/ipv6/conf/%s/use_tempaddr",
-                                                               ifname);
+ static int set_ipv6_state(gchar *ifname, bool enable)
+ {
+       int disabled = enable ? 0 : 1;
  
-       if (!path)
-               return 0;
+       DBG("%s %d", ifname, disabled);
  
-       f = fopen(path, "r");
+       return write_ipv6_conf_value(ifname, "disable_ipv6", disabled);
+ }
  
-       g_free(path);
+ static int get_ipv6_privacy(gchar *ifname)
+ {
+       int value;
  
-       if (!f)
+       if (!ifname)
                return 0;
  
-       if (fscanf(f, "%d", &value) <= 0)
+       if (read_ipv6_conf_value(ifname, "use_tempaddr", &value) < 0)
                value = 0;
  
-       fclose(f);
        return value;
  }
  
  /* Enable the IPv6 privacy extension for stateless address autoconfiguration.
   * The privacy extension is described in RFC 3041 and RFC 4941
   */
- static void set_ipv6_privacy(gchar *ifname, int value)
+ static int set_ipv6_privacy(gchar *ifname, int value)
  {
-       gchar *path;
-       FILE *f;
        if (!ifname)
-               return;
-       path = g_strdup_printf("/proc/sys/net/ipv6/conf/%s/use_tempaddr",
-                                                               ifname);
-       if (!path)
-               return;
+               return -EINVAL;
  
        if (value < 0)
                value = 0;
  
-       f = fopen(path, "r+");
-       g_free(path);
-       if (!f)
-               return;
-       fprintf(f, "%d", value);
-       fclose(f);
+       return write_ipv6_conf_value(ifname, "use_tempaddr", value);
  }
  
  static int get_rp_filter(void)
  {
-       FILE *f;
-       int value = -EINVAL, tmp;
+       int value;
  
-       f = fopen("/proc/sys/net/ipv4/conf/all/rp_filter", "r");
-       if (f) {
-               if (fscanf(f, "%d", &tmp) == 1)
-                       value = tmp;
-               fclose(f);
-       }
+       if (read_ipv4_conf_value(NULL, "rp_filter", &value) < 0)
+               value = -EINVAL;
  
        return value;
  }
  
- static void set_rp_filter(int value)
+ static int set_rp_filter(int value)
  {
-       FILE *f;
-       f = fopen("/proc/sys/net/ipv4/conf/all/rp_filter", "r+");
-       if (!f)
-               return;
-       fprintf(f, "%d", value);
+       /* 0 = no validation, 1 = strict mode, 2 = loose mode */
+       switch (value) {
+       case -1:
+               value = 0;
+               /* fall through */
+       case 0:
+       case 1:
+       case 2:
+               break;
+       default:
+               return -EINVAL;
+       }
  
-       fclose(f);
+       return write_ipv4_conf_value(NULL, "rp_filter", value);
  }
  
  int __connman_ipconfig_set_rp_filter()
@@@ -577,16 -585,6 +589,16 @@@ void __connman_ipconfig_newlink(int ind
                                                index, type, type2str(type));
  
  update:
 +#if defined TIZEN_EXT
 +      if (g_strcmp0(ipdevice->address, address) != 0) {
 +              /* If an original address is built-in physical device,
 +               * it's hardly get an address at a initial creation
 +               */
 +              g_free(ipdevice->address);
 +              ipdevice->address = g_strdup(address);
 +      }
 +#endif
 +
        ipdevice->mtu = mtu;
  
        update_stats(ipdevice, ifname, stats);
@@@ -710,6 -708,25 +722,25 @@@ static inline gint check_duplicate_addr
        return g_strcmp0(addr1->local, addr2->local);
  }
  
+ static bool is_index_p2p_service(int index)
+ {
+       struct connman_service *service;
+       enum connman_service_type type;
+       service = __connman_service_lookup_from_index(index);
+       if (!service)
+               return false;
+       type = connman_service_get_type(service);
+       switch (type) {
+       case CONNMAN_SERVICE_TYPE_P2P:
+       case CONNMAN_SERVICE_TYPE_VPN:
+               return true;
+       default:
+               return false;
+       }
+ }
  int __connman_ipconfig_newaddr(int index, int family, const char *label,
                                unsigned char prefixlen, const char *address)
  {
        ipaddress->prefixlen = prefixlen;
        ipaddress->local = g_strdup(address);
  
+       if (is_index_p2p_service(index))
+               connman_ipaddress_set_p2p(ipaddress, true);
        if (g_slist_find_custom(ipdevice->address_list, ipaddress,
                                        check_duplicate_address)) {
                connman_ipaddress_free(ipaddress);
@@@ -1146,32 -1166,16 +1180,32 @@@ void __connman_ipconfig_set_gateway(str
        ipconfig->address->gateway = g_strdup(gateway);
  }
  
 +#if defined TIZEN_EXT
 +void __connman_ipconfig_set_dhcp_lease_duration(struct connman_ipconfig *ipconfig,
 +              int dhcp_lease_duration)
 +{
 +      ipconfig->dhcp_lease_duration = dhcp_lease_duration;
 +}
 +#endif
 +
 +#if defined TIZEN_EXT
 +int __connman_ipconfig_gateway_add(struct connman_ipconfig *ipconfig, struct connman_service *service)
 +#else
  int __connman_ipconfig_gateway_add(struct connman_ipconfig *ipconfig)
 +#endif
  {
 +#if !defined TIZEN_EXT
        struct connman_service *service;
 +#endif
  
        DBG("");
  
        if (!ipconfig->address)
                return -EINVAL;
  
 +#if !defined TIZEN_EXT
        service = __connman_service_lookup_from_index(ipconfig->index);
 +#endif
        if (!service)
                return -EINVAL;
  
@@@ -1216,6 -1220,15 +1250,15 @@@ void __connman_ipconfig_set_prefixlen(s
        ipconfig->address->prefixlen = prefixlen;
  }
  
+ static void ipconfig_set_p2p(int index, struct connman_ipconfig *ipconfig)
+ {
+       if (!is_index_p2p_service(index))
+               return;
+       connman_ipaddress_set_p2p(ipconfig->address, true);
+       connman_ipaddress_set_p2p(ipconfig->system, true);
+ }
  static struct connman_ipconfig *create_ipv6config(int index)
  {
        struct connman_ipconfig *ipv6config;
  
        ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
        if (ipdevice)
 +#if !defined TIZEN_EXT
                ipv6config->ipv6_privacy_config = ipdevice->ipv6_privacy;
 +#else
 +              ipv6config->ipv6_privacy_config = ipdevice->ipv6_privacy = 2;
 +#endif
  
        ipv6config->address = connman_ipaddress_alloc(AF_INET6);
        if (!ipv6config->address) {
  
        ipv6config->system = connman_ipaddress_alloc(AF_INET6);
  
+       ipconfig_set_p2p(index, ipv6config);
        DBG("ipconfig %p index %d method %s", ipv6config, index,
                __connman_ipconfig_method2string(ipv6config->method));
  
@@@ -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;
@@@ -1326,9 -1337,7 +1374,9 @@@ void __connman_ipconfig_unref_debug(str
  {
        if (!ipconfig)
                return;
 -
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        DBG("%p ref %d by %s:%d:%s()", ipconfig, ipconfig->refcount - 1,
                file, line, caller);
  
@@@ -1477,12 -1486,6 +1525,12 @@@ int __connman_ipconfig_address_unset(st
        if (!ipconfig)
                return 0;
  
 +#if defined TIZEN_EXT
 +      DBG("ipconfig method %d type %d", ipconfig->method, ipconfig->type);
 +#else
 +      DBG("method %d", ipconfig->method);
 +#endif
 +
        switch (ipconfig->method) {
        case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
        case CONNMAN_IPCONFIG_METHOD_OFF:
                        err = connman_inet_clear_address(ipconfig->index,
                                                        ipconfig->address);
                else if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6)
-                       err = connman_inet_clear_ipv6_address(
-                                               ipconfig->index,
-                                               ipconfig->address->local,
-                                               ipconfig->address->prefixlen);
+                       err = connman_inet_clear_ipv6_address(ipconfig->index,
+                                                       ipconfig->address);
                else
                        err = -EINVAL;
  
@@@ -1691,6 -1692,9 +1737,9 @@@ int __connman_ipconfig_enable(struct co
                connman_ipaddress_clear(ipdevice->config_ipv4->system);
  
                __connman_ipconfig_unref(ipdevice->config_ipv4);
+               g_free(ipdevice->ipv4_gateway);
+               ipdevice->ipv4_gateway = NULL;
        }
  
        if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
                connman_ipaddress_clear(ipdevice->config_ipv6->system);
  
                __connman_ipconfig_unref(ipdevice->config_ipv6);
+               g_free(ipdevice->ipv6_gateway);
+               ipdevice->ipv6_gateway = NULL;
        }
  
        if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
  int __connman_ipconfig_disable(struct connman_ipconfig *ipconfig)
  {
        struct connman_ipdevice *ipdevice;
 -
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        DBG("ipconfig %p", ipconfig);
  
        if (!ipconfig || ipconfig->index < 0)
                connman_ipaddress_clear(ipdevice->config_ipv4->system);
                __connman_ipconfig_unref(ipdevice->config_ipv4);
                ipdevice->config_ipv4 = NULL;
+               g_free(ipdevice->ipv4_gateway);
+               ipdevice->ipv4_gateway = NULL;
                return 0;
        }
  
        if (ipdevice->config_ipv6 == ipconfig) {
                ipconfig_list = g_list_remove(ipconfig_list, ipconfig);
  
 +#if defined TIZEN_EXT
 +              if (ipdevice->config_ipv6->method ==
 +                              CONNMAN_IPCONFIG_METHOD_AUTO) {
 +                      disable_ipv6(ipdevice->config_ipv6);
 +                      enable_ipv6(ipdevice->config_ipv6);
 +              }
 +#endif
                connman_ipaddress_clear(ipdevice->config_ipv6->system);
                __connman_ipconfig_unref(ipdevice->config_ipv6);
                ipdevice->config_ipv6 = NULL;
+               g_free(ipdevice->ipv6_gateway);
+               ipdevice->ipv6_gateway = NULL;
                return 0;
        }
  
@@@ -1911,11 -1917,6 +1971,11 @@@ void __connman_ipconfig_append_ipv4(str
        case CONNMAN_IPCONFIG_METHOD_MANUAL:
        case CONNMAN_IPCONFIG_METHOD_DHCP:
                append_addr = ipconfig->system;
 +#if defined TIZEN_EXT
 +              /* TIZEN enables get_properties before __connman_ipconfig_newaddr */
 +              if (append_addr && append_addr->local == NULL)
 +                      append_addr = ipconfig->address;
 +#endif
                break;
        }
  
        if (append_addr->gateway)
                connman_dbus_dict_append_basic(iter, "Gateway",
                                DBUS_TYPE_STRING, &append_addr->gateway);
 +
 +#if defined TIZEN_EXT
 +      if (ipconfig->method == CONNMAN_IPCONFIG_METHOD_DHCP) {
 +              char *server_ip;
 +              server_ip = __connman_dhcp_get_server_address(ipconfig);
 +              if (server_ip) {
 +                      connman_dbus_dict_append_basic(iter, "DHCPServerIP",
 +                                      DBUS_TYPE_STRING, &server_ip);
 +                      g_free(server_ip);
 +              }
 +              connman_dbus_dict_append_basic(iter, "DHCPLeaseDuration",
 +                              DBUS_TYPE_INT32, &ipconfig->dhcp_lease_duration);
 +      }
 +#endif
  }
  
  void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig,
        case CONNMAN_IPCONFIG_METHOD_DHCP:
        case CONNMAN_IPCONFIG_METHOD_AUTO:
                append_addr = ipconfig->system;
 +#if defined TIZEN_EXT
 +              /* TIZEN enables get_properties before __connman_ipconfig_newaddr */
 +              if (append_addr && append_addr->local == NULL)
 +                      append_addr = ipconfig->address;
 +#endif
                break;
        }
  
@@@ -2195,10 -2177,6 +2255,10 @@@ int __connman_ipconfig_set_config(struc
  
        case CONNMAN_IPCONFIG_METHOD_OFF:
                ipconfig->method = method;
 +#if defined TIZEN_EXT
 +              if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6)
 +                      disable_ipv6(ipconfig);
 +#endif
  
                break;
  
                ipconfig->method = method;
                if (privacy_string)
                        ipconfig->ipv6_privacy_config = privacy;
 +#if defined TIZEN_EXT
 +              enable_ipv6(ipconfig);
 +#endif
  
                break;
  
diff --combined src/iptables.c
index 2ee9485,664b27f..90a296e
mode 100755,100644..100755
@@@ -452,7 -452,7 +452,7 @@@ static struct connman_iptables *hash_ta
        case AF_INET6:
                return g_hash_table_lookup(table_hash_ipv6, table_name);
        }
 -      
 +
        return NULL;
  }
  
@@@ -466,7 -466,7 +466,7 @@@ static bool hash_table_replace(int type
        case AF_INET6:
                return g_hash_table_replace(table_hash_ipv6, table_name, table);
        }
 -      
 +
        return false;
  }
  
@@@ -478,7 -478,7 +478,7 @@@ static bool hash_table_remove(int type
        case AF_INET6:
                return g_hash_table_remove(table_hash_ipv6, table_name);
        }
 -      
 +
        return false;
  }
  
@@@ -534,7 -534,7 +534,7 @@@ static int iterate_entries(struct connm
        for (offset = 0; offset < size;
                        offset += iptables_entry_get_next_offset(&entry)) {
                builtin = -1;
 -              
 +
                switch (entries->type) {
                case AF_INET:
                        entry.entry = (void* )entries->entry + offset;
@@@ -682,7 -682,7 +682,7 @@@ static bool is_chain(struct connman_ipt
                return true;
  
        target = iptables_entry_get_target(e);
 -      
 +
        if (!target)
                return false;
  
@@@ -699,7 -699,7 +699,7 @@@ static GList *find_chain_head(struct co
        struct connman_iptables_entry *head;
        struct xt_entry_target *target;
        int builtin;
 -      
 +
        switch (table->type) {
        case AF_INET:
        case AF_INET6:
  
                /* User defined chain */
                target = iptables_entry_get_target(head);
 -              
 +
                if (!target)
                        continue;
  
@@@ -813,7 -813,7 +813,7 @@@ static void update_targets_reference(st
        if (is_fallthrough(modified_entry)) {
                t = (struct xt_standard_target *)
                        iptables_entry_get_target(modified_entry);
 -              
 +
                if (!t)
                        return;
  
@@@ -1573,25 -1573,14 +1573,25 @@@ static GList *find_existing_rule(struc
  
        switch (entry_test->type) {
        case AF_INET:
 -              if (!entry_test->entry)
 +              if (!entry_test->entry) {
 +#if defined TIZEN_EXT
 +                      iptables_entry_free(entry_test);
 +#endif
                        return NULL;
 +              }
                break;
        case AF_INET6:
 -              if (!entry_test->entry6)
 +              if (!entry_test->entry6) {
 +#if defined TIZEN_EXT
 +                      iptables_entry_free(entry_test);
 +#endif
                        return NULL;
 +              }
                break;
        default:
 +#if defined TIZEN_EXT
 +              iptables_entry_free(entry_test);
 +#endif
                return NULL;
        }
  
@@@ -2106,7 -2095,7 +2106,7 @@@ static void dump_table(struct connman_i
        underflow = iptables_table_get_info_underflow(table);
        valid_hooks = iptables_table_get_info_valid_hooks(table);
        size = iptables_table_get_info_size(table);
 -      
 +
        DBG("%s valid_hooks=0x%08x, num_entries=%u, size=%u",
                iptables_table_get_info_name(table),
                valid_hooks,
@@@ -2245,7 -2234,7 +2245,7 @@@ static void dump_replace(struct iptable
        unsigned int *underflow;
        unsigned int valid_hooks;
        unsigned int size;
 -      
 +
        hook_entry = iptables_replace_get_hook_entry(repl);
        underflow = iptables_replace_get_underflow(repl);
        valid_hooks = iptables_replace_get_valid_hooks(repl);
@@@ -2383,7 -2372,7 +2383,7 @@@ static int add_entry(struct connman_ipt
        struct connman_iptables *table = user_data;
        struct connman_iptables_entry new_entry = { 0 };
        u_int16_t next_offset;
 -      
 +
        new_entry.type = entry->type;
        next_offset = iptables_entry_get_next_offset(entry);
  
        default:
                return -EINVAL;
        }
 -      
 +
        return iptables_add_entry(table, &new_entry, NULL, builtin,
                                table->num_entries);
  }
@@@ -2429,7 -2418,7 +2429,7 @@@ static void table_cleanup(struct connma
  
        g_list_free(table->entries);
        g_free(table->name);
 -      
 +
        if (table->type == AF_INET) {
                g_free(table->info);
                g_free(table->blob_entries);
@@@ -2469,13 -2458,8 +2469,13 @@@ static struct connman_iptables *iptable
  
        DBG("%d %s", type, table_name);
  
 -      if (setup_xtables(type))
 +      if (setup_xtables(type)) {
 +#if defined TIZEN_EXT
 +              g_free(iptables_mod);
 +              g_free(module);
 +#endif
                return NULL;
 +      }
  
        if (xtables_insmod(iptables_mod, NULL, TRUE) != 0)
                DBG("%s module loading gives error but trying anyway",
@@@ -2706,9 -2690,9 +2706,9 @@@ static struct xtables_target *prepare_t
  
        is_builtin = false;
        is_user_defined = false;
 -      
 +
        DBG("target %s", target_name);
 -      
 +
        if (!table)
                return NULL;
  
        if (is_builtin || is_user_defined)
                xt_t = xtables_find_target(get_standard_target(table->type),
                                                XTF_LOAD_MUST_SUCCEED);
 -      else 
 +      else
                xt_t = xtables_find_target(target_name, XTF_TRY_LOAD);
  
        disable_jmp();
@@@ -2947,7 -2931,7 +2947,7 @@@ static int parse_ip_and_mask(const cha
        if (!tokens)
                return -1;
  
-       if (!inet_pton(AF_INET, tokens[0], ip)) {
+       if (inet_pton(AF_INET, tokens[0], ip) != 1) {
                err = -1;
                goto out;
        }
@@@ -2988,7 -2972,7 +2988,7 @@@ static int parse_ipv6_and_mask(const ch
        if (!tokens)
                return -1;
  
-       if (!inet_pton(AF_INET6, tokens[0], ip)) {
+       if (inet_pton(AF_INET6, tokens[0], ip) != 1) {
                err = -1;
                goto out;
        }
@@@ -3049,7 -3033,7 +3049,7 @@@ static struct connman_iptables *get_tab
                g_free(table->name);
  
        table->name = g_strdup(table_name);
 -      
 +
        hash_table_replace(type, table->name, table);
  
        return table;
@@@ -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 */
                                if (invert)
                                        ctx->ip->invflags |= IPT_INV_VIA_IN;
                        }
 -                      
 +
                        if (ctx->type == AF_INET6) {
                                g_stpcpy(ctx->ipv6->iniface, optarg);
                                memset(ctx->ipv6->iniface_mask, 0xff, len + 1);
@@@ -3565,7 -3549,7 +3565,7 @@@ static int setup_xtables(int type
        default:
                return -1;
        }
 -      
 +
        if (!err) {
                current_type = type;
        } else {
@@@ -3728,7 -3712,7 +3728,7 @@@ int __connman_iptables_find_chain(int t
  
        if(!find_chain_head(table, chain))
                return -ENOENT; // Not Found
 -      
 +
        return 0; // Found
  }
  
@@@ -3770,7 -3754,7 +3770,7 @@@ int __connman_iptables_append(int type
        int err;
  
        err = setup_xtables(type);
 -      
 +
        if (err < 0)
                return err;
  
@@@ -3824,14 -3808,14 +3824,14 @@@ int __connman_iptables_insert(int type
        int err;
  
        err = setup_xtables(type);
 -      
 +
        if (err < 0)
                return err;
  
        ctx = g_try_new0(struct parse_context, 1);
        if (!ctx)
                return -ENOMEM;
 -      
 +
        ctx->type = type;
  
        DBG("%d -t %s -I %s %s", type, table_name, chain, rule_spec);
@@@ -3878,14 -3862,14 +3878,14 @@@ int __connman_iptables_delete(int type
        int err;
  
        err = setup_xtables(type);
 -      
 +
        if (err < 0)
                return err;
  
        ctx = g_try_new0(struct parse_context, 1);
        if (!ctx)
                return -ENOMEM;
 -      
 +
        ctx->type = type;
  
        DBG("%d -t %s -D %s %s", type, table_name, chain, rule_spec);
@@@ -3931,7 -3915,7 +3931,7 @@@ int __connman_iptables_commit(int type
        unsigned int cnt;
  
        err = setup_xtables(type);
 -      
 +
        if (err < 0)
                return err;
  
                repl.r = iptables_blob(table);
                if (!repl.r)
                        return -ENOMEM;
 -              
 +
                break;
        case AF_INET6:
                repl.r6 = ip6tables_blob(table);
        for (list = table->entries, cnt = 0; list; list = list->next, cnt++) {
                e = list->data;
                if (e->counter_idx >= 0) {
 -              
 +
                        switch (type) {
                        case AF_INET:
                                counters->counters[cnt] =
@@@ -4007,7 -3991,7 +4007,7 @@@ out_free
  
        g_free(repl.r);
        g_free(repl.r6);
 -      
 +
        reset_xtables();
  
        return err;
@@@ -4052,15 -4036,9 +4052,15 @@@ int __connman_iptables_iterate_chains(i
        int err;
  
        err = setup_xtables(type);
 -      
 +#if defined TIZEN_EXT
 +      if (err < 0) {
 +              g_free(cbd);
 +              return err;
 +      }
 +#else
        if (err < 0)
                return err;
 +#endif
  
        table = get_table(type, table_name);
        if (!table) {
                        iterate_chains_cb, cbd);
  
        g_free(cbd);
 -      
 +
        reset_xtables();
  
        return 0;
diff --combined src/main.c
index 772f7b8,6480caa..13e26d4
mode 100755,100644..100755
@@@ -34,8 -34,6 +34,8 @@@
  #include <sys/stat.h>
  #include <net/if.h>
  #include <netdb.h>
 +#include <sys/time.h>
 +#include <sys/resource.h>
  
  #include <gdbus.h>
  
  #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
  
@@@ -95,22 -96,12 +103,25 @@@ static struct 
        bool enable_6to4;
        char *vendor_class_id;
        bool enable_online_check;
+       bool enable_online_to_ready_transition;
+       unsigned int online_check_initial_interval;
+       unsigned int online_check_max_interval;
        bool auto_connect_roaming_services;
        bool acd;
        bool use_gateways_as_timeservers;
 +#if defined TIZEN_EXT
 +      char **cellular_interfaces;
 +      bool tizen_tv_extension;
 +      bool auto_ip;
 +      char *global_nameserver;
 +      bool supplicant_debug;
 +      char *def_wifi_ifname;
 +      bool file_log;
 +      bool dlog_log;
 +      bool simple_log;
 +      bool wifi_roam_scan;
 +      bool wifi_roam;
 +#endif
  } connman_settings  = {
        .bg_scan = true,
        .pref_timeservers = NULL,
        .enable_6to4 = false,
        .vendor_class_id = NULL,
        .enable_online_check = true,
+       .enable_online_to_ready_transition = false,
+       .online_check_initial_interval = DEFAULT_ONLINE_CHECK_INITIAL_INTERVAL,
+       .online_check_max_interval = DEFAULT_ONLINE_CHECK_MAX_INTERVAL,
        .auto_connect_roaming_services = false,
        .acd = false,
        .use_gateways_as_timeservers = false,
 +#if defined TIZEN_EXT
 +      .cellular_interfaces = NULL,
 +      .tizen_tv_extension = false,
 +      .auto_ip = true,
 +      .global_nameserver = NULL,
 +      .supplicant_debug = false,
 +      .def_wifi_ifname = DEFAULT_WIFI_INTERFACE,
 +      .file_log = true,
 +      .dlog_log = true,
 +      .simple_log = true,
 +      .wifi_roam_scan = false,
 +      .wifi_roam = false,
 +#endif
  };
  
 +#if defined TIZEN_EXT
 +static struct {
 +      /* BSSID */
 +      char *ins_preferred_freq_bssid;
 +      bool ins_last_connected_bssid;
 +      bool ins_assoc_reject;
 +      bool ins_signal_bssid;
 +      unsigned int ins_preferred_freq_bssid_score;
 +      unsigned int ins_last_connected_bssid_score;
 +      unsigned int ins_assoc_reject_score;
 +      /* SSID */
 +      bool ins_last_user_selection;
 +      unsigned int ins_last_user_selection_time;
 +      bool ins_last_connected;
 +      char *ins_preferred_freq;
 +      char **ins_security_priority;
 +      unsigned int ins_security_priority_count;
 +      bool ins_signal;
 +      bool ins_internet;
 +      unsigned int ins_last_user_selection_score;
 +      unsigned int ins_last_connected_score;
 +      unsigned int ins_preferred_freq_score;
 +      unsigned int ins_security_priority_score;
 +      unsigned int ins_internet_score;
 +      /* Common */
 +      int ins_signal_level3_5ghz;
 +      int ins_signal_level3_24ghz;
 +} connman_ins_settings = {
 +      /* BSSID */
 +      .ins_preferred_freq_bssid = NULL,
 +      .ins_last_connected_bssid = true,
 +      .ins_assoc_reject = true,
 +      .ins_signal_bssid = true,
 +      .ins_preferred_freq_bssid_score = 20,
 +      .ins_last_connected_bssid_score = 20,
 +      .ins_assoc_reject_score = 10,
 +      /* SSID */
 +      .ins_last_user_selection = true,
 +      .ins_last_user_selection_time = 480,
 +      .ins_last_connected = true,
 +      .ins_preferred_freq = NULL,
 +      .ins_security_priority = NULL,
 +      .ins_security_priority_count = 0,
 +      .ins_signal = true,
 +      .ins_internet = true,
 +      .ins_last_user_selection_score = 30,
 +      .ins_last_connected_score = 30,
 +      .ins_preferred_freq_score = 60,
 +      .ins_security_priority_score = 5,
 +      .ins_internet_score = 30,
 +      /* Common */
 +      .ins_signal_level3_5ghz = -76,
 +      .ins_signal_level3_24ghz = -74,
 +};
 +#endif
 +
  #define CONF_BG_SCAN                    "BackgroundScanning"
  #define CONF_PREF_TIMESERVERS           "FallbackTimeservers"
  #define CONF_AUTO_CONNECT_TECHS         "DefaultAutoConnectTechnologies"
  #define CONF_ENABLE_6TO4                "Enable6to4"
  #define CONF_VENDOR_CLASS_ID            "VendorClassID"
  #define CONF_ENABLE_ONLINE_CHECK        "EnableOnlineCheck"
+ #define CONF_ENABLE_ONLINE_TO_READY_TRANSITION "EnableOnlineToReadyTransition"
+ #define CONF_ONLINE_CHECK_INITIAL_INTERVAL "OnlineCheckInitialInterval"
+ #define CONF_ONLINE_CHECK_MAX_INTERVAL     "OnlineCheckMaxInterval"
  #define CONF_AUTO_CONNECT_ROAMING_SERVICES "AutoConnectRoamingServices"
  #define CONF_ACD                        "AddressConflictDetection"
  #define CONF_USE_GATEWAYS_AS_TIMESERVERS "UseGatewaysAsTimeservers"
 +#if defined TIZEN_EXT
 +#define CONF_CELLULAR_INTERFACE         "NetworkCellularInterfaceList"
 +#define CONF_TIZEN_TV_EXT                     "TizenTVExtension"
 +#define CONF_ENABLE_AUTO_IP                   "EnableAutoIp"
 +#define CONF_GLOBAL_NAMESERVER          "GlobalNameserver"
 +#define CONF_CONNMAN_SUPPLICANT_DEBUG   "ConnmanSupplicantDebug"
 +#define CONF_CONNMAN_WIFI_DEF_IFNAME    "DefaultWifiInterface"
 +#define CONF_CONNMAN_FILE_LOG           "FileLogging"
 +#define CONF_CONNMAN_DLOG_LOG           "DlogLogging"
 +#define CONF_CONNMAN_SIMPLIFIED_LOG     "SimplifiedLog"
 +#define CONF_CONNMAN_WIFI_ROAM_SCAN     "WifiRoamingScan"
 +#define CONF_CONNMAN_WIFI_ROAM          "WifiRoaming"
 +#endif
 +
 +#if defined TIZEN_EXT
 +/* BSSID */
 +#define CONF_INS_PREFERRED_FREQ_BSSID        "INSPreferredFreqBSSID"
 +#define CONF_INS_PREFERRED_FREQ_BSSID_SCORE  "INSPreferredFreqBSSIDScore"
 +#define CONF_INS_LAST_CONNECTED_BSSID        "INSLastConnectedBSSID"
 +#define CONF_INS_LAST_CONNECTED_BSSID_SCORE  "INSLastConnectedBSSIDScore"
 +#define CONF_INS_ASSOC_REJECT                "INSAssocReject"
 +#define CONF_INS_ASSOC_REJECT_SCORE          "INSAssocRejectScore"
 +#define CONF_INS_SIGNAL_BSSID                "INSSignalBSSID"
 +/* SSID */
 +#define CONF_INS_LAST_USER_SELECTION         "INSLastUserSelection"
 +#define CONF_INS_LAST_USER_SELECTION_TIME    "INSLastUserSelectionTime"
 +#define CONF_INS_LAST_USER_SELECTION_SCORE   "INSLastUserSelectionScore"
 +#define CONF_INS_LAST_CONNECTED              "INSLastConnected"
 +#define CONF_INS_LAST_CONNECTED_SCORE        "INSLastConnectedScore"
 +#define CONF_INS_PREFERRED_FREQ              "INSPreferredFreq"
 +#define CONF_INS_PREFERRED_FREQ_SCORE        "INSPreferredFreqScore"
 +#define CONF_INS_SECURITY_PRIORITY           "INSSecurityPriority"
 +#define CONF_INS_SECURITY_PRIORITY_COUNT     "INSSecurityPriorityCount"
 +#define CONF_INS_SECURITY_PRIORITY_SCORE     "INSSecurityPriorityScore"
 +#define CONF_INS_SIGNAL                      "INSSignal"
 +#define CONF_INS_INTERNET                    "INSInternet"
 +#define CONF_INS_INTERNET_SCORE              "INSInternetScore"
 +/* Common */
 +#define CONF_INS_SIGNAL_LEVEL3_5GHZ          "INSSignalLevel3_5GHz"
 +#define CONF_INS_SIGNAL_LEVEL3_24GHZ         "INSSignalLevel3_24GHz"
 +#endif
  
  static const char *supported_options[] = {
        CONF_BG_SCAN,
        CONF_PREF_TIMESERVERS,
        CONF_AUTO_CONNECT_TECHS,
+       CONF_FAVORITE_TECHS,
        CONF_ALWAYS_CONNECTED_TECHS,
        CONF_PREFERRED_TECHS,
        CONF_FALLBACK_NAMESERVERS,
        CONF_ENABLE_6TO4,
        CONF_VENDOR_CLASS_ID,
        CONF_ENABLE_ONLINE_CHECK,
+       CONF_ENABLE_ONLINE_TO_READY_TRANSITION,
+       CONF_ONLINE_CHECK_INITIAL_INTERVAL,
+       CONF_ONLINE_CHECK_MAX_INTERVAL,
        CONF_AUTO_CONNECT_ROAMING_SERVICES,
        CONF_ACD,
        CONF_USE_GATEWAYS_AS_TIMESERVERS,
 +#if defined TIZEN_EXT
 +      CONF_CELLULAR_INTERFACE,
 +      CONF_TIZEN_TV_EXT,
 +      CONF_ENABLE_AUTO_IP,
 +      CONF_GLOBAL_NAMESERVER,
 +      CONF_CONNMAN_SUPPLICANT_DEBUG,
 +      CONF_CONNMAN_WIFI_DEF_IFNAME,
 +      CONF_CONNMAN_FILE_LOG,
 +      CONF_CONNMAN_DLOG_LOG,
 +      CONF_CONNMAN_SIMPLIFIED_LOG,
 +      CONF_CONNMAN_WIFI_ROAM_SCAN,
 +      CONF_CONNMAN_WIFI_ROAM,
 +#endif
        NULL
  };
  
 +#if defined TIZEN_EXT
 +static const char *supported_ins_options[] = {
 +      /* BSSID */
 +      CONF_INS_PREFERRED_FREQ_BSSID,
 +      CONF_INS_PREFERRED_FREQ_BSSID_SCORE,
 +      CONF_INS_LAST_CONNECTED_BSSID,
 +      CONF_INS_LAST_CONNECTED_BSSID_SCORE,
 +      CONF_INS_ASSOC_REJECT,
 +      CONF_INS_ASSOC_REJECT_SCORE,
 +      CONF_INS_SIGNAL_BSSID,
 +      /* SSID */
 +      CONF_INS_LAST_USER_SELECTION,
 +      CONF_INS_LAST_USER_SELECTION_TIME,
 +      CONF_INS_LAST_USER_SELECTION_SCORE,
 +      CONF_INS_LAST_CONNECTED,
 +      CONF_INS_LAST_CONNECTED_SCORE,
 +      CONF_INS_PREFERRED_FREQ,
 +      CONF_INS_PREFERRED_FREQ_SCORE,
 +      CONF_INS_SECURITY_PRIORITY,
 +      CONF_INS_SECURITY_PRIORITY_COUNT,
 +      CONF_INS_SECURITY_PRIORITY_SCORE,
 +      CONF_INS_SIGNAL,
 +      CONF_INS_INTERNET,
 +      CONF_INS_INTERNET_SCORE,
 +      /* Common */
 +      CONF_INS_SIGNAL_LEVEL3_5GHZ,
 +      CONF_INS_SIGNAL_LEVEL3_24GHZ,
 +      NULL
 +};
 +#endif
 +
  static GKeyFile *load_config(const char *file)
  {
        GError *err = NULL;
@@@ -418,12 -265,7 +439,12 @@@ static void check_config(GKeyFile *conf
        keys = g_key_file_get_groups(config, NULL);
  
        for (j = 0; keys && keys[j]; j++) {
 +#if defined TIZEN_EXT
 +              if (g_strcmp0(keys[j], "General") != 0 &&
 +                      g_strcmp0(keys[j], "INS") != 0)
 +#else
                if (g_strcmp0(keys[j], "General") != 0)
 +#endif
                        connman_warn("Unknown group %s in %s",
                                                keys[j], MAINFILE);
        }
        }
  
        g_strfreev(keys);
 +
 +#if defined TIZEN_EXT
 +      keys = g_key_file_get_keys(config, "INS", NULL, NULL);
 +
 +      for (j = 0; keys && keys[j]; j++) {
 +              bool found;
 +              int i;
 +
 +              found = false;
 +              for (i = 0; supported_ins_options[i]; i++) {
 +                      if (g_strcmp0(keys[j], supported_ins_options[i]) == 0) {
 +                              found = true;
 +                              break;
 +                      }
 +              }
 +              if (!found && !supported_ins_options[i])
 +                      connman_warn("Unknown option %s in %s",
 +                                              keys[j], MAINFILE);
 +      }
 +
 +      g_strfreev(keys);
 +#endif
  }
  
 +#if defined TIZEN_EXT
 +static void check_Tizen_INS_configuration(GKeyFile *config)
 +{
 +      GError *error = NULL;
 +      char *ins_preferred_freq_bssid;
 +      char *ins_preferred_freq;
 +      char **ins_security_priority;
 +      bool boolean;
 +      int integer;
 +      gsize len;
 +
 +      ins_preferred_freq_bssid = __connman_config_get_string(config, "INS",
 +                                      CONF_INS_PREFERRED_FREQ_BSSID, &error);
 +      if (!error)
 +              connman_ins_settings.ins_preferred_freq_bssid = ins_preferred_freq_bssid;
 +
 +      g_clear_error(&error);
 +
 +      integer = g_key_file_get_integer(config, "INS",
 +                      CONF_INS_PREFERRED_FREQ_BSSID_SCORE, &error);
 +      if (!error && integer >= 0)
 +              connman_ins_settings.ins_preferred_freq_bssid_score = integer;
 +
 +      g_clear_error(&error);
 +
 +      boolean = __connman_config_get_bool(config, "INS",
 +                      CONF_INS_LAST_CONNECTED_BSSID, &error);
 +      if (!error)
 +              connman_ins_settings.ins_last_connected_bssid = boolean;
 +
 +      g_clear_error(&error);
 +
 +      integer = g_key_file_get_integer(config, "INS",
 +                      CONF_INS_LAST_CONNECTED_BSSID_SCORE, &error);
 +      if (!error && integer >= 0)
 +              connman_ins_settings.ins_last_connected_bssid_score = integer;
 +
 +      g_clear_error(&error);
 +
 +      boolean = __connman_config_get_bool(config, "INS",
 +                      CONF_INS_ASSOC_REJECT, &error);
 +      if (!error)
 +              connman_ins_settings.ins_assoc_reject = boolean;
 +
 +      g_clear_error(&error);
 +
 +      integer = g_key_file_get_integer(config, "INS",
 +                      CONF_INS_ASSOC_REJECT_SCORE, &error);
 +      if (!error && integer >= 0)
 +              connman_ins_settings.ins_assoc_reject_score = integer;
 +
 +      g_clear_error(&error);
 +
 +      boolean = __connman_config_get_bool(config, "INS",
 +                      CONF_INS_SIGNAL_BSSID, &error);
 +      if (!error)
 +              connman_ins_settings.ins_signal_bssid = boolean;
 +
 +      g_clear_error(&error);
 +
 +      boolean = __connman_config_get_bool(config, "INS",
 +                      CONF_INS_LAST_USER_SELECTION, &error);
 +      if (!error)
 +              connman_ins_settings.ins_last_user_selection = boolean;
 +
 +      g_clear_error(&error);
 +
 +      integer = g_key_file_get_integer(config, "INS",
 +                      CONF_INS_LAST_USER_SELECTION_TIME, &error);
 +      if (!error && integer >= 0)
 +              connman_ins_settings.ins_last_user_selection_time = integer;
 +
 +      g_clear_error(&error);
 +
 +      integer = g_key_file_get_integer(config, "INS",
 +                      CONF_INS_LAST_USER_SELECTION_SCORE, &error);
 +      if (!error && integer >= 0)
 +              connman_ins_settings.ins_last_user_selection_score = integer;
 +
 +      g_clear_error(&error);
 +
 +      boolean = __connman_config_get_bool(config, "INS",
 +                      CONF_INS_LAST_CONNECTED, &error);
 +      if (!error)
 +              connman_ins_settings.ins_last_connected = boolean;
 +
 +      g_clear_error(&error);
 +
 +      integer = g_key_file_get_integer(config, "INS",
 +                      CONF_INS_LAST_CONNECTED_SCORE, &error);
 +      if (!error && integer >= 0)
 +              connman_ins_settings.ins_last_connected_score = integer;
 +
 +      g_clear_error(&error);
 +
 +      ins_preferred_freq = __connman_config_get_string(config, "INS",
 +                                      CONF_INS_PREFERRED_FREQ, &error);
 +      if (!error)
 +              connman_ins_settings.ins_preferred_freq = ins_preferred_freq;
 +
 +      g_clear_error(&error);
 +
 +      integer = g_key_file_get_integer(config, "INS",
 +                      CONF_INS_PREFERRED_FREQ_SCORE, &error);
 +      if (!error && integer >= 0)
 +              connman_ins_settings.ins_preferred_freq_score = integer;
 +
 +      g_clear_error(&error);
 +
 +      ins_security_priority = g_key_file_get_string_list(config, "INS",
 +                      CONF_INS_SECURITY_PRIORITY, &len, &error);
 +
 +      if (error == NULL) {
 +              connman_ins_settings.ins_security_priority = ins_security_priority;
 +              connman_ins_settings.ins_security_priority_count = len;
 +      }
 +
 +      g_clear_error(&error);
 +
 +      integer = g_key_file_get_integer(config, "INS",
 +                      CONF_INS_SECURITY_PRIORITY_SCORE, &error);
 +      if (!error && integer >= 0)
 +              connman_ins_settings.ins_security_priority_score = integer;
 +
 +      g_clear_error(&error);
 +
 +      boolean = __connman_config_get_bool(config, "INS",
 +                      CONF_INS_SIGNAL, &error);
 +      if (!error)
 +              connman_ins_settings.ins_signal = boolean;
 +
 +      g_clear_error(&error);
 +
 +      boolean = __connman_config_get_bool(config, "INS",
 +                      CONF_INS_INTERNET, &error);
 +      if (!error)
 +              connman_ins_settings.ins_internet = boolean;
 +
 +      g_clear_error(&error);
 +
 +      integer = g_key_file_get_integer(config, "INS",
 +                      CONF_INS_INTERNET_SCORE, &error);
 +      if (!error && integer >= 0)
 +              connman_ins_settings.ins_internet_score = integer;
 +
 +      g_clear_error(&error);
 +
 +      integer = g_key_file_get_integer(config, "INS",
 +                      CONF_INS_SIGNAL_LEVEL3_5GHZ, &error);
 +      if (!error)
 +              connman_ins_settings.ins_signal_level3_5ghz = integer;
 +
 +      g_clear_error(&error);
 +
 +      integer = g_key_file_get_integer(config, "INS",
 +                      CONF_INS_SIGNAL_LEVEL3_24GHZ, &error);
 +      if (!error)
 +              connman_ins_settings.ins_signal_level3_24ghz = integer;
 +
 +      g_clear_error(&error);
 +}
 +
 +static void check_Tizen_configuration(GKeyFile *config)
 +{
 +      GError *error = NULL;
 +      char **cellular_interfaces;
 +      char *global_nameserver;
 +      char *default_wifi_ifname;
 +      bool boolean;
 +      gsize len;
 +
 +      cellular_interfaces = g_key_file_get_string_list(config, "General",
 +                      CONF_CELLULAR_INTERFACE, &len, &error);
 +
 +      if (error == NULL)
 +              connman_settings.cellular_interfaces = cellular_interfaces;
 +
 +      g_clear_error(&error);
 +
 +      boolean = __connman_config_get_bool(config, "General",
 +                      CONF_TIZEN_TV_EXT, &error);
 +      if (!error)
 +              connman_settings.tizen_tv_extension = boolean;
 +
 +      g_clear_error(&error);
 +
 +      boolean = __connman_config_get_bool(config, "General",
 +                      CONF_ENABLE_AUTO_IP, &error);
 +      if (!error)
 +              connman_settings.auto_ip = boolean;
 +
 +      g_clear_error(&error);
 +
 +      global_nameserver = __connman_config_get_string(config, "General",
 +                                      CONF_GLOBAL_NAMESERVER, &error);
 +      if (!error)
 +              connman_settings.global_nameserver = global_nameserver;
 +
 +      g_clear_error(&error);
 +
 +      boolean = __connman_config_get_bool(config, "General",
 +                      CONF_CONNMAN_SUPPLICANT_DEBUG, &error);
 +      if (!error)
 +              connman_settings.supplicant_debug = boolean;
 +
 +      g_clear_error(&error);
 +
 +      default_wifi_ifname = __connman_config_get_string(config, "General",
 +                      CONF_CONNMAN_WIFI_DEF_IFNAME, &error);
 +      if (!error)
 +              connman_settings.def_wifi_ifname = default_wifi_ifname;
 +
 +      g_clear_error(&error);
 +
 +      boolean = __connman_config_get_bool(config, "General",
 +                      CONF_CONNMAN_FILE_LOG, &error);
 +      if (!error)
 +              connman_settings.file_log = boolean;
 +
 +      g_clear_error(&error);
 +
 +      boolean = __connman_config_get_bool(config, "General",
 +                      CONF_CONNMAN_DLOG_LOG, &error);
 +      if (!error)
 +              connman_settings.dlog_log = boolean;
 +
 +      g_clear_error(&error);
 +
 +      boolean = __connman_config_get_bool(config, "General",
 +                      CONF_CONNMAN_SIMPLIFIED_LOG, &error);
 +      if (!error)
 +              connman_settings.simple_log = boolean;
 +
 +      boolean = __connman_config_get_bool(config, "General",
 +                      CONF_CONNMAN_WIFI_ROAM_SCAN, &error);
 +      if (!error)
 +              connman_settings.wifi_roam_scan = boolean;
 +
 +      boolean = __connman_config_get_bool(config, "General",
 +                      CONF_CONNMAN_WIFI_ROAM, &error);
 +      if (!error)
 +              connman_settings.wifi_roam = boolean;
 +
 +      g_clear_error(&error);
 +
 +      check_Tizen_INS_configuration(config);
 +}
 +
 +static void set_nofile_inc(void)
 +{
 +      int err;
 +      struct rlimit rlim;
 +
 +      rlim.rlim_cur = 8192;
 +      rlim.rlim_max = 8192;
 +
 +      err = setrlimit(RLIMIT_NOFILE, &rlim);
 +      if (err)
 +              DBG("fail to increase FILENO err(%d)", err);
 +
 +      return;
 +}
 +#endif
 +
  static void parse_config(GKeyFile *config)
  {
        GError *error = NULL;
        char **interfaces;
        char **str_list;
        char **tethering;
-         char *vendor_class_id;
+       char *string;
        gsize len;
-       int timeout;
+       int integer;
  
        if (!config) {
                connman_settings.auto_connect =
                connman_settings.auto_connect =
                        parse_service_types(default_auto_connect, CONF_ARRAY_SIZE(default_auto_connect));
  
 +      g_strfreev(str_list);
 +
        g_clear_error(&error);
  
        str_list = __connman_config_get_string_list(config, "General",
  
        g_clear_error(&error);
  
-       timeout = g_key_file_get_integer(config, "General",
+       integer = g_key_file_get_integer(config, "General",
                        CONF_TIMEOUT_INPUTREQ, &error);
-       if (!error && timeout >= 0)
-               connman_settings.timeout_inputreq = timeout * 1000;
+       if (!error && integer >= 0)
+               connman_settings.timeout_inputreq = integer * 1000;
  
        g_clear_error(&error);
  
-       timeout = g_key_file_get_integer(config, "General",
+       integer = g_key_file_get_integer(config, "General",
                        CONF_TIMEOUT_BROWSERLAUNCH, &error);
-       if (!error && timeout >= 0)
-               connman_settings.timeout_browserlaunch = timeout * 1000;
+       if (!error && integer >= 0)
+               connman_settings.timeout_browserlaunch = integer * 1000;
  
        g_clear_error(&error);
  
  
        g_clear_error(&error);
  
-       vendor_class_id = __connman_config_get_string(config, "General",
+       string = __connman_config_get_string(config, "General",
                                        CONF_VENDOR_CLASS_ID, &error);
        if (!error)
-               connman_settings.vendor_class_id = vendor_class_id;
+               connman_settings.vendor_class_id = string;
  
        g_clear_error(&error);
  
        g_clear_error(&error);
  
        boolean = __connman_config_get_bool(config, "General",
+                       CONF_ENABLE_ONLINE_TO_READY_TRANSITION, &error);
+       if (!error) {
+               connman_settings.enable_online_to_ready_transition = boolean;
+       }
+       g_clear_error(&error);
+       integer = g_key_file_get_integer(config, "General",
+                       CONF_ONLINE_CHECK_INITIAL_INTERVAL, &error);
+       if (!error && integer >= 0)
+               connman_settings.online_check_initial_interval = integer;
+       g_clear_error(&error);
+       integer = g_key_file_get_integer(config, "General",
+                       CONF_ONLINE_CHECK_MAX_INTERVAL, &error);
+       if (!error && integer >= 0)
+               connman_settings.online_check_max_interval = integer;
+       g_clear_error(&error);
+       if (connman_settings.online_check_initial_interval < 1 ||
+               connman_settings.online_check_initial_interval >
+               connman_settings.online_check_max_interval) {
+               connman_warn("Incorrect online check intervals [%u, %u]",
+                               connman_settings.online_check_initial_interval,
+                               connman_settings.online_check_max_interval);
+               connman_settings.online_check_initial_interval =
+                       DEFAULT_ONLINE_CHECK_INITIAL_INTERVAL;
+               connman_settings.online_check_max_interval =
+                       DEFAULT_ONLINE_CHECK_MAX_INTERVAL;
+       }
+       boolean = __connman_config_get_bool(config, "General",
                                CONF_AUTO_CONNECT_ROAMING_SERVICES, &error);
        if (!error)
                connman_settings.auto_connect_roaming_services = boolean;
                connman_settings.use_gateways_as_timeservers = boolean;
  
        g_clear_error(&error);
 +
 +#if defined TIZEN_EXT
 +      check_Tizen_configuration(config);
 +#endif
  }
  
  static int config_init(const char *file)
  {
        GKeyFile *config;
  
 +#if defined TIZEN_EXT
 +      set_nofile_inc();
 +#endif
        config = load_config(file);
        check_config(config);
        parse_config(config);
        if (config)
                g_key_file_free(config);
  
 +#if defined TIZEN_EXT
 +      set_simple_log_option(connman_settings.simple_log);
 +      set_dlog_logging_option(connman_settings.dlog_log);
 +      set_file_logging_option(connman_settings.file_log);
 +#endif
        return 0;
  }
  
@@@ -1127,7 -703,7 +1182,7 @@@ static GOptionEntry options[] = 
        { NULL },
  };
  
- const char *connman_option_get_string(const char *key)
+ char *connman_setting_get_string(const char *key)
  {
        if (g_str_equal(key, CONF_VENDOR_CLASS_ID))
                return connman_settings.vendor_class_id;
                        return option_wifi;
        }
  
 +#if defined TIZEN_EXT
 +      if (g_str_equal(key, CONF_GLOBAL_NAMESERVER))
 +              return connman_settings.global_nameserver;
 +
 +      if (g_str_equal(key, CONF_INS_PREFERRED_FREQ_BSSID))
 +              return connman_ins_settings.ins_preferred_freq_bssid;
 +
 +      if (g_str_equal(key, CONF_INS_PREFERRED_FREQ))
 +              return connman_ins_settings.ins_preferred_freq;
 +
 +      if (g_str_equal(key, CONF_CONNMAN_WIFI_DEF_IFNAME))
 +              return connman_settings.def_wifi_ifname;
 +#endif
        return NULL;
  }
  
@@@ -1178,6 -741,9 +1233,9 @@@ bool connman_setting_get_bool(const cha
        if (g_str_equal(key, CONF_ENABLE_ONLINE_CHECK))
                return connman_settings.enable_online_check;
  
+       if (g_str_equal(key, CONF_ENABLE_ONLINE_TO_READY_TRANSITION))
+               return connman_settings.enable_online_to_ready_transition;
        if (g_str_equal(key, CONF_AUTO_CONNECT_ROAMING_SERVICES))
                return connman_settings.auto_connect_roaming_services;
  
        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))
        if (g_str_equal(key, CONF_TETHERING_TECHNOLOGIES))
                return connman_settings.tethering_technologies;
  
 +#if defined TIZEN_EXT
 +      if (g_str_equal(key, CONF_CELLULAR_INTERFACE))
 +              return connman_settings.cellular_interfaces;
 +#endif
 +
 +#if defined TIZEN_EXT
 +      if (g_str_equal(key, CONF_INS_SECURITY_PRIORITY))
 +              return connman_ins_settings.ins_security_priority;
 +#endif
 +
        return NULL;
  }
  
@@@ -1403,21 -876,6 +1466,21 @@@ int main(int argc, char *argv[]
  
        __connman_dbus_init(conn);
  
 +#if defined TIZEN_EXT
 +      if (access(CONTAINER_FILE, F_OK) == 0) {
 +              g_main_loop_run(main_loop);
 +
 +              g_source_remove(signal);
 +              dbus_connection_unref(conn);
 +              g_main_loop_unref(main_loop);
 +
 +              __connman_dbus_cleanup();
 +              __connman_log_cleanup(option_backtrace);
 +
 +              return 0;
 +      }
 +#endif
 +
        if (!option_config)
                config_init(CONFIGMAINFILE);
        else
        __connman_service_init();
        __connman_peer_service_init();
        __connman_peer_init();
 +#if defined TIZEN_EXT_WIFI_MESH
 +      __connman_mesh_init();
 +#endif /* TIZEN_EXT_WIFI_MESH */
        __connman_provider_init();
        __connman_network_init();
        __connman_config_init();
        __connman_clock_init();
  
        __connman_ipconfig_init();
 +#if defined TIZEN_EXT
 +      __connman_rtnl_init(GIO_SOCKET_RETRY_COUNT);
 +#else /* TIZEN_EXT */
        __connman_rtnl_init();
 +#endif /* TIZEN_EXT */
        __connman_task_init();
        __connman_proxy_init();
        __connman_detect_init();
        __connman_dhcpv6_init();
        __connman_wpad_init();
        __connman_wispr_init();
 +#if !defined TIZEN_EXT
        __connman_rfkill_init();
        __connman_machine_init();
 +#endif
  
        g_free(option_config);
        g_free(option_device);
  
        g_source_remove(signal);
  
 +#if !defined TIZEN_EXT
        __connman_machine_cleanup();
        __connman_rfkill_cleanup();
 +#endif
        __connman_wispr_cleanup();
        __connman_wpad_cleanup();
        __connman_dhcpv6_cleanup();
        __connman_firewall_cleanup();
        __connman_peer_service_cleanup();
        __connman_peer_cleanup();
 +#if defined TIZEN_EXT_WIFI_MESH
 +      __connman_mesh_cleanup();
 +#endif /* TIZEN_EXT_WIFI_MESH */
        __connman_ippool_cleanup();
        __connman_device_cleanup();
        __connman_network_cleanup();
        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 --combined src/main.conf
index f761da7,df70e17..e734ecf
mode 100755,100644..100755
@@@ -24,7 -24,6 +24,7 @@@
  # regardless of wifi is connected or not, unless it is requested by
  # the user through a D-Bus call.
  # BackgroundScanning = true
 +BackgroundScanning = false
  
  # Assume that service gateways also function as timeservers.
  # UseGatewaysAsTimeservers = false
@@@ -36,7 -35,6 +36,7 @@@
  # mixed combination of fully qualified domain names, IPv4
  # and IPv6 addresses.
  # FallbackTimeservers =
 +#FallbackTimeservers = pool.ntp.org
  
  # List of fallback nameservers separated by "," used if no
  # nameservers are otherwise provided by the service. The
@@@ -63,7 -61,6 +63,7 @@@
  # the default route when compared to either a non-preferred
  # type or a preferred type further down in the list.
  # PreferredTechnologies =
 +PreferredTechnologies = wifi, ethernet
  
  # List of blacklisted network interfaces separated by ",".
  # Found interfaces will be compared to the list and will
@@@ -71,7 -68,6 +71,7 @@@
  # match any of the list entries. Default value is
  # vmnet,vboxnet,virbr,ifb,ve-,vb-.
  # NetworkInterfaceBlacklist = vmnet,vboxnet,virbr,ifb,ve-,vb-
 +NetworkInterfaceBlacklist = veth,vmnet,vboxnet,virbr,usb,rndis,rmnet,rev_rmnet,dummy,seth_td,seth_w
  
  # Allow ConnMan to change the system hostname. This can
  # happen for example if we receive DHCP hostname option.
@@@ -94,7 -90,6 +94,7 @@@
  # setting enabled applications will notice more network breaks than
  # normal. Default value is false.
  # SingleConnectedTechnology = false
 +SingleConnectedTechnology = true
  
  # List of technologies for which tethering is allowed separated by ",".
  # The default value is wifi,bluetooth,gadget. Only those technologies
  # Default value is true.
  # EnableOnlineCheck = false
  
+ # Range of intervals between two online check requests.
+ # When an online check request fails, another one is triggered after a
+ # longer interval. The intervals follow the power of two series of numbers
+ # between OnlineCheckInitialInterval and OnlineCheckMaxInterval.
+ # Default range is [1, 12], corresponding to the following intervals, in
+ # seconds: 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121 and 144.
+ # OnlineCheckInitialInterval = 1
+ # OnlineCheckMaxInterval = 12
+ # WARNING: Experimental feature!!!
+ # In addition to EnableOnlineCheck setting, enable or disable use of HTTP GET
+ # to detect the loss of end-to-end connectivity.
+ # If this setting is false, when the default service transitions to ONLINE
+ # state, the HTTP GET request is no more called until next cycle, initiated
+ # by a transition of the default service to DISCONNECT state.
+ # If this setting is true, the HTTP GET request keeps beeing called to guarantee
+ # that end-to-end connectivity is still successful. If not, the default service
+ # will transition to READY state, enabling another service to become the
+ # default one, in replacement.
+ # EnableOnlineToReadyTransition = false
  # List of technologies with AutoConnect = true which are always connected
  # regardless of PreferredTechnologies setting. Default value is empty and
  # will connect a technology only if it is at a higher preference than any
  # This setting has no effect if SingleConnectedTechnologies is enabled.
  # AlwaysConnectedTechnologies =
  
 +# Allow connman to add service gateway to the time server list.
 +# Default value is false.
 +# UseGatewaysAsTimeservers = false
 +
  # Enable auto connection of services in roaming.
  # If this setting is false, roaming services are not auto-connected by ConnMan.
  # Default value is false.
  # to an interface (in accordance with RFC 5227).
  # Default value is false.
  # AddressConflictDetection = false
 +
 +NetworkCellularInterfaceList = pdp,rmnet,seth_td,seth_w
 +
 +# Enable use of link-local address for auto-configuration.
 +# When a device fails to get IP address from DHCP server,
 +# ConnMan will start link-local address autoconfiguration and
 +# assign a link-local IP address to device.
 +# If this setting is false and device fails to get IP address
 +# from DHCP server then device state will be set to disconnected.
 +# Default value is true.
 +# EnableAutoIp = false
 +
 +# Allow connman to set additional global nameserver and it will be used
 +# if all nameservers are failed to resolve DNS query. The nameserver
 +# entries must be in numeric format.
 +# GlobalNameserver = 8.8.8.8
 +
 +# Enable supplicant debugging log
 +ConnmanSupplicantDebug = false
 +
 +# Save ConnMan log to file
 +FileLogging = false
 +
 +# Use dlog for ConnMan logging
 +DlogLogging = true
 +
 +# Some logs of low importance are omitted to reduce the amount of logs
 +SimplifiedLog = true
 +
 +# This value specifies which will be the default when there are multiple wifi interfaces.
 +# Default value is wlan0.
 +DefaultWifiInterface = wlan0
 +
 +# Allow ConnMan to start scan for wifi roaming when SNR and signal are weakened
 +# Default value is false.
 +# WifiRoamingScan = true
 +
 +# Allow ConnMan to start wifi roaming when SNR and signal are weakened
 +# and there is another BSS in better condition.
 +# Default value is false.
 +# WifiRoaming = true
 +
 +
 +[INS]
 +# INS(Intelligent Network Selection) configuration: BSSID Selection.
 +INSPreferredFreqBSSID = 5GHz
 +INSPreferredFreqBSSIDScore = 20
 +INSLastConnectedBSSID = true
 +INSLastConnectedBSSIDScore = 20
 +INSAssocReject = true
 +INSAssocRejectScore = 10
 +INSSignalBSSID = true
 +
 +# INS(Intelligent Network Selection) configuration: SSID Selection.
 +INSLastUserSelection = true
 +INSLastUserSelectionTime = 480
 +INSLastUserSelectionScore = 30
 +# (INSLastUserSelectionTime - selection time diff) / (INSLastUserSelectionTime / INSLastUserSelectionScore)
 +# This means '(480 - selection time) / x) <= 30'
 +INSLastConnected = true
 +INSLastConnectedScore = 30
 +INSPreferredFreq = 5GHz
 +INSPreferredFreqScore = 60
 +INSSecurityPriority = SAE,RSN
 +INSSecurityPriorityScore = 5
 +# In this case, SAE(10 score), RSN(5 score)
 +INSSignal = true
 +INSInternet = true
 +INSInternetScore = 30
 +
 +# INS(Intelligent Network Selection) configuration: Common.
 +INSSignalLevel3_5GHz = -76
 +INSSignalLevel3_24GHz = -74
diff --combined src/manager.c
index 4f8306a,3bf8f4e..0000f78
mode 100755,100644..100755
@@@ -41,9 -41,6 +41,9 @@@ static DBusMessage *get_properties(DBus
        DBusMessageIter array, dict;
        dbus_bool_t offlinemode;
        const char *str;
 +#if defined TIZEN_EXT
 +      dbus_bool_t autoconnectmode;
 +#endif
  
        DBG("conn %p", conn);
  
        connman_dbus_dict_append_basic(&dict, "SessionMode",
                                        DBUS_TYPE_BOOLEAN,
                                        &sessionmode);
 +#if defined TIZEN_EXT
 +      autoconnectmode = __connman_service_get_auto_connect_mode();
 +      connman_dbus_dict_append_basic(&dict, "AutoConnectMode",
 +                                      DBUS_TYPE_BOOLEAN,
 +                                      &autoconnectmode);
 +#endif
  
        connman_dbus_dict_close(&array, &dict);
  
@@@ -118,17 -109,7 +118,17 @@@ static DBusMessage *set_property(DBusCo
                        return __connman_error_invalid_arguments(msg);
  
                dbus_message_iter_get_basic(&value, &sessionmode);
 +#if defined TIZEN_EXT
 +      } else if (g_str_equal(name, "AutoConnectMode") == TRUE) {
 +              bool automode;
  
 +              if (type != DBUS_TYPE_BOOLEAN)
 +                      return __connman_error_invalid_arguments(msg);
 +
 +              dbus_message_iter_get_basic(&value, &automode);
 +
 +              __connman_service_set_auto_connect_mode(automode);
 +#endif
        } else
                return __connman_error_invalid_property(msg);
  
@@@ -145,9 -126,7 +145,9 @@@ static DBusMessage *get_technologies(DB
  {
        DBusMessage *reply;
  
 +#if !defined TIZEN_EXT
        DBG("");
 +#endif
  
        reply = dbus_message_new_method_return(msg);
        if (!reply)
@@@ -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);
@@@ -616,114 -521,6 +616,114 @@@ error
  
  }
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +static void append_mesh_peer_structs(DBusMessageIter *iter, void *user_data)
 +{
 +      __connman_mesh_peer_list_struct(iter);
 +}
 +
 +static DBusMessage *get_mesh_peers(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_mesh_peer_structs, NULL);
 +      return reply;
 +}
 +
 +static DBusMessage *get_connected_mesh_peers(DBusConnection *conn,
 +                                      DBusMessage *msg, void *data)
 +{
 +      DBusMessage *reply;
 +      DBusMessageIter iter, array;
 +
 +      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_STRUCT_BEGIN_CHAR_AS_STRING
 +                      DBUS_TYPE_ARRAY_AS_STRING
 +                              DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
 +                                      DBUS_TYPE_STRING_AS_STRING
 +                                      DBUS_TYPE_VARIANT_AS_STRING
 +                              DBUS_DICT_ENTRY_END_CHAR_AS_STRING
 +                      DBUS_STRUCT_END_CHAR_AS_STRING, &array);
 +
 +      __connman_mesh_connected_peer_list_struct(&array);
 +      dbus_message_iter_close_container(&iter, &array);
 +      return reply;
 +}
 +
 +static DBusMessage *get_disconnected_mesh_peers(DBusConnection *conn,
 +                                      DBusMessage *msg, void *data)
 +{
 +      DBusMessage *reply;
 +      DBusMessageIter iter, array;
 +
 +      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_STRUCT_BEGIN_CHAR_AS_STRING
 +                      DBUS_TYPE_ARRAY_AS_STRING
 +                              DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
 +                                      DBUS_TYPE_STRING_AS_STRING
 +                                      DBUS_TYPE_VARIANT_AS_STRING
 +                              DBUS_DICT_ENTRY_END_CHAR_AS_STRING
 +                      DBUS_STRUCT_END_CHAR_AS_STRING, &array);
 +
 +      __connman_mesh_disconnected_peer_list_struct(&array);
 +      dbus_message_iter_close_container(&iter, &array);
 +      return reply;
 +}
 +
 +static DBusMessage *mesh_add_peer(DBusConnection *conn,
 +                                      DBusMessage *msg, void *user_data)
 +{
 +      const char *addr;
 +      int err;
 +
 +      dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &addr,
 +                                                      DBUS_TYPE_INVALID);
 +
 +      DBG("Address %s", addr);
 +
 +      err = __connman_mesh_change_peer_status(msg, addr, CONNMAN_MESH_PEER_ADD);
 +      if (err < 0)
 +              return __connman_error_failed(msg, -err);
 +
 +      return NULL;
 +}
 +
 +static DBusMessage *mesh_remove_peer(DBusConnection *conn,
 +                                      DBusMessage *msg, void *user_data)
 +{
 +      const char *addr;
 +      int err;
 +
 +      dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &addr,
 +                                                      DBUS_TYPE_INVALID);
 +
 +      DBG("Address %s", addr);
 +
 +      err = __connman_mesh_change_peer_status(msg, addr,
 +                                                                              CONNMAN_MESH_PEER_REMOVE);
 +      if (err < 0)
 +              return __connman_error_failed(msg, -err);
 +
 +      return NULL;
 +}
 +#endif
 +
  static const GDBusMethodTable manager_methods[] = {
        { GDBUS_METHOD("GetProperties",
                        NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
        { GDBUS_METHOD("GetServices",
                        NULL, GDBUS_ARGS({ "services", "a(oa{sv})" }),
                        get_services) },
 +#if defined TIZEN_EXT
 +      { GDBUS_METHOD("GetInterfaces",
 +                      NULL, GDBUS_ARGS({ "interface_list", "as" }),
 +                      get_interfaces) },
 +      { GDBUS_METHOD("GetDefaultService",
 +                      NULL, GDBUS_ARGS({ "service", "oa{sv}" }),
 +                      get_default_service) },
 +      { GDBUS_METHOD("GetConnectedService",
 +                      GDBUS_ARGS({ "ifname", "s" }),
 +                      GDBUS_ARGS({ "service", "oa{sv}" }),
 +                      get_connected_service) },
 +#endif
 +#if defined TIZEN_EXT_INS
 +      { GDBUS_METHOD("GetINS",
 +                      NULL, GDBUS_ARGS({ "services", "a(oa{sv})" }),
 +                      get_ins) },
 +#endif
        { GDBUS_METHOD("GetPeers",
                        NULL, GDBUS_ARGS({ "peers", "a(oa{sv})" }),
                        get_peers) },
        { GDBUS_METHOD("UnregisterPeerService",
                        GDBUS_ARGS({ "specification", "a{sv}" }), NULL,
                        unregister_peer_service) },
 +#if defined TIZEN_EXT_WIFI_MESH
 +      { GDBUS_METHOD("GetMeshPeers",
 +                      NULL, GDBUS_ARGS({ "peers", "a(oa{sv})" }),
 +                      get_mesh_peers) },
 +      { GDBUS_METHOD("GetConnectedMeshPeers",
 +                      NULL, GDBUS_ARGS({ "peers", "a(a{sv})" }),
 +                      get_connected_mesh_peers) },
 +      { GDBUS_METHOD("GetDisconnectedMeshPeers",
 +                      NULL, GDBUS_ARGS({ "peers", "a(a{sv})" }),
 +                      get_disconnected_mesh_peers) },
 +      { GDBUS_ASYNC_METHOD("MeshAddPeer", GDBUS_ARGS({ "address", "s" }), NULL,
 +                                 mesh_add_peer) },
 +      { GDBUS_ASYNC_METHOD("MeshRemovePeer", GDBUS_ARGS({ "address", "s" }), NULL,
 +                                 mesh_remove_peer) },
 +#endif
        { },
  };
  
diff --combined src/network.c
index 6849c1b,b12bbc0..7046137
mode 100755,100644..100755
  
  #define DHCP_RETRY_TIMEOUT     10
  
 +#if defined TIZEN_EXT
 +static unsigned char invalid_bssid[WIFI_BSSID_LEN_MAX] = {
 +      0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 +};
 +#endif
 +
  static GSList *network_list = NULL;
  static GSList *driver_list = NULL;
  
@@@ -113,52 -107,8 +113,52 @@@ struct connman_network 
                bool wps_advertizing;
                bool use_wps;
                char *pin_wps;
 +#if defined TIZEN_EXT
 +              char encryption_mode[WIFI_ENCYPTION_MODE_LEN_MAX];
 +              unsigned char bssid[WIFI_BSSID_LEN_MAX];
 +              unsigned int maxrate;
 +              int maxspeed;
 +              bool isHS20AP;
 +              unsigned int keymgmt;
 +              char *keymgmt_type;
 +              bool rsn_mode;
 +              bool pmf_required;
 +              int disconnect_reason;
 +              int assoc_status_code;
 +              GSList *vsie_list;
 +              /*
 +              * Only for EAP-FAST
 +              */
 +              char *phase1;
 +              unsigned char country_code[WIFI_COUNTRY_CODE_LEN];
 +              GSList *bssid_list;
 +              GSList *sec_list;
 +              ieee80211_modes_e phy_mode;
 +              connection_mode_e connection_mode;
 +              char *connector;
 +              char *c_sign_key;
 +              char *net_access_key;
 +#endif
 +#if defined TIZEN_EXT
 +              unsigned char last_connected_bssid[WIFI_BSSID_LEN_MAX];
 +              GHashTable *assoc_reject_table;
 +              bool owe_transition_mode;
 +              void *transition_mode_ssid;
 +              int transition_mode_ssid_len;
 +              unsigned char transition_mode_bssid[WIFI_BSSID_LEN_MAX];
 +              bool roaming_progress;
 +              char *roaming_cur_bssid;
 +              char *roaming_dst_bssid;
 +              __time_t roam_scan_time;
 +              int snr;
 +#endif
        } wifi;
  
 +#if defined TIZEN_EXT
 +      /* Multiple APN services and a default APN which a user selected */
 +      bool default_internet;
 +#endif
 +
  };
  
  static const char *type2string(enum connman_network_type type)
@@@ -254,11 -204,7 +254,11 @@@ static void acd_host_ipv4_available(str
        if (err < 0)
                goto err;
  
 +#if defined TIZEN_EXT
 +      err = __connman_ipconfig_gateway_add(ipconfig_ipv4, service);
 +#else
        err = __connman_ipconfig_gateway_add(ipconfig_ipv4);
 +#endif
        if (err < 0)
                goto err;
  
@@@ -498,11 -444,7 +498,11 @@@ static void dhcp_success(struct connman
        if (err < 0)
                goto err;
  
 +#if defined TIZEN_EXT
 +      err = __connman_ipconfig_gateway_add(ipconfig_ipv4, service);
 +#else
        err = __connman_ipconfig_gateway_add(ipconfig_ipv4);
 +#endif
        if (err < 0)
                goto err;
  
@@@ -561,10 -503,6 +561,10 @@@ static int set_connected_manual(struct 
        ipconfig = __connman_service_get_ip4config(service);
        __connman_ipconfig_enable(ipconfig);
  
 +#if defined TIZEN_EXT
 +      if (!service || !ipconfig)
 +              return -EINVAL;
 +#endif
        if (!__connman_ipconfig_get_local(ipconfig))
                __connman_service_read_ip4config(service);
  
        if (err < 0)
                goto err;
  
 +#if defined TIZEN_EXT
 +      err = __connman_ipconfig_gateway_add(ipconfig, service);
 +#else
        err = __connman_ipconfig_gateway_add(ipconfig);
 +#endif
        if (err < 0)
                goto err;
  
@@@ -685,11 -619,7 +685,11 @@@ static int manual_ipv6_set(struct connm
                return err;
        }
  
 +#if defined TIZEN_EXT
 +      err = __connman_ipconfig_gateway_add(ipconfig_ipv6, service);
 +#else
        err = __connman_ipconfig_gateway_add(ipconfig_ipv6);
 +#endif
        if (err < 0)
                return err;
  
@@@ -746,10 -676,6 +746,10 @@@ static int dhcpv6_set_addresses(struct 
        network->connecting = false;
  
        ipconfig_ipv6 = __connman_service_get_ip6config(service);
 +#if defined TIZEN_EXT
 +      if (!ipconfig_ipv6)
 +              goto err;
 +#endif
        err = __connman_ipconfig_address_add(ipconfig_ipv6);
        if (err < 0)
                goto err;
@@@ -837,9 -763,6 +837,9 @@@ static void check_dhcpv6(struct nd_rout
                                                check_dhcpv6, network);
                        return;
                }
 +#if defined TIZEN_EXT
 +              DBG("RA message is not received from server in reply of RS.");
 +#endif
                connman_network_unref(network);
                return;
        }
         */
        if (!network->connected) {
                connman_network_unref(network);
 +#if defined TIZEN_EXT
 +              DBG("Network is not connected");
 +#endif
                return;
        }
  
         * We do stateful/stateless DHCPv6 if router advertisement says so.
         */
        if (reply->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) {
 +#if defined TIZEN_EXT
 +              DBG("IPv6 ND_RA_FLAG_MANAGED");
 +#endif
                __connman_dhcpv6_start(network, prefixes, dhcpv6_callback);
        } else {
                if (reply->nd_ra_flags_reserved & ND_RA_FLAG_OTHER)
 +#if defined TIZEN_EXT
 +              {
 +                      DBG("IPv6 ND_RA_FLAG_OTHER");
 +#endif
                        __connman_dhcpv6_start_info(network,
                                                        dhcpv6_info_callback);
 +#if defined TIZEN_EXT
 +              }
 +#endif
  
                g_slist_free_full(prefixes, g_free);
                network->connecting = false;
@@@ -978,11 -888,6 +978,11 @@@ static void autoconf_ipv6_set(struct co
  
        __connman_device_set_network(network->device, network);
  
 +#if defined TIZEN_EXT
 +      if(network->type == CONNMAN_NETWORK_TYPE_CELLULAR)
 +              return;
 +#endif
 +
        service = connman_service_lookup_from_network(network);
        if (!service)
                return;
@@@ -1118,23 -1023,12 +1118,23 @@@ static void set_disconnected(struct con
                                        CONNMAN_IPCONFIG_TYPE_IPV6);
  
        if (network->connected) {
 +#if defined TIZEN_EXT
 +              /**
 +               * Do not remove gateway and its address,
 +               * if there are connected profiles that use same interface (multiple PDN)
 +               */
 +              if (connman_service_get_type(service) != CONNMAN_SERVICE_TYPE_CELLULAR ||
 +                              __connman_service_get_connected_count_of_iface(service) <= 0) {
 +#endif
                __connman_connection_gateway_remove(service,
                                                CONNMAN_IPCONFIG_TYPE_ALL);
  
                __connman_ipconfig_address_unset(ipconfig_ipv4);
                __connman_ipconfig_address_unset(ipconfig_ipv6);
  
 +#if defined TIZEN_EXT
 +              }
 +#endif
                /*
                 * Special handling for IPv6 autoconfigured address.
                 * The simplest way to remove autoconfigured routes is to
@@@ -1180,9 -1074,7 +1180,9 @@@ static int network_probe(struct connman
                        driver = NULL;
                        continue;
                }
 -
 +#if defined TIZEN_EXT
 +              if (!simplified_log)
 +#endif
                DBG("driver %p name %s", driver, driver->name);
  
                if (driver->probe(network) == 0)
@@@ -1347,10 -1239,6 +1347,10 @@@ static void network_destruct(struct con
        g_free(network->wifi.phase2_auth);
        g_free(network->wifi.pin_wps);
  
 +#if defined TIZEN_EXT
 +      g_slist_free_full(network->wifi.vsie_list, g_free);
 +      g_slist_free_full(network->wifi.bssid_list, g_free);
 +#endif
        g_free(network->path);
        g_free(network->group);
        g_free(network->node);
@@@ -1597,15 -1485,6 +1597,15 @@@ bool __connman_network_get_weakness(str
        return false;
  }
  
 +#if defined TIZEN_EXT
 +void connman_network_set_connecting(struct connman_network *network)
 +{
 +      DBG("set network connecting true");
 +      network->connecting = TRUE;
 +      return;
 +}
 +#endif
 +
  bool connman_network_get_connecting(struct connman_network *network)
  {
        return network->connecting;
  int connman_network_set_available(struct connman_network *network,
                                                bool available)
  {
 +#if !defined TIZEN_EXT
        DBG("network %p available %d", network, available);
 +#endif
  
        if (network->available == available)
                return -EALREADY;
@@@ -1644,120 -1521,6 +1644,120 @@@ bool connman_network_get_available(stru
        return network->available;
  }
  
 +#if defined TIZEN_EXT
 +void connman_network_clear_associating(struct connman_network *network)
 +{
 +      struct connman_service *service;
 +      enum connman_service_state state;
 +
 +      DBG("network %p", network);
 +
 +      network->connecting = FALSE;
 +      network->associating = FALSE;
 +
 +      service = connman_service_lookup_from_network(network);
 +      if (!service)
 +              return;
 +
 +      state = __connman_service_ipconfig_get_state(service,
 +                                              CONNMAN_IPCONFIG_TYPE_IPV4);
 +      if (state != CONNMAN_SERVICE_STATE_IDLE &&
 +                      state != CONNMAN_SERVICE_STATE_FAILURE)
 +              __connman_service_ipconfig_indicate_state(service,
 +                                      CONNMAN_SERVICE_STATE_DISCONNECT,
 +                                      CONNMAN_IPCONFIG_TYPE_IPV4);
 +
 +      state = __connman_service_ipconfig_get_state(service,
 +                                              CONNMAN_IPCONFIG_TYPE_IPV6);
 +      if (state != CONNMAN_SERVICE_STATE_IDLE &&
 +                              state != CONNMAN_SERVICE_STATE_FAILURE)
 +              __connman_service_ipconfig_indicate_state(service,
 +                                      CONNMAN_SERVICE_STATE_DISCONNECT,
 +                                      CONNMAN_IPCONFIG_TYPE_IPV6);
 +
 +      __connman_service_ipconfig_indicate_state(service,
 +                                              CONNMAN_SERVICE_STATE_IDLE,
 +                                              CONNMAN_IPCONFIG_TYPE_IPV4);
 +
 +      __connman_service_ipconfig_indicate_state(service,
 +                                              CONNMAN_SERVICE_STATE_IDLE,
 +                                              CONNMAN_IPCONFIG_TYPE_IPV6);
 +}
 +
 +static gboolean __connman_network_clear_associating_delayed(gpointer user_data)
 +{
 +      GSList *list;
 +      gboolean found = FALSE;
 +      enum connman_service_state state_ipv4;
 +      enum connman_service_state state_ipv6;
 +      struct connman_service *service;
 +      struct connman_network *network = (struct connman_network *)user_data;
 +
 +      for (list = network_list; list != NULL; list = list->next) {
 +              struct connman_network *item = list->data;
 +
 +              if (item == network) {
 +                      found = TRUE;
 +                      break;
 +              }
 +      }
 +
 +      if (found != TRUE)
 +              return FALSE;
 +
 +      DBG("network %p name %s", network, network->name);
 +      service = connman_service_lookup_from_network(network);
 +
 +      state_ipv4 = __connman_service_ipconfig_get_state(service,
 +                                              CONNMAN_IPCONFIG_TYPE_IPV4);
 +      state_ipv6 = __connman_service_ipconfig_get_state(service,
 +                                              CONNMAN_IPCONFIG_TYPE_IPV6);
 +
 +      DBG("service %p state %d/%d", service, state_ipv4, state_ipv6);
 +
 +      if (network->associating == FALSE &&
 +                      state_ipv4 == CONNMAN_SERVICE_STATE_ASSOCIATION &&
 +                      state_ipv6 == CONNMAN_SERVICE_STATE_ASSOCIATION) {
 +              __connman_service_ipconfig_indicate_state(service,
 +                              CONNMAN_SERVICE_STATE_IDLE,
 +                              CONNMAN_IPCONFIG_TYPE_IPV4);
 +              __connman_service_ipconfig_indicate_state(service,
 +                              CONNMAN_SERVICE_STATE_IDLE,
 +                              CONNMAN_IPCONFIG_TYPE_IPV6);
 +      } else {
 +              if (network->associating == FALSE) {
 +                      struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6;
 +                      enum connman_ipconfig_method ipv4_method, ipv6_method;
 +
 +                      ipconfig_ipv4 = __connman_service_get_ip4config(service);
 +                      ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4);
 +                      ipconfig_ipv6 = __connman_service_get_ip4config(service);
 +                      ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6);
 +
 +                      if((ipv4_method == CONNMAN_IPCONFIG_METHOD_UNKNOWN || ipv4_method == CONNMAN_IPCONFIG_METHOD_OFF) &&
 +                                      (state_ipv6 == CONNMAN_SERVICE_STATE_ASSOCIATION))
 +                              __connman_service_ipconfig_indicate_state(service,
 +                                              CONNMAN_SERVICE_STATE_IDLE,
 +                                              CONNMAN_IPCONFIG_TYPE_IPV6);
 +                      if((ipv6_method == CONNMAN_IPCONFIG_METHOD_UNKNOWN || ipv6_method == CONNMAN_IPCONFIG_METHOD_OFF) &&
 +                                      (state_ipv4 == CONNMAN_SERVICE_STATE_ASSOCIATION))
 +                              __connman_service_ipconfig_indicate_state(service,
 +                                              CONNMAN_SERVICE_STATE_IDLE,
 +                                              CONNMAN_IPCONFIG_TYPE_IPV4);
 +              }
 +      }
 +
 +      return FALSE;
 +}
 +#endif
 +
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +bool connman_network_check_validity(struct connman_network *network)
 +{
 +      return (NULL == g_slist_find(network_list, network)) ? false : true;
 +}
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
  /**
   * connman_network_set_associating:
   * @network: network structure
@@@ -1787,49 -1550,17 +1787,49 @@@ int connman_network_set_associating(str
                                        CONNMAN_IPCONFIG_TYPE_IPV6);
        }
  
 +#if defined TIZEN_EXT
 +      if (associating == FALSE &&
 +                      connman_network_get_bool(network, "WiFi.UseWPS") == FALSE)
 +              g_timeout_add_seconds(1,
 +                              __connman_network_clear_associating_delayed,
 +                              network);
 +#endif
 +
        return 0;
  }
  
 +#if defined TIZEN_EXT
 +static void set_authenticate_error(struct connman_network *network)
 +{
 +      struct connman_service *service;
 +
 +      service = connman_service_lookup_from_network(network);
 +
 +      if (!service)
 +              return;
 +
 +      __connman_service_indicate_error(service,
 +                                      CONNMAN_SERVICE_ERROR_AUTH_FAILED);
 +}
 +#endif
 +
 +
  static void set_associate_error(struct connman_network *network)
  {
        struct connman_service *service;
  
        service = connman_service_lookup_from_network(network);
  
 +#if defined TIZEN_EXT
 +      if (!service)
 +              return;
 +
 +      __connman_service_indicate_error(service,
 +                                      CONNMAN_SERVICE_ERROR_ASSOC_FAILED);
 +#else
        __connman_service_indicate_error(service,
                                        CONNMAN_SERVICE_ERROR_CONNECT_FAILED);
 +#endif
  }
  
  static void set_configure_error(struct connman_network *network)
@@@ -1848,10 -1579,6 +1848,10 @@@ static void set_invalid_key_error(struc
  
        service = connman_service_lookup_from_network(network);
  
 +#if defined TIZEN_EXT
 +      if (service)
 +              __connman_service_set_favorite(service, false);
 +#endif
        __connman_service_indicate_error(service,
                                        CONNMAN_SERVICE_ERROR_INVALID_KEY);
  }
@@@ -1876,22 -1603,6 +1876,22 @@@ static void set_blocked_error(struct co
                                        CONNMAN_SERVICE_ERROR_BLOCKED);
  }
  
 +
 +#if defined TIZEN_EXT
 +static void set_dhcp_error(struct connman_network *network)
 +{
 +      struct connman_service *service;
 +
 +      if (network->associating != FALSE)
 +              network->associating = FALSE;
 +
 +      service = connman_service_lookup_from_network(network);
 +
 +      __connman_service_indicate_error(service,
 +                                      CONNMAN_SERVICE_ERROR_DHCP_FAILED);
 +}
 +#endif
 +
  void connman_network_set_ipv4_method(struct connman_network *network,
                                        enum connman_ipconfig_method method)
  {
@@@ -1946,15 -1657,6 +1946,15 @@@ void connman_network_set_error(struct c
        case CONNMAN_NETWORK_ERROR_CONNECT_FAIL:
                set_connect_error(network);
                break;
 +#if defined TIZEN_EXT
 +      case CONNMAN_NETWORK_ERROR_AUTHENTICATE_FAIL:
 +              set_authenticate_error(network);
 +              break;
 +      case CONNMAN_NETWORK_ERROR_DHCP_FAIL:
 +              set_dhcp_error(network);
 +              break;
 +#endif
 +
        case CONNMAN_NETWORK_ERROR_BLOCKED:
                set_blocked_error(network);
                break;
@@@ -2095,42 -1797,20 +2095,42 @@@ int __connman_network_connect(struct co
        if (!network->device)
                return -ENODEV;
  
 +#if defined TIZEN_EXT
 +      if (network->type != CONNMAN_NETWORK_TYPE_CELLULAR)
 +#endif
        __connman_device_disconnect(network->device);
  
        network->connecting = true;
  
 +#if defined TIZEN_EXT
 +      DBG("ConnMan, Connect Request [%s]", network->name);
 +#endif
 +
        err = network->driver->connect(network);
        if (err < 0) {
 -              if (err == -EINPROGRESS)
 +              if (err == -EINPROGRESS) {
 +#if defined TIZEN_EXT
 +                      if (network->type != CONNMAN_NETWORK_TYPE_CELLULAR)
 +#endif
                        connman_network_set_associating(network, true);
 -              else
 +              else
                        network->connecting = false;
  
                return err;
        }
  
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      /*
 +       * Note: If EAP on Ethernet is ON, then network will be connected
 +       * after EAP Success event is recieved, from plugin/ethernet.c
 +       */
 +      struct connman_service *service = connman_service_lookup_from_network(network);
 +      if (service && __connman_service_get_use_eapol(service)) {
 +              connman_network_set_associating(network, true);
 +              return 0;
 +      }
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
        set_connected(network);
  
        return err;
  int __connman_network_disconnect(struct connman_network *network)
  {
        int err = 0;
 -
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        DBG("network %p", network);
  
        remove_ipv4ll_timeout(network);
  
        network->connecting = false;
  
 +#if defined TIZEN_EXT
 +      DBG("ConnMan, Disconnect request");
 +      struct connman_service *service = connman_service_lookup_from_network(network);
 +      connman_service_set_disconnection_requested(service, true);
 +#endif
        if (network->driver->disconnect)
                err = network->driver->disconnect(network);
  
@@@ -2224,38 -1897,12 +2224,38 @@@ int __connman_network_clear_ipconfig(st
        return 0;
  }
  
 +#if defined TIZEN_EXT
 +void __connman_network_set_auto_ipv6_gateway(char *gateway, void *user_data)
 +{
 +      DBG("");
 +
 +      struct connman_network *network = user_data;
 +      struct connman_service *service;
 +      struct connman_ipconfig *ipconfig = NULL;
 +
 +      service = connman_service_lookup_from_network(network);
 +      if (service == NULL)
 +              return;
 +
 +      ipconfig = __connman_service_get_ipconfig(service, AF_INET6);
 +      if (ipconfig == NULL)
 +              return;
 +
 +      __connman_ipconfig_set_gateway(ipconfig, gateway);
 +
 +      return;
 +}
 +#endif
 +
  int __connman_network_enable_ipconfig(struct connman_network *network,
                                struct connman_ipconfig *ipconfig)
  {
        int r = 0;
        enum connman_ipconfig_type type;
        enum connman_ipconfig_method method;
 +#if defined TIZEN_EXT
 +      struct connman_service *service;
 +#endif
  
        if (!network || !ipconfig)
                return -EINVAL;
                        break;
  
                case CONNMAN_IPCONFIG_METHOD_AUTO:
 +#if defined TIZEN_EXT
 +              service = connman_service_lookup_from_network(network);
 +
 +              if(network->type == CONNMAN_NETWORK_TYPE_CELLULAR)
 +                      __connman_service_ipconfig_indicate_state(service,
 +                              CONNMAN_SERVICE_STATE_CONFIGURATION,
 +                                      CONNMAN_IPCONFIG_TYPE_IPV6);
 +#endif
                        autoconf_ipv6_set(network);
                        break;
  
@@@ -2367,340 -2006,6 +2367,340 @@@ int connman_network_set_ipaddress(struc
        return 0;
  }
  
 +#if defined TIZEN_EXT
 +/*
 + * Description: Network client requires additional wifi specific info
 + */
 +int connman_network_set_bssid(struct connman_network *network,
 +                              const unsigned char *bssid)
 +{
 +      int i = 0;
 +
 +      if (bssid == NULL)
 +              return -EINVAL;
 +
 +      if (network->connected)
 +              return -EPERM;
 +
 +      if (!simplified_log)
 +              DBG("network %p bssid %02x:%02x:%02x:%02x:%02x:%02x", network,
 +                              bssid[0], bssid[1], bssid[2],
 +                              bssid[3], bssid[4], bssid[5]);
 +
 +      for (;i < WIFI_BSSID_LEN_MAX;i++)
 +              network->wifi.bssid[i] = bssid[i];
 +
 +      return 0;
 +}
 +
 +unsigned char *connman_network_get_bssid(struct connman_network *network)
 +{
 +      return (unsigned char *)network->wifi.bssid;
 +}
 +
 +int connman_network_set_transition_mode_bssid(struct connman_network *network,
 +                              const unsigned char *transition_mode_bssid)
 +{
 +      int i = 0;
 +
 +      if (transition_mode_bssid == NULL)
 +              return -EINVAL;
 +
 +      for (;i < WIFI_BSSID_LEN_MAX;i++)
 +              network->wifi.transition_mode_bssid[i] = transition_mode_bssid[i];
 +
 +      return 0;
 +}
 +
 +unsigned char *connman_network_get_transition_mode_bssid(struct connman_network *network)
 +{
 +      return (unsigned char *)network->wifi.transition_mode_bssid;
 +}
 +
 +bool connman_network_check_transition_mode(struct connman_network *network1, struct connman_network *network2)
 +{
 +
 +      if (network1 == NULL || network2 == NULL)
 +              return FALSE;
 +
 +      if (network1->wifi.owe_transition_mode == FALSE || network2->wifi.owe_transition_mode == FALSE)
 +              return FALSE;
 +
 +      if ((memcmp(network1->wifi.bssid, network2->wifi.transition_mode_bssid, WIFI_BSSID_LEN_MAX) == 0)
 +              && (memcmp(network1->wifi.transition_mode_bssid, network2->wifi.bssid, WIFI_BSSID_LEN_MAX) == 0))
 +              return TRUE;
 +      else
 +              return FALSE;
 +}
 +
 +int connman_network_set_maxspeed(struct connman_network *network,
 +                                int maxspeed)
 +{
 +      network->wifi.maxspeed = maxspeed;
 +        return 0;
 +}
 +
 +int connman_network_get_maxspeed(struct connman_network *network)
 +{
 +      if (!network->driver)
 +              return 0;
 +
 +      if (network->connected)
 +              return network->wifi.maxspeed;
 +
 +      return 0;
 +}
 +
 +int connman_network_set_sec_list(struct connman_network *network,
 +                                      GSList *sec_list)
 +{
 +      g_slist_free(network->wifi.sec_list);
 +      network->wifi.sec_list = sec_list;
 +
 +      return 0;
 +}
 +
 +void *connman_network_get_sec_list(struct connman_network *network)
 +{
 +      return network->wifi.sec_list;
 +}
 +
 +int connman_network_set_maxrate(struct connman_network *network,
 +                              unsigned int maxrate)
 +{
 +#if !defined TIZEN_EXT
 +      DBG("network %p maxrate %d", network, maxrate);
 +#endif
 +
 +      network->wifi.maxrate = maxrate;
 +
 +      return 0;
 +}
 +
 +unsigned int connman_network_get_maxrate(struct connman_network *network)
 +{
 +      return network->wifi.maxrate;
 +}
 +
 +int connman_network_set_enc_mode(struct connman_network *network,
 +                              const char *encryption_mode)
 +{
 +      if (encryption_mode == NULL)
 +              return -EINVAL;
 +
 +      if (!simplified_log)
 +              DBG("network %p encryption mode %s", network, encryption_mode);
 +
 +      g_strlcpy(network->wifi.encryption_mode, encryption_mode,
 +                                      WIFI_ENCYPTION_MODE_LEN_MAX);
 +
 +      return 0;
 +}
 +
 +const char *connman_network_get_enc_mode(struct connman_network *network)
 +{
 +      return (const char *)network->wifi.encryption_mode;
 +}
 +
 +int connman_network_set_rsn_mode(struct connman_network *network,
 +                              bool rsn_mode)
 +{
 +      network->wifi.rsn_mode = rsn_mode;
 +
 +      return 0;
 +}
 +
 +int connman_network_set_proxy(struct connman_network *network,
 +                              const char *proxies)
 +{
 +      struct connman_service *service;
 +
 +      DBG("network %p proxies %s", network, proxies);
 +
 +      service = connman_service_lookup_from_network(network);
 +      if (service == NULL)
 +              return -EINVAL;
 +
 +      __connman_service_set_proxy(service, proxies);
 +
 +      connman_service_set_proxy_method(service,
 +                              CONNMAN_SERVICE_PROXY_METHOD_MANUAL);
 +
 +      return 0;
 +}
 +
 +int connman_network_set_keymgmt(struct connman_network *network,
 +                              unsigned int keymgmt)
 +{
 +      if (network == NULL)
 +              return 0;
 +
 +      network->wifi.keymgmt = keymgmt;
 +
 +      return 0;
 +}
 +
 +unsigned int connman_network_get_keymgmt(struct connman_network *network)
 +{
 +      if (network == NULL)
 +              return 0;
 +
 +      return network->wifi.keymgmt;
 +}
 +
 +int connman_network_set_disconnect_reason(struct connman_network *network,
 +                              int reason_code)
 +{
 +      if (network == NULL)
 +              return 0;
 +
 +      network->wifi.disconnect_reason = reason_code;
 +
 +      return 0;
 +}
 +
 +int connman_network_get_disconnect_reason(struct connman_network *network)
 +{
 +      if (network == NULL)
 +              return 0;
 +
 +      return network->wifi.disconnect_reason;
 +}
 +int connman_network_get_assoc_status_code(struct connman_network *network)
 +{
 +      if (network == NULL)
 +              return 0;
 +
 +      return network->wifi.assoc_status_code;
 +}
 +
 +int connman_network_set_countrycode(struct connman_network *network,
 +                                  const unsigned char *country_code)
 +{
 +      int i = 0;
 +
 +      if (country_code == NULL)
 +              return -EINVAL;
 +
 +      if (!simplified_log)
 +              DBG("network %p Country Code %02x:%02x",network,
 +                              country_code[0],country_code[1]);
 +
 +      for (; i < WIFI_COUNTRY_CODE_LEN; i++)
 +              network->wifi.country_code[i] = country_code[i];
 +
 +      return 0;
 +}
 +
 +unsigned char *connman_network_get_countrycode(struct connman_network *network)
 +{
 +      return (unsigned char *)network->wifi.country_code;
 +}
 +
 +int connman_network_set_bssid_list(struct connman_network *network,
 +                                      GSList *bssids)
 +{
 +      g_slist_free_full(network->wifi.bssid_list, g_free);
 +      network->wifi.bssid_list = bssids;
 +
 +      return 0;
 +}
 +
 +int connman_network_set_phy_mode(struct connman_network *network,
 +                                  ieee80211_modes_e mode)
 +{
 +      if (!simplified_log)
 +              DBG("network %p phy mode %d", network, mode);
 +      network->wifi.phy_mode = mode;
 +
 +      return 0;
 +}
 +
 +ieee80211_modes_e connman_network_get_phy_mode(struct connman_network *network)
 +{
 +      return network->wifi.phy_mode;
 +}
 +
 +int connman_network_set_connection_mode(struct connman_network *network,
 +                                  connection_mode_e mode)
 +{
 +      DBG("network %p connection mode %d", network, mode);
 +      network->wifi.connection_mode = mode;
 +
 +      return 0;
 +}
 +
 +connection_mode_e connman_network_get_connection_mode(struct connman_network *network)
 +{
 +      return network->wifi.connection_mode;
 +}
 +
 +void *connman_network_get_bssid_list(struct connman_network *network)
 +{
 +      return network->wifi.bssid_list;
 +}
 +
 +int connman_network_set_last_connected_bssid(struct connman_network *network,
 +                              const unsigned char *bssid)
 +{
 +      if (!bssid)
 +              return -EINVAL;
 +
 +      if (!memcmp(bssid, invalid_bssid, WIFI_BSSID_LEN_MAX))
 +              return -EINVAL;
 +
 +      memcpy(network->wifi.last_connected_bssid, bssid, WIFI_BSSID_LEN_MAX);
 +
 +      return 0;
 +}
 +
 +unsigned char *connman_network_get_last_connected_bssid(struct connman_network *network)
 +{
 +      return (unsigned char *)network->wifi.last_connected_bssid;
 +}
 +
 +void connman_network_set_assoc_reject_table(struct connman_network *network,
 +              GHashTable *assoc_reject_table)
 +{
 +      if (!network)
 +              return;
 +
 +      if (!assoc_reject_table)
 +              return;
 +
 +      network->wifi.assoc_reject_table = assoc_reject_table;
 +}
 +
 +GHashTable *connman_network_get_assoc_reject_table(struct connman_network *network)
 +{
 +      if (!network)
 +              return NULL;
 +
 +      return network->wifi.assoc_reject_table;
 +}
 +
 +__time_t connman_network_get_roam_scan_time(struct connman_network *network)
 +{
 +      return network->wifi.roam_scan_time;
 +}
 +
 +void connman_network_set_roam_scan_time(struct connman_network *network,
 +                                              __time_t roam_scan_time)
 +{
 +      network->wifi.roam_scan_time = roam_scan_time;
 +}
 +
 +int connman_network_get_snr(struct connman_network *network)
 +{
 +      return network->wifi.snr;
 +}
 +
 +void connman_network_set_snr(struct connman_network *network, int snr)
 +{
 +      network->wifi.snr = snr;
 +}
 +#endif
 +
  int connman_network_set_nameservers(struct connman_network *network,
                                const char *nameservers)
  {
        nameservers_array = g_strsplit(nameservers, " ", 0);
  
        for (i = 0; nameservers_array[i]; i++) {
 +#if defined TIZEN_EXT
 +              __connman_service_nameserver_append(service,
 +                                              nameservers_array[i], false,
 +                                              CONNMAN_IPCONFIG_TYPE_ALL);
 +#else
                __connman_service_nameserver_append(service,
                                                nameservers_array[i], false);
 +#endif
        }
  
        g_strfreev(nameservers_array);
@@@ -2763,9 -2062,6 +2763,9 @@@ int connman_network_set_domain(struct c
  int connman_network_set_name(struct connman_network *network,
                                                        const char *name)
  {
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        DBG("network %p name %s", network, name);
  
        g_free(network->name);
@@@ -2786,9 -2082,6 +2786,9 @@@ int connman_network_set_strength(struc
                                                uint8_t strength)
  {
        network->strength = strength;
 +#if defined TIZEN_EXT
 +      __connman_service_notify_strength_changed(network);
 +#endif
  
        return 0;
  }
@@@ -2819,6 -2112,21 +2819,21 @@@ int connman_network_set_wifi_channel(st
        return 0;
  }
  
+ int connman_network_set_autoconnect(struct connman_network *network,
+                               bool autoconnect)
+ {
+       if (!network->driver || !network->driver->set_autoconnect)
+               return 0;
+       return network->driver->set_autoconnect(network, autoconnect);
+ }
+ bool __connman_network_native_autoconnect(struct connman_network *network)
+ {
+       if (!network->driver || !network->driver->set_autoconnect)
+               return false;
+       return true;
+ }
  uint16_t connman_network_get_wifi_channel(struct connman_network *network)
  {
        return network->wifi.channel;
@@@ -2851,9 -2159,6 +2866,9 @@@ int connman_network_set_string(struct c
                g_free(network->wifi.security);
                network->wifi.security = g_strdup(value);
        } else if (g_str_equal(key, "WiFi.Passphrase")) {
 +#if defined TIZEN_EXT
 +              DBG("ConnMan, %p key %s", network, key);
 +#endif
                g_free(network->wifi.passphrase);
                network->wifi.passphrase = g_strdup(value);
        } else if (g_str_equal(key, "WiFi.EAP")) {
        } else if (g_str_equal(key, "WiFi.PinWPS")) {
                g_free(network->wifi.pin_wps);
                network->wifi.pin_wps = g_strdup(value);
 +#if defined TIZEN_EXT
 +      } else if (g_str_equal(key, "WiFi.Connector")) {
 +              g_free(network->wifi.connector);
 +              network->wifi.connector = g_strdup(value);
 +      } else if (g_str_equal(key, "WiFi.CSignKey")) {
 +              g_free(network->wifi.c_sign_key);
 +              network->wifi.c_sign_key = g_strdup(value);
 +      } else if (g_str_equal(key, "WiFi.NetAccessKey")) {
 +              g_free(network->wifi.net_access_key);
 +              network->wifi.net_access_key = g_strdup(value);
 +      } else if (g_str_equal(key, "WiFi.RoamingCurBSSID")) {
 +              g_free(network->wifi.roaming_cur_bssid);
 +              network->wifi.roaming_cur_bssid = g_strdup(value);
 +      } else if (g_str_equal(key, "WiFi.RoamingDstBSSID")) {
 +              g_free(network->wifi.roaming_dst_bssid);
 +              network->wifi.roaming_dst_bssid = g_strdup(value);
 +#endif
        } else {
                return -EINVAL;
        }
@@@ -2972,18 -2260,6 +2987,18 @@@ const char *connman_network_get_string(
                return network->wifi.phase2_auth;
        else if (g_str_equal(key, "WiFi.PinWPS"))
                return network->wifi.pin_wps;
 +#if defined TIZEN_EXT
 +      else if (g_str_equal(key, "WiFi.Connector"))
 +              return network->wifi.connector;
 +      else if (g_str_equal(key, "WiFi.CSignKey"))
 +              return network->wifi.c_sign_key;
 +      else if (g_str_equal(key, "WiFi.NetAccessKey"))
 +              return network->wifi.net_access_key;
 +      else if (g_str_equal(key, "WiFi.RoamingCurBSSID"))
 +              return network->wifi.roaming_cur_bssid;
 +      else if (g_str_equal(key, "WiFi.RoamingDstBSSID"))
 +              return network->wifi.roaming_dst_bssid;
 +#endif
  
        return NULL;
  }
@@@ -3007,18 -2283,6 +3022,18 @@@ int connman_network_set_bool(struct con
                network->wifi.wps_advertizing = value;
        else if (g_strcmp0(key, "WiFi.UseWPS") == 0)
                network->wifi.use_wps = value;
 +#if defined TIZEN_EXT
 +      else if (g_strcmp0(key, "DefaultInternet") == 0)
 +              network->default_internet = value;
 +      else if (g_strcmp0(key, "WiFi.HS20AP") == 0)
 +              network->wifi.isHS20AP = value;
 +      else if (g_strcmp0(key, "WiFi.TRANSITION_MODE") == 0)
 +              network->wifi.owe_transition_mode = value;
 +      else if (g_strcmp0(key, "WiFi.Roaming") == 0)
 +              network->wifi.roaming_progress = value;
 +      else if (g_strcmp0(key, "WiFi.PMFRequired") == 0)
 +              network->wifi.pmf_required = value;
 +#endif
  
        return -EINVAL;
  }
@@@ -3041,48 -2305,10 +3056,48 @@@ bool connman_network_get_bool(struct co
                return network->wifi.wps_advertizing;
        else if (g_str_equal(key, "WiFi.UseWPS"))
                return network->wifi.use_wps;
 +#if defined TIZEN_EXT
 +      else if (g_str_equal(key, "DefaultInternet"))
 +              return network->default_internet;
 +      else if (g_str_equal(key, "WiFi.HS20AP"))
 +              return network->wifi.isHS20AP;
 +      else if (g_str_equal(key, "WiFi.TRANSITION_MODE"))
 +              return network->wifi.owe_transition_mode;
 +      else if (g_str_equal(key, "WiFi.Roaming"))
 +              return network->wifi.roaming_progress;
 +      else if (g_str_equal(key, "WiFi.PMFRequired"))
 +              return network->wifi.pmf_required;
 +#endif
  
        return false;
  }
  
 +#if defined TIZEN_EXT
 +/**
 + * connman_network_set_vsie_list:
 + * @network: network structure
 + * @vsie_list: GSList pointer
 + *
 + * Set vendor specific list pointer
 + */
 +void connman_network_set_vsie_list(struct connman_network *network, GSList *vsie_list)
 +{
 +      g_slist_free_full(network->wifi.vsie_list, g_free);
 +      network->wifi.vsie_list = vsie_list;
 +}
 +
 +/**
 + * connman_network_get_vsie_list:
 + * @network: network structure
 + *
 + * Get vendor specific list pointer
 + */
 +void *connman_network_get_vsie_list(struct connman_network *network)
 +{
 +      return network->wifi.vsie_list;
 +}
 +#endif
 +
  /**
   * connman_network_set_blob:
   * @network: network structure
@@@ -3103,16 -2329,6 +3118,16 @@@ int connman_network_set_blob(struct con
                        network->wifi.ssid_len = size;
                } else
                        network->wifi.ssid_len = 0;
 +#ifdef TIZEN_EXT
 +      } else if (g_str_equal(key, "WiFi.TRANSITION_MODE_SSID")) {
 +              g_free(network->wifi.transition_mode_ssid);
 +              network->wifi.transition_mode_ssid = g_try_malloc(size);
 +              if (network->wifi.transition_mode_ssid) {
 +                      memcpy(network->wifi.transition_mode_ssid, data, size);
 +                      network->wifi.transition_mode_ssid_len = size;
 +              } else
 +                      network->wifi.transition_mode_ssid_len = 0;
 +#endif
        } else {
                return -EINVAL;
        }
@@@ -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 --combined src/peer.c
index 2102f11,bad5c84..bad5c84
mode 100755,100644..100755
@@@ -154,7 -154,7 +154,7 @@@ static int start_dhcp_server(struct con
  
        err = __connman_inet_modify_address(RTM_NEWADDR,
                                NLM_F_REPLACE | NLM_F_ACK, index, AF_INET,
-                               gateway, NULL, prefixlen, broadcast);
+                               gateway, NULL, prefixlen, broadcast, true);
        if (err < 0)
                goto error;
  
@@@ -983,7 -983,10 +983,10 @@@ void connman_peer_add_service(struct co
  
        service = g_malloc0(sizeof(struct _peer_service));
        service->type = type;
-       service->data = g_memdup(data, data_length * sizeof(unsigned char));
+       if (data_length > 0) {
+               service->data = g_malloc(data_length * sizeof(unsigned char));
+               memcpy(service->data, data, data_length * sizeof(unsigned char));
+       }
        service->length = data_length;
  
        peer->services = g_slist_prepend(peer->services, service);
diff --combined src/provider.c
index c437c91,e209184..195ae22
mode 100755,100644..100755
@@@ -53,6 -53,7 +53,7 @@@ void __connman_provider_append_properti
                                                        DBusMessageIter *iter)
  {
        const char *host, *domain, *type;
+       dbus_bool_t split_routing;
  
        if (!provider->driver || !provider->driver->get_property)
                return;
        if (type)
                connman_dbus_dict_append_basic(iter, "Type", DBUS_TYPE_STRING,
                                                 &type);
+       if (provider->vpn_service) {
+               split_routing = connman_provider_is_split_routing(provider);
+               connman_dbus_dict_append_basic(iter, "SplitRouting",
+                                       DBUS_TYPE_BOOLEAN, &split_routing);
+       }
  }
  
  struct connman_provider *
@@@ -250,11 -257,7 +257,11 @@@ static int set_connected(struct connman
                }
  
                __connman_ipconfig_address_add(ipconfig);
 +#if defined TIZEN_EXT
 +              __connman_ipconfig_gateway_add(ipconfig, service);
 +#else
                __connman_ipconfig_gateway_add(ipconfig);
 +#endif
  
                provider_indicate_state(provider,
                                        CONNMAN_SERVICE_STATE_READY);
@@@ -439,6 -442,15 +446,15 @@@ const char *__connman_provider_get_iden
        return provider->identifier;
  }
  
+ const char * __connman_provider_get_transport_ident(
+                                       struct connman_provider *provider)
+ {
+       if (provider && provider && provider->driver && provider->driver->get_property)
+               return provider->driver->get_property(provider, "Transport");
+       return NULL;
+ }
  int connman_provider_set_string(struct connman_provider *provider,
                                        const char *key, const char *value)
  {
@@@ -584,14 -596,8 +600,14 @@@ int connman_provider_set_nameservers(st
                return 0;
  
        for (i = 0; nameservers[i]; i++)
 +#if defined TIZEN_EXT
 +              __connman_service_nameserver_append(provider->vpn_service,
 +                                              nameservers[i], false,
 +                                              CONNMAN_IPCONFIG_TYPE_ALL);
 +#else
                __connman_service_nameserver_append(provider->vpn_service,
                                                nameservers[i], false);
 +#endif
  
        return 0;
  }
@@@ -607,6 -613,100 +623,100 @@@ void connman_provider_set_autoconnect(s
                __connman_service_save(provider->vpn_service);
  }
  
+ bool connman_provider_is_split_routing(struct connman_provider *provider)
+ {
+       if (!provider || !provider->vpn_service)
+               return false;
+       return __connman_service_is_split_routing(provider->vpn_service);
+ }
+ int connman_provider_set_split_routing(struct connman_provider *provider,
+                                                       bool split_routing)
+ {
+       struct connman_service *service;
+       enum connman_ipconfig_type type;
+       int service_index;
+       int vpn_index;
+       bool service_split_routing;
+       int err = 0;
+       DBG("");
+       if (!provider || !provider->vpn_service)
+               return -EINVAL;
+       service_split_routing = __connman_service_is_split_routing(
+                               provider->vpn_service);
+       if (service_split_routing == split_routing) {
+               DBG("split_routing already set %s",
+                                       split_routing ? "true" : "false");
+               return -EALREADY;
+       }
+       switch (provider->family) {
+       case AF_INET:
+               type = CONNMAN_IPCONFIG_TYPE_IPV4;
+               break;
+       case AF_INET6:
+               type = CONNMAN_IPCONFIG_TYPE_IPV6;
+               break;
+       case AF_UNSPEC:
+               type = CONNMAN_IPCONFIG_TYPE_ALL;
+               break;
+       default:
+               type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
+       }
+       if (!__connman_service_is_connected_state(provider->vpn_service,
+                                                               type)) {
+               DBG("%p VPN not connected", provider->vpn_service);
+               goto save;
+       }
+       vpn_index = __connman_service_get_index(provider->vpn_service);
+       service_index = __connman_connection_get_vpn_phy_index(vpn_index);
+       service = __connman_service_lookup_from_index(service_index);
+       if (!service)
+               goto save;
+       if (split_routing)
+               err = __connman_service_move(service, provider->vpn_service,
+                                       true);
+       else
+               err = __connman_service_move(provider->vpn_service, service,
+                                       true);
+       if (err) {
+               connman_warn("cannot move service %p and VPN %p error %d",
+                                       service, provider->vpn_service, err);
+               /*
+                * In case of error notify vpnd about the current split routing
+                * state.
+                */
+               __connman_service_split_routing_changed(provider->vpn_service);
+               goto out;
+       }
+ save:
+       __connman_service_set_split_routing(provider->vpn_service,
+                                                               split_routing);
+       __connman_service_save(provider->vpn_service);
+ out:
+       return err;
+ }
+ int connman_provider_get_family(struct connman_provider *provider)
+ {
+       if (!provider)
+               return AF_UNSPEC;
+       return provider->family;
+ }
  static void unregister_provider(gpointer data)
  {
        struct connman_provider *provider = data;
diff --combined src/rtnl.c
  #define ARPHDR_PHONET_PIPE (821)
  #endif
  
 +#if defined TIZEN_EXT
 +#ifndef ARPHDR_RMNET
 +#define ARPHDR_RMNET (530)
 +#endif
 +#endif
 +
  #define print(arg...) do { if (0) connman_info(arg); } while (0)
  //#define print(arg...) connman_info(arg)
  
@@@ -100,7 -94,6 +100,7 @@@ static bool ether_blacklisted(const cha
        return false;
  }
  
 +#if !defined TIZEN_EXT
  static bool wext_interface(char *ifname)
  {
        struct iwreq wrq;
  
        return true;
  }
 +#endif
 +
 +#if defined TIZEN_EXT
 +static bool __connman_rtnl_is_cellular_device(const char *name)
 +{
 +      char **pattern;
 +      char **cellular_interfaces;
 +
 +      cellular_interfaces =
 +                      connman_setting_get_string_list(
 +                                      "NetworkCellularInterfaceList");
 +      if (!cellular_interfaces)
 +              return false;
 +
 +      for (pattern = cellular_interfaces; *pattern; pattern++) {
 +              if (g_str_has_prefix(name, *pattern)) {
 +                      DBG("Cellular interface: %s", name);
 +                      return true;
 +              }
 +      }
 +
 +      return false;
 +}
 +#endif
  
  static void read_uevent(struct interface_data *interface)
  {
  
        name = connman_inet_ifname(interface->index);
  
 +#if defined TIZEN_EXT
 +      if (__connman_rtnl_is_cellular_device(name)) {
 +              interface->service_type = CONNMAN_SERVICE_TYPE_CELLULAR;
 +              interface->device_type = CONNMAN_DEVICE_TYPE_CELLULAR;
 +              g_free(name);
 +              return;
 +      }
 +#endif
 +
        if (ether_blacklisted(name)) {
                interface->service_type = CONNMAN_SERVICE_TYPE_UNKNOWN;
                interface->device_type = CONNMAN_DEVICE_TYPE_UNKNOWN;
                } else if (strcmp(line + 8, "bond") == 0) {
                        interface->service_type = CONNMAN_SERVICE_TYPE_ETHERNET;
                        interface->device_type = CONNMAN_DEVICE_TYPE_ETHERNET;
+               } else if (strcmp(line + 8, "dsa") == 0) {
+                       interface->service_type = CONNMAN_SERVICE_TYPE_ETHERNET;
+                       interface->device_type = CONNMAN_DEVICE_TYPE_ETHERNET;
                } else {
                        interface->service_type = CONNMAN_SERVICE_TYPE_UNKNOWN;
                        interface->device_type = CONNMAN_DEVICE_TYPE_UNKNOWN;
        if (found_devtype)
                goto out;
  
 +#if !defined TIZEN_EXT
 +      /* TIZEN does not use old wext interface */
        /* We haven't got a DEVTYPE, let's check if it's a wireless device */
        if (wext_interface(name)) {
                interface->service_type = CONNMAN_SERVICE_TYPE_WIFI;
  
                connman_error("%s runs an unsupported 802.11 driver", name);
        }
 +#endif
  
  out:
        g_free(name);
@@@ -463,28 -423,6 +466,28 @@@ static void process_newlink(unsigned sh
        if (!extract_link(msg, bytes, &address, &ifname, &mtu, &operstate, &stats))
                return;
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +      /* Do not accept Wi-Fi Mesh interface */
 +      if (g_strrstr(ifname, "mesh") != NULL) {
 +              DBG("Newlink event for Wi-Fi Mesh interface ignored");
 +              return;
 +      }
 +
 +      /* Do not accept Wi-Fi WLAN1 interface "dedicated for softAP */
 +      if (!g_strcmp0(ifname, "wlan1")) {
 +              DBG("Newlink event for Wi-Fi WLAN1 interface ignored");
 +              return;
 +      }
 +#endif
 +
 +#if defined TIZEN_EXT
 +      /* Do not accept Wi-Fi P2P interface */
 +      if (g_strrstr(ifname, "p2p") != NULL) {
 +              DBG("Newlink event for Wi-Fi P2P interface ignored");
 +              return;
 +      }
 +#endif
 +
        snprintf(ident, 13, "%02x%02x%02x%02x%02x%02x",
                                                address.ether_addr_octet[0],
                                                address.ether_addr_octet[1],
                return;
        }
  
 +#ifdef TIZEN_EXT
 +      if (TIZEN_TV_EXT && g_strcmp0(ident, "eeeeeeeeeeee") == 0) {
 +              DBG("Newlink event with Dummy MAC. Ignored!");
 +              return;
 +      }
 +#endif
 +
        switch (type) {
        case ARPHRD_ETHER:
        case ARPHRD_LOOPBACK:
        case ARPHDR_PHONET_PIPE:
        case ARPHRD_PPP:
        case ARPHRD_NONE:
 +#if defined TIZEN_EXT
 +/*
 + * Description: ARPHDR_RMNET for QC modem using QMI
 + */
 +      case ARPHDR_RMNET:
 +#endif
                __connman_ipconfig_newlink(index, type, flags,
                                                        str, mtu, &stats);
                break;
  
                if (type == ARPHRD_ETHER)
                        read_uevent(interface);
 +#if defined TIZEN_EXT
 +              if (type == ARPHRD_PPP || type == ARPHDR_RMNET)
 +                      read_uevent(interface);
 +
 +      } else if (g_strcmp0(interface->ident, ident) != 0) {
 +              /* If an original address is built-in physical device,
 +               * it's hardly get an address at a initial creation
 +               */
 +              __connman_technology_remove_interface(interface->service_type,
 +                              interface->index, interface->ident);
 +
 +              g_free(interface->ident);
 +              interface->ident = g_strdup(ident);
 +
 +              __connman_technology_add_interface(interface->service_type,
 +                              interface->index, interface->ident);
 +
 +              interface = NULL;
 +#endif
        } else if (type == ARPHRD_ETHER && interface->device_type == CONNMAN_DEVICE_TYPE_UNKNOWN)
                read_uevent(interface);
        else
@@@ -633,13 -539,6 +636,13 @@@ static void process_dellink(unsigned sh
        case ARPHDR_PHONET_PIPE:
        case ARPHRD_PPP:
        case ARPHRD_NONE:
 +#if defined TIZEN_EXT
 +      /*
 +       * Description: SLP requires ARPHRD_PPP for PPP type device
 +       *              ARPHDR_RMNET for QC modem using QMI
 +       */
 +      case ARPHDR_RMNET:
 +#endif
                __connman_ipconfig_dellink(index, &stats);
                break;
        }
@@@ -1335,37 -1234,6 +1338,37 @@@ static void rtnl_newnduseropt(struct nl
        if (index < 0)
                return;
  
 +#if defined TIZEN_EXT
 +      struct connman_service *service;
 +      enum connman_service_state state;
 +      enum connman_dnsconfig_method ipv6_dns_method;
 +
 +      service = __connman_service_lookup_from_index(index);
 +      if (!service) {
 +              DBG("Invalid service");
 +              return;
 +      }
 +
 +      DBG("service: %p index: %d\n", service, index);
 +
 +      if (connman_setting_get_bool("SingleConnectedTechnology") == TRUE) {
 +              state = __connman_service_ipconfig_get_state(service, CONNMAN_IPCONFIG_TYPE_IPV6);
 +              if (state != CONNMAN_SERVICE_STATE_ASSOCIATION &&
 +                              state != CONNMAN_SERVICE_STATE_CONFIGURATION &&
 +                              state != CONNMAN_SERVICE_STATE_READY &&
 +                              state != CONNMAN_SERVICE_STATE_ONLINE) {
 +                      DBG("Service state[%d] is not connecting/connected", state);
 +                      return;
 +              }
 +      }
 +
 +      ipv6_dns_method = connman_service_get_ipv6_dns_method(service);
 +      if (ipv6_dns_method != CONNMAN_DNSCONFIG_METHOD_DHCP) {
 +              DBG("IPv6 DNS method is not Auto ignore RA!!! [DNS method: %d]", ipv6_dns_method);
 +              return;
 +      }
 +#endif
 +
        for (opt = (void *)&msg[1];
                        msglen > 0;
                        msglen -= opt->nd_opt_len * 8,
  
                if (opt->nd_opt_type == 25) { /* ND_OPT_RDNSS */
                        char buf[40];
 +#if defined TIZEN_EXT
 +                      struct connman_service *service;
  
 +                      service = __connman_service_lookup_from_index(index);
 +                      DBG("service: %p\n",service);
 +#endif
                        servers = rtnl_nd_opt_rdnss(opt, &lifetime,
                                                                &nr_servers);
                        for (i = 0; i < nr_servers; i++) {
                                                                sizeof(buf)))
                                        continue;
  
 +#if defined TIZEN_EXT
 +                              __connman_service_nameserver_remove(service,
 +                                              buf, false,
 +                                              CONNMAN_IPCONFIG_TYPE_IPV6);
 +                              __connman_service_nameserver_append(service,
 +                                              buf, false,
 +                                              CONNMAN_IPCONFIG_TYPE_IPV6);
 +#endif
                                connman_resolver_append_lifetime(index,
                                                        NULL, buf, lifetime);
                        }
@@@ -1587,15 -1442,8 +1590,15 @@@ static gboolean netlink_event(GIOChanne
        ssize_t status;
        int fd;
  
 +#if defined TIZEN_EXT
 +      if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
 +              __connman_rtnl_init(GIO_SOCKET_RETRY_COUNT);
 +              return FALSE;
 +      }
 +#else /* TIZEN_EXT */
        if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
                return FALSE;
 +#endif /* TIZEN_EXT */
  
        memset(buf, 0, sizeof(buf));
        memset(&nladdr, 0, sizeof(nladdr));
                if (errno == EINTR || errno == EAGAIN)
                        return TRUE;
  
 +#if defined TIZEN_EXT
 +              __connman_rtnl_init(GIO_SOCKET_RETRY_COUNT);
 +#endif /* TIZEN_EXT */
                return FALSE;
        }
  
 +#if defined TIZEN_EXT
 +      if (status == 0) {
 +              __connman_rtnl_init(GIO_SOCKET_RETRY_COUNT);
 +              return FALSE;
 +      }
 +#else /* TIZEN_EXT */
        if (status == 0)
                return FALSE;
 +#endif /* TIZEN_EXT */
  
        if (nladdr.nl_pid != 0) { /* not sent by kernel, ignore */
                DBG("Received msg from %u, ignoring it", nladdr.nl_pid);
@@@ -1766,34 -1604,19 +1769,34 @@@ int __connman_rtnl_request_update(void
        return send_getlink();
  }
  
 +#if defined TIZEN_EXT
 +int __connman_rtnl_init(int retry_count)
 +#else /* TIZEN_EXT */
  int __connman_rtnl_init(void)
 +#endif /* TIZEN_EXT */
  {
        struct sockaddr_nl addr;
        int sk;
  
 +#if defined TIZEN_EXT
 +      if (retry_count < 0)
 +              return -1;
 +
 +      DBG("retry_count %d", retry_count);
 +#else /* TIZEN_EXT */
        DBG("");
 +#endif /* TIZEN_EXT */
  
        interface_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
                                                        NULL, free_interface);
  
        sk = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_ROUTE);
        if (sk < 0)
 +#if defined TIZEN_EXT
 +              return __connman_rtnl_init(retry_count - 1);
 +#else /* TIZEN_EXT */
                return -1;
 +#endif /* TIZEN_EXT */
  
        memset(&addr, 0, sizeof(addr));
        addr.nl_family = AF_NETLINK;
  
        if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
                close(sk);
 +#if defined TIZEN_EXT
 +              return __connman_rtnl_init(retry_count - 1);
 +#else /* TIZEN_EXT */
                return -1;
 +#endif /* TIZEN_EXT */
        }
  
        channel = g_io_channel_unix_new(sk);
diff --combined src/service.c
index 19056a8,20917a8..411b617
mode 100755,100644..100755
  
  #define CONNECT_TIMEOUT               120
  
 +#if defined TIZEN_EXT
 +#define WIFI_BSSID_STR_LEN    18
 +#define MAX_WIFI_PROFILES     200
 +
 +#define FREQ_RANGE_24GHZ_CHANNEL_1   2412
 +#define FREQ_RANGE_24GHZ_CHANNEL_14  2484
 +#define FREQ_RANGE_5GHZ_CHANNEL_32   5160
 +#define FREQ_RANGE_5GHZ_CHANNEL_165  5825
 +
 +#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
 +#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
 +#endif
  #define VPN_AUTOCONNECT_TIMEOUT_DEFAULT 1
  #define VPN_AUTOCONNECT_TIMEOUT_STEP 30
  #define VPN_AUTOCONNECT_TIMEOUT_ATTEMPTS_THRESHOLD 270
@@@ -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;
@@@ -187,71 -137,13 +190,71 @@@ struct connman_service 
        bool wps;
        bool wps_advertizing;
        guint online_timeout;
-       int online_check_interval_ipv4;
-       int online_check_interval_ipv6;
+       unsigned int online_check_interval_ipv4;
+       unsigned int online_check_interval_ipv6;
        bool do_split_routing;
        bool new_service;
        bool hidden_service;
        char *config_file;
        char *config_entry;
 +#if defined TIZEN_EXT
 +      /*
 +       * Description: TIZEN implements system global connection management.
 +       *              It's only for PDP (cellular) bearer. Wi-Fi is managed
 +       *              by ConnMan automatically. Reference count can help to
 +       *              manage open/close connection requests by each application.
 +       */
 +      int user_pdn_connection_refcount;
 +      bool storage_reload;
 +      /*
 +       * Description: In case of EAP security type,
 +       *                                user can select the keymgmt type for roaming(802.11r).
 +       *                                - FT, CCKM, OKC, ...
 +       */
 +      char *keymgmt_type;
 +      int disconnect_reason;
 +      int assoc_status_code;
 +      /*
 +       * Only for EAP-FAST and EAP-PEAP in EAPoL.
 +       */
 +      char *phase1;
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      /*
 +       * Only for EAP-FAST
 +       */
 +      char *pac_file;
 +#endif
 +      /*
 +       * Description: To indicate that disconnection triggered by user.
 +       */
 +      bool disconnection_requested;
 +
 +      enum connman_dnsconfig_method dns_config_method_ipv4;
 +      enum connman_dnsconfig_method dns_config_method_ipv6;
 +#endif
 +#if defined TIZEN_EXT
 +      char *connector;
 +      char *c_sign_key;
 +      char *net_access_key;
 +      unsigned char last_connected_bssid[WIFI_BSSID_LEN_MAX];
 +      bool is_internet_connection;
 +      int assoc_reject_count;
 +#if defined TIZEN_EXT_INS
 +      int score_last_user_selection;
 +      int score_last_connected;
 +      int score_frequency;
 +      int score_security_priority;
 +      int score_internet_connection;
 +      int score_strength;
 +#endif
 +      int ins_score;
 +#endif
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      /*
 +       * To indicate use of EAP over Ethernet.
 +       */
 +      bool use_eapol;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
  };
  
  static bool allow_property_changed(struct connman_service *service);
@@@ -268,55 -160,6 +271,55 @@@ struct find_data 
        struct connman_service *service;
  };
  
 +#if defined TIZEN_EXT
 +struct assoc_reject_data {
 +      char *bssid;
 +      GSList *reject_time_list;
 +};
 +
 +/*
 + * Public APIs to use user_pdn_connection_refcount
 + */
 +void connman_service_user_pdn_connection_ref(struct connman_service *service)
 +{
 +      __sync_fetch_and_add(&service->user_pdn_connection_refcount, 1);
 +
 +      DBG("User made PDN connection referenced: %d",
 +                              service->user_pdn_connection_refcount);
 +}
 +
 +gboolean connman_service_user_pdn_connection_unref_and_test(
 +                                      struct connman_service *service)
 +{
 +      __sync_synchronize();
 +
 +      DBG("User made PDN connection referenced: %d, which will be decreased",
 +                              service->user_pdn_connection_refcount);
 +
 +      if (service->user_pdn_connection_refcount < 1)
 +              return TRUE;
 +
 +      if (__sync_sub_and_fetch(&service->user_pdn_connection_refcount, 1) == 0)
 +              return TRUE;
 +
 +      return FALSE;
 +}
 +
 +gboolean connman_service_is_no_ref_user_pdn_connection(
 +                                      struct connman_service *cellular)
 +{
 +      if (cellular == NULL)
 +              return TRUE;
 +
 +      __sync_synchronize();
 +      if (cellular->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
 +                      cellular->user_pdn_connection_refcount == 0)
 +              return TRUE;
 +
 +      return FALSE;
 +}
 +#endif
 +
  static void compare_path(gpointer value, gpointer user_data)
  {
        struct connman_service *service = value;
@@@ -352,6 -195,8 +355,8 @@@ static const char *reason2string(enum c
                return "auto";
        case CONNMAN_SERVICE_CONNECT_REASON_SESSION:
                return "session";
+       case CONNMAN_SERVICE_CONNECT_REASON_NATIVE:
+               return "native";
        }
  
        return "unknown";
@@@ -380,10 -225,6 +385,10 @@@ const char *__connman_service_type2stri
                return "gadget";
        case CONNMAN_SERVICE_TYPE_P2P:
                return "p2p";
 +#if defined TIZEN_EXT_WIFI_MESH
 +      case CONNMAN_SERVICE_TYPE_MESH:
 +              return "mesh";
 +#endif
        }
  
        return NULL;
@@@ -429,16 -270,6 +434,16 @@@ enum connman_service_security __connman
                return CONNMAN_SERVICE_SECURITY_NONE;
        if (!strcmp(str, "wep"))
                return CONNMAN_SERVICE_SECURITY_WEP;
 +#if defined TIZEN_EXT
 +      if (!strcmp(str, "rsn"))
 +              return CONNMAN_SERVICE_SECURITY_RSN;
 +      if (!strcmp(str, "sae"))
 +              return CONNMAN_SERVICE_SECURITY_SAE;
 +      if (!strcmp(str, "owe"))
 +              return CONNMAN_SERVICE_SECURITY_OWE;
 +      if (!strcmp(str, "dpp"))
 +              return CONNMAN_SERVICE_SECURITY_DPP;
 +#endif
  
        return CONNMAN_SERVICE_SECURITY_UNKNOWN;
  }
@@@ -454,20 -285,8 +459,20 @@@ static const char *security2string(enu
                return "wep";
        case CONNMAN_SERVICE_SECURITY_PSK:
        case CONNMAN_SERVICE_SECURITY_WPA:
 +#if defined TIZEN_EXT
 +              return "psk";
 +      case CONNMAN_SERVICE_SECURITY_RSN:
 +              return "rsn";
 +      case CONNMAN_SERVICE_SECURITY_SAE:
 +              return "sae";
 +      case CONNMAN_SERVICE_SECURITY_OWE:
 +              return "owe";
 +      case CONNMAN_SERVICE_SECURITY_DPP:
 +              return "dpp";
 +#else
        case CONNMAN_SERVICE_SECURITY_RSN:
                return "psk";
 +#endif
        case CONNMAN_SERVICE_SECURITY_8021X:
                return "ieee8021x";
        }
@@@ -516,10 -335,6 +521,10 @@@ static const char *error2string(enum co
                return "login-failed";
        case CONNMAN_SERVICE_ERROR_AUTH_FAILED:
                return "auth-failed";
 +#ifdef TIZEN_EXT
 +      case CONNMAN_SERVICE_ERROR_ASSOC_FAILED:
 +              return "assoc-failed";
 +#endif
        case CONNMAN_SERVICE_ERROR_INVALID_KEY:
                return "invalid-key";
        case CONNMAN_SERVICE_ERROR_BLOCKED:
@@@ -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;
                service->order = 0;
        else
                service->order = 10;
+       /*
+        * In order to make sure the value is propagated also when loading the
+        * VPN service signal the value regardless of the value change.
+        */
+       __connman_service_split_routing_changed(service);
  }
  
  int __connman_service_load_modifiable(struct connman_service *service)
        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:
        return 0;
  }
  
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +static void __connman_service_cleanup_8021x(struct connman_service *service)
 +{
 +      if (service == NULL)
 +              return;
 +
 +      DBG("service %p ", service);
 +
 +      __connman_service_set_string(service, "EAP", NULL);
 +      __connman_service_set_string(service, "Identity", NULL);
 +      __connman_service_set_string(service, "Passphrase", NULL);
 +      __connman_service_set_string(service, "AnonymousIdentity", NULL);
 +      __connman_service_set_string(service, "CACertFile", NULL);
 +      __connman_service_set_string(service, "ClientCertFile", NULL);
 +      __connman_service_set_string(service, "PrivateKeyFile", NULL);
 +      __connman_service_set_string(service, "PrivateKeyPassphrase", NULL);
 +      __connman_service_set_string(service, "Phase1", NULL);
 +      __connman_service_set_string(service, "Phase2", NULL);
 +      __connman_service_set_string(service, "PacFile", NULL);
 +}
 +
 +static int connman_service_set_eapol_property(struct connman_service *service,
 +                      DBusMessageIter *array)
 +{
 +      DBusMessageIter dict;
 +      char *str = NULL;
 +
 +      __connman_service_cleanup_8021x(service);
 +
 +      if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
 +              return -EINVAL;
 +
 +      dbus_message_iter_recurse(array, &dict);
 +
 +      while(dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
 +              DBusMessageIter entry, value;
 +              const char *key;
 +              int type;
 +
 +              dbus_message_iter_recurse(&dict, &entry);
 +
 +              if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
 +                      return -EINVAL;
 +
 +              dbus_message_iter_get_basic(&entry, &key);
 +              dbus_message_iter_next(&entry);
 +
 +              if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
 +                      return -EINVAL;
 +
 +              dbus_message_iter_recurse(&entry, &value);
 +
 +              type = dbus_message_iter_get_arg_type(&value);
 +
 +              if (g_str_equal(key, "UseEapol")) {
 +                      dbus_bool_t use_eapol;
 +
 +                      if (type != DBUS_TYPE_BOOLEAN)
 +                              return -EINVAL;
 +
 +                      dbus_message_iter_get_basic(&value, &use_eapol);
 +                      service->use_eapol = use_eapol;
 +
 +              } else if (g_str_equal(key, "EAP")) {
 +                      if (type != DBUS_TYPE_STRING)
 +                              return -EINVAL;
 +
 +                      dbus_message_iter_get_basic(&value, &str);
 +                      __connman_service_set_string(service, "EAP", str);
 +
 +              } else if (g_str_equal(key, "Identity")) {
 +                      if (type != DBUS_TYPE_STRING)
 +                              return -EINVAL;
 +
 +                      dbus_message_iter_get_basic(&value, &str);
 +                      __connman_service_set_string(service, "Identity", str);
 +
 +              } else if (g_str_equal(key, "AnonymousIdentity")) {
 +                      if (type != DBUS_TYPE_STRING)
 +                              return -EINVAL;
 +
 +                      dbus_message_iter_get_basic(&value, &str);
 +                      __connman_service_set_string(service, "AnonymousIdentity", str);
 +
 +              } else if (g_str_equal(key, "CACertFile")) {
 +                      if (type != DBUS_TYPE_STRING)
 +                              return -EINVAL;
 +
 +                      dbus_message_iter_get_basic(&value, &str);
 +                      __connman_service_set_string(service, "CACertFile", str);
 +              } else if (g_str_equal(key, "ClientCertFile")) {
 +                      if (type != DBUS_TYPE_STRING)
 +                              return -EINVAL;
 +
 +                      dbus_message_iter_get_basic(&value, &str);
 +                      __connman_service_set_string(service, "ClientCertFile", str);
 +              } else if (g_str_equal(key, "PrivateKeyFile")) {
 +                      if (type != DBUS_TYPE_STRING)
 +                              return -EINVAL;
 +
 +                      dbus_message_iter_get_basic(&value, &str);
 +                      __connman_service_set_string(service, "PrivateKeyFile", str);
 +              } else if (g_str_equal(key, "PrivateKeyPassphrase")) {
 +                      if (type != DBUS_TYPE_STRING)
 +                              return -EINVAL;
 +
 +                      dbus_message_iter_get_basic(&value, &str);
 +                      __connman_service_set_string(service, "PrivateKeyPassphrase", str);
 +              } else if (g_str_equal(key, "Phase2")) {
 +                      if (type != DBUS_TYPE_STRING)
 +                              return -EINVAL;
 +
 +                      dbus_message_iter_get_basic(&value, &str);
 +                      __connman_service_set_string(service, "Phase2", str);
 +              } else if (g_str_equal(key, "Phase1")) {
 +                      int val;
 +                      char phase1[5] = {0,};
 +
 +                      if (type != DBUS_TYPE_INT32)
 +                              return -EINVAL;
 +
 +                      dbus_message_iter_get_basic(&value, &val);
 +                      sprintf(phase1, "%d", val);
 +                      __connman_service_set_string(service, "Phase1", phase1);
 +              } else if (g_str_equal(key, "PacFile")) {
 +                      if (type != DBUS_TYPE_STRING)
 +                              return -EINVAL;
 +
 +                      dbus_message_iter_get_basic(&value, &str);
 +                      __connman_service_set_string(service, "PacFile", str);
 +              }
 +
 +              dbus_message_iter_next(&dict);
 +      }
 +
 +      return 0;
 +}
 +#endif
 +
 +#if defined TIZEN_EXT
 +static void save_assoc_reject(gpointer key, gpointer value, gpointer user_data)
 +{
 +      struct assoc_reject_data *assoc_rd = value;
 +      GString *assoc_reject_str = user_data;
 +      GSList *list;
 +      char *val_str;
 +
 +      if (g_slist_length(assoc_rd->reject_time_list) < 1)
 +              return;
 +
 +      for (list = assoc_rd->reject_time_list; list; list = list->next) {
 +              time_t assoc_reject_time = GPOINTER_TO_INT(list->data);
 +
 +              val_str = g_strdup_printf("%s_%ld", assoc_rd->bssid, assoc_reject_time);
 +
 +              if (assoc_reject_str->len > 0)
 +                      g_string_append_printf(assoc_reject_str, " %s", val_str);
 +              else
 +                      g_string_append(assoc_reject_str, val_str);
 +
 +              g_free(val_str);
 +      }
 +}
 +
 +static void count_assoc_reject(gpointer key, gpointer value, gpointer user_data)
 +{
 +      struct assoc_reject_data *assoc_data = value;
 +      int *assoc_reject_count = user_data;
 +
 +      if (assoc_data)
 +              *assoc_reject_count += g_slist_length(assoc_data->reject_time_list);
 +}
 +
 +static bool update_assoc_reject(struct connman_service *service)
 +{
 +      GHashTable *assoc_reject_table;
 +      int assoc_reject_count;
 +
 +      if (!service->network)
 +              return false;
 +
 +      assoc_reject_table = connman_network_get_assoc_reject_table(service->network);
 +      if (assoc_reject_table) {
 +              assoc_reject_count = 0;
 +              g_hash_table_foreach(assoc_reject_table, count_assoc_reject, &assoc_reject_count);
 +#if defined TIZEN_EXT_INS
 +              DBG("assoc reject count [%d -> %d]",
 +                      service->assoc_reject_count, assoc_reject_count);
 +#endif
 +              if (service->assoc_reject_count != assoc_reject_count) {
 +                      service->assoc_reject_count = assoc_reject_count;
 +                      return true;
 +              }
 +      }
 +
 +      return false;
 +}
 +
 +static int service_ext_load(struct connman_service *service)
 +{
 +      GKeyFile *keyfile;
 +      GHashTable *reject_table;
 +      char **reject_list;
 +      gsize reject_len;
 +      struct assoc_reject_data *reject_data;
 +      char **bssid_time;
 +      char *bssid;
 +      time_t reject_time;
 +      time_t curr_time;
 +      time_t ref_time;
 +      struct tm* ref_timeinfo;
 +      int i;
 +      int err = 0;
 +
 +      if (!simplified_log)
 +              DBG("service %p", service);
 +
 +      if (!service->network)
 +              return -EINVAL;
 +
 +      if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
 +              return -EINVAL;
 +
 +      keyfile = connman_storage_load_service(service->identifier);
 +      if (!keyfile)
 +              return -EIO;
 +
 +      reject_table = connman_network_get_assoc_reject_table(service->network);
 +
 +      reject_list = g_key_file_get_string_list(keyfile,
 +              service->identifier, "AssocReject", &reject_len, NULL);
 +
 +      if (!reject_list || reject_len == 0) {
 +              g_strfreev(reject_list);
 +              goto done;
 +      }
 +
 +      /* Only events that occur within one hour are appened. */
 +      curr_time = time(NULL);
 +      ref_timeinfo = localtime(&curr_time);
 +      ref_timeinfo->tm_hour -= 1;
 +      ref_time = mktime(ref_timeinfo);
 +
 +      for (i = 0; reject_list[i]; i++) {
 +              bssid_time = g_strsplit(reject_list[i], "_", 0);
 +              if (!bssid_time) {
 +                      err = -ERANGE;
 +                      continue;
 +              }
 +
 +              bssid = bssid_time[0];
 +              reject_time = strtol(bssid_time[1], NULL, 10);
 +
 +              if (reject_time < ref_time) {
 +                      g_strfreev(bssid_time);
 +                      err = -ERANGE;
 +                      continue;
 +              }
 +
 +              reject_data = g_hash_table_lookup(reject_table, bssid);
 +              if (!reject_data) {
 +                      reject_data = g_try_new0(struct assoc_reject_data, 1);
 +                      if (!reject_data) {
 +                              g_strfreev(bssid_time);
 +                              err = -ERANGE;
 +                              continue;
 +                      }
 +
 +                      reject_data->bssid = g_strdup(bssid);
 +                      g_hash_table_insert(reject_table, reject_data->bssid, reject_data);
 +              }
 +
 +              reject_data->reject_time_list = g_slist_append(reject_data->reject_time_list,
 +                              GINT_TO_POINTER(reject_time));
 +
 +#if defined TIZEN_EXT_INS
 +              DBG("assoc reject [%s_%ld]", bssid, reject_time);
 +#endif
 +
 +              g_strfreev(bssid_time);
 +      }
 +
 +      g_strfreev(reject_list);
 +
 +done:
 +      g_key_file_free(keyfile);
 +      return err;
 +}
 +
 +static int service_ext_save(struct connman_service *service)
 +{
 +      GKeyFile *keyfile;
 +      GHashTable *reject_table;
 +      GString *reject_str;
 +      char **reject_list;
 +      guint reject_len;
 +      int err = 0;
 +
 +      DBG("service %p", service);
 +
 +      if (!service->network)
 +              return -EINVAL;
 +
 +      if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
 +              return -EINVAL;
 +
 +      keyfile = g_key_file_new();
 +      if (!keyfile)
 +              return -EIO;
 +
 +      /* Last connected BSSID */
 +      if (memcmp(service->last_connected_bssid, invalid_bssid, WIFI_BSSID_LEN_MAX)) {
 +              char *identifier = service->identifier;
 +              GString *bssid_str;
 +              unsigned int i;
 +
 +              bssid_str = g_string_sized_new(MAC_ADDRESS_LENGTH);
 +              if (!bssid_str) {
 +                      err = -ENOMEM;
 +                      goto next;
 +              }
 +
 +              for (i = 0; i < WIFI_BSSID_LEN_MAX; i++) {
 +                      g_string_append_printf(bssid_str,
 +                                      "%02x", service->last_connected_bssid[i]);
 +                      if (i < WIFI_BSSID_LEN_MAX - 1)
 +                              g_string_append(bssid_str, ":");
 +              }
 +
 +              g_key_file_set_string(keyfile, identifier,
 +                                      "LastConnectedBSSID", bssid_str->str);
 +
 +#if defined TIZEN_EXT_INS
 +              DBG("last connected bssid[%s]", bssid_str->str);
 +#endif
 +
 +              g_string_free(bssid_str, TRUE);
 +      }
 +
 +next:
 +
 +      /* Assoc reject */
 +      reject_table = connman_network_get_assoc_reject_table(service->network);
 +      if (reject_table && g_hash_table_size(reject_table) > 0) {
 +              reject_str = g_string_new(NULL);
 +              if (!reject_str) {
 +                      err = -ENOMEM;
 +                      goto done;
 +              }
 +
 +              g_hash_table_foreach(reject_table, save_assoc_reject, reject_str);
 +
 +              reject_list = g_strsplit_set(reject_str->str, " ", 0);
 +              reject_len = g_strv_length(reject_list);
 +
 +              g_key_file_set_string_list(keyfile, service->identifier,
 +                      "AssocReject", (const gchar **)reject_list, reject_len);
 +
 +#if defined TIZEN_EXT_INS
 +              DBG("assoc reject table [%d]", reject_len);
 +#endif
 +
 +              g_strfreev(reject_list);
 +              g_string_free(reject_str, TRUE);
 +      } else {
 +              g_key_file_remove_key(keyfile, service->identifier, "AssocReject", NULL);
 +      }
 +
 +done:
 +      __connman_storage_save_service(keyfile, service->identifier);
 +
 +      g_key_file_free(keyfile);
 +      return err;
 +}
 +#endif
 +
  static int service_load(struct connman_service *service)
  {
        GKeyFile *keyfile;
        bool autoconnect;
        unsigned int ssid_len;
        int err = 0;
 -
 +#if defined TIZEN_EXT
 +      bool internet_connection;
 +#endif
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      bool use_eapol;
 +#endif
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        DBG("service %p", service);
  
        keyfile = connman_storage_load_service(service->identifier);
        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);
  
                        g_free(hex_ssid);
                }
 +
 +#if defined TIZEN_EXT
 +              /* Last connected BSSID */
 +              if (service->network) {
 +                      gchar *bssid_str;
 +                      unsigned char last_connected_bssid[WIFI_BSSID_LEN_MAX];
 +                      char **str_list;
 +                      unsigned int i;
 +
 +                      bssid_str = g_key_file_get_string(keyfile,
 +                              service->identifier, "LastConnectedBSSID", NULL);
 +
 +                      if (bssid_str) {
 +                              str_list = g_strsplit(bssid_str, ":", 0);
 +
 +                              if (str_list) {
 +                                      for (i = 0; i < WIFI_BSSID_LEN_MAX; i++)
 +                                              last_connected_bssid[i] = strtol(str_list[i], NULL, 16);
 +
 +                                      memcpy(service->last_connected_bssid,
 +                                              last_connected_bssid, WIFI_BSSID_LEN_MAX);
 +
 +                                      connman_network_set_last_connected_bssid(service->network,
 +                                              last_connected_bssid);
 +
 +                                      g_strfreev(str_list);
 +                              }
 +
 +                              g_free(bssid_str);
 +                      }
 +              }
 +
 +              /* Internet connection */
 +              internet_connection = g_key_file_get_boolean(keyfile,
 +                              service->identifier, "InternetConnection", &error);
 +              if (!error)
 +                      service->is_internet_connection = internet_connection;
 +
 +              g_clear_error(&error);
 +#endif
                /* fall through */
  
        case CONNMAN_SERVICE_TYPE_GADGET:
                if (!error)
                        service->autoconnect = autoconnect;
                g_clear_error(&error);
 +
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +              use_eapol = g_key_file_get_boolean(keyfile,
 +                              service->identifier, "UseEapol", &error);
 +              if (!error)
 +                      service->use_eapol = use_eapol;
 +              g_clear_error(&error);
 +#endif
                break;
        }
  
        str = g_key_file_get_string(keyfile,
                                service->identifier, "Passphrase", NULL);
        if (str) {
+               char *dec = g_strcompress(str);
+               g_free(str);
                g_free(service->passphrase);
-               service->passphrase = str;
+               service->passphrase = dec;
        }
  
        if (service->ipconfig_ipv4)
                service->nameservers_config = NULL;
        }
  
 +#ifdef TIZEN_EXT
 +      char *dns_method;
 +
 +      dns_method = g_key_file_get_string(keyfile, service->identifier,
 +                      "Nameservers.IPv4method", NULL);
 +      if (dns_method) {
 +              service->dns_config_method_ipv4 = __connman_dnsconfig_string2method(dns_method);
 +              g_free(dns_method);
 +      }
 +
 +      dns_method = g_key_file_get_string(keyfile, service->identifier,
 +                      "Nameservers.IPv6method", NULL);
 +      if (dns_method) {
 +              service->dns_config_method_ipv6 = __connman_dnsconfig_string2method(dns_method);
 +              g_free(dns_method);
 +      }
 +#endif
 +
        service->timeservers_config = g_key_file_get_string_list(keyfile,
                        service->identifier, "Timeservers", &length, NULL);
        if (service->timeservers_config && length == 0) {
        service->hidden_service = g_key_file_get_boolean(keyfile,
                                        service->identifier, "Hidden", NULL);
  
 +#if defined TIZEN_EXT
 +      if ((service->type == CONNMAN_SERVICE_TYPE_WIFI &&
 +                      service->security == CONNMAN_SERVICE_SECURITY_8021X)
 +#if defined TIZEN_EXT_EAP_ON_ETHERNET
 +      || (service->type == CONNMAN_SERVICE_TYPE_ETHERNET && service->use_eapol)
 +#endif
 +      ) {
 +              str = g_key_file_get_string(keyfile,
 +                              service->identifier, "EAP", NULL);
 +              if (str != NULL) {
 +                      g_free(service->eap);
 +                      service->eap = str;
 +              }
 +
 +              str = g_key_file_get_string(keyfile,
 +                              service->identifier, "Phase2", NULL);
 +              if (str != NULL) {
 +                      g_free(service->phase2);
 +                      service->phase2 = str;
 +              }
 +
 +              str = g_key_file_get_string(keyfile,
 +                              service->identifier, "Identity", NULL);
 +              if (str != NULL) {
 +                      g_free(service->identity);
 +                      service->identity = str;
 +              }
 +
 +#if defined TIZEN_EXT_EAP_ON_ETHERNET
 +              str = g_key_file_get_string(keyfile,
 +                              service->identifier, "AnonymousIdentity", NULL);
 +              if (str != NULL) {
 +                      g_free(service->anonymous_identity);
 +                      service->anonymous_identity = str;
 +              }
 +#endif
 +              str = g_key_file_get_string(keyfile,
 +                              service->identifier, "CACertFile", NULL);
 +              if (str != NULL) {
 +                      g_free(service->ca_cert_file);
 +                      service->ca_cert_file = str;
 +              }
 +
 +              str = g_key_file_get_string(keyfile,
 +                              service->identifier, "ClientCertFile", NULL);
 +              if (str != NULL) {
 +                      g_free(service->client_cert_file);
 +                      service->client_cert_file = str;
 +              }
 +
 +              str = g_key_file_get_string(keyfile,
 +                              service->identifier, "PrivateKeyFile", NULL);
 +              if (str != NULL) {
 +                      g_free(service->private_key_file);
 +                      service->private_key_file = str;
 +              }
 +
 +              str = g_key_file_get_string(keyfile,
 +                              service->identifier, "PrivateKeyPassphrase", NULL);
 +              if (str != NULL) {
 +                      g_free(service->private_key_passphrase);
 +                      service->private_key_passphrase = str;
 +              }
 +
 +#if defined TIZEN_EXT_EAP_ON_ETHERNET
 +              str = g_key_file_get_string(keyfile,
 +                              service->identifier, "Phase1", NULL);
 +              if (str != NULL) {
 +                      g_free(service->phase1);
 +                      service->phase1 = str;
 +              }
 +
 +              str = g_key_file_get_string(keyfile,
 +                              service->identifier, "PacFile", NULL);
 +              if (str != NULL) {
 +                      g_free(service->pac_file);
 +                      service->pac_file = str;
 +              }
 +#endif
 +      }
 +#endif
 +#if defined TIZEN_EXT
 +      if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
 +                      service->security == CONNMAN_SERVICE_SECURITY_DPP) {
 +              str = g_key_file_get_string(keyfile,
 +                              service->identifier, "Connector", NULL);
 +              if (str != NULL) {
 +                      g_free(service->connector);
 +                      service->connector = str;
 +              }
 +              str = g_key_file_get_string(keyfile,
 +                              service->identifier, "CSignKey", NULL);
 +              if (str != NULL) {
 +                      g_free(service->c_sign_key);
 +                      service->c_sign_key = str;
 +              }
 +              str = g_key_file_get_string(keyfile,
 +                              service->identifier, "NetAccessKey", NULL);
 +              if (str != NULL) {
 +                      g_free(service->net_access_key);
 +                      service->net_access_key = str;
 +              }
 +      }
 +#endif
 +
  done:
        g_key_file_free(keyfile);
  
@@@ -1422,9 -678,6 +1456,9 @@@ static int service_save(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:
                g_key_file_set_boolean(keyfile, service->identifier,
                if (service->network) {
                        const unsigned char *ssid;
                        unsigned int ssid_len = 0;
 +#if defined TIZEN_EXT
 +                      GHashTable *assoc_reject_table;
 +#endif
  
                        ssid = connman_network_get_blob(service->network,
                                                        "WiFi.SSID", &ssid_len);
                        freq = connman_network_get_frequency(service->network);
                        g_key_file_set_integer(keyfile, service->identifier,
                                                "Frequency", freq);
 +
 +#if defined TIZEN_EXT
 +                      /* Last connected BSSID */
 +                      if (memcmp(service->last_connected_bssid, invalid_bssid, WIFI_BSSID_LEN_MAX)) {
 +                              char *identifier = service->identifier;
 +                              GString *bssid_str;
 +                              unsigned int i;
 +
 +                              bssid_str = g_string_sized_new(18);
 +                              if (!bssid_str) {
 +                                      err = -ENOMEM;
 +                                      goto done;
 +                              }
 +
 +                              for (i = 0; i < WIFI_BSSID_LEN_MAX; i++) {
 +                                      g_string_append_printf(bssid_str,
 +                                                      "%02x", service->last_connected_bssid[i]);
 +                                      if (i < WIFI_BSSID_LEN_MAX - 1)
 +                                              g_string_append(bssid_str, ":");
 +                              }
 +
 +                              g_key_file_set_string(keyfile, identifier,
 +                                                      "LastConnectedBSSID", bssid_str->str);
 +
 +#if defined TIZEN_EXT_INS
 +                              DBG("last connected bssid[%s]", bssid_str->str);
 +#endif
 +
 +                              g_string_free(bssid_str, TRUE);
 +                      }
 +
 +                      /* Assoc reject */
 +                      assoc_reject_table = connman_network_get_assoc_reject_table(service->network);
 +                      if (assoc_reject_table && g_hash_table_size(assoc_reject_table) > 0) {
 +                              GString *assoc_reject_str;
 +                              char **assoc_reject_list;
 +                              guint assoc_reject_len;
 +
 +                              assoc_reject_str = g_string_new(NULL);
 +                              if (!assoc_reject_str) {
 +                                      err = -ENOMEM;
 +                                      goto done;
 +                              }
 +
 +                              g_hash_table_foreach(assoc_reject_table, save_assoc_reject, assoc_reject_str);
 +
 +                              assoc_reject_list = g_strsplit_set(assoc_reject_str->str, " ", 0);
 +                              assoc_reject_len = g_strv_length(assoc_reject_list);
 +
 +                              g_key_file_set_string_list(keyfile, service->identifier,
 +                                      "AssocReject", (const gchar **)assoc_reject_list, assoc_reject_len);
 +
 +#if defined TIZEN_EXT_INS
 +                              DBG("assoc reject table [%d]", assoc_reject_len);
 +#endif
 +
 +                              g_strfreev(assoc_reject_list);
 +                              g_string_free(assoc_reject_str, TRUE);
 +                      } else
 +                              g_key_file_remove_key(keyfile, service->identifier, "AssocReject", NULL);
 +
 +                      /* Internet connection */
 +                      g_key_file_set_boolean(keyfile, service->identifier,
 +                                      "InternetConnection", service->is_internet_connection);
 +#if defined TIZEN_EXT_INS
 +                      DBG("internet connection [%s]", service->is_internet_connection ? "true" : "false");
 +#endif
 +#endif
                }
                /* fall through */
  
                if (service->favorite)
                        g_key_file_set_boolean(keyfile, service->identifier,
                                        "AutoConnect", service->autoconnect);
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +              g_key_file_set_boolean(keyfile, service->identifier,
 +                              "UseEapol", service->use_eapol);
 +#endif
                break;
        }
  
                g_free(str);
        }
  
-       if (service->passphrase && strlen(service->passphrase) > 0)
+       if (service->passphrase && strlen(service->passphrase) > 0) {
+               char *enc = g_strescape(service->passphrase, NULL);
                g_key_file_set_string(keyfile, service->identifier,
-                               "Passphrase", service->passphrase);
+                               "Passphrase", enc);
+               g_free(enc);
+       }
  
        if (service->ipconfig_ipv4)
                __connman_ipconfig_save(service->ipconfig_ipv4, keyfile,
                                (const gchar **) service->nameservers_config, len);
        }
  
 +#if defined TIZEN_EXT
 +      if(service->dns_config_method_ipv4 != 0) {
 +              const char *method;
 +              method = __connman_dnsconfig_method2string(
 +                              service->dns_config_method_ipv4);
 +              g_key_file_set_string(keyfile, service->identifier,
 +                              "Nameservers.IPv4method", method);
 +      } else
 +      g_key_file_remove_key(keyfile, service->identifier,
 +                                              "Nameservers.IPv4method", NULL);
 +
 +      if(service->dns_config_method_ipv6 != 0) {
 +              const char *method;
 +              method = __connman_dnsconfig_method2string(
 +                              service->dns_config_method_ipv6);
 +              g_key_file_set_string(keyfile, service->identifier,
 +                              "Nameservers.IPv6method", method);
 +      } else
 +      g_key_file_remove_key(keyfile, service->identifier,
 +                                                      "Nameservers.IPv6method", NULL);
 +#endif
 +
        if (service->timeservers_config) {
                guint len = g_strv_length(service->timeservers_config);
  
                                "mDNS", TRUE);
  
        if (service->hidden_service)
-               g_key_file_set_boolean(keyfile, service->identifier, "Hidden",
-                                                                       TRUE);
+               g_key_file_set_boolean(keyfile, service->identifier,
+                               "Hidden", TRUE);
  
        if (service->config_file && strlen(service->config_file) > 0)
                g_key_file_set_string(keyfile, service->identifier,
                                "Config.file", service->config_file);
  
-       if (service->config_entry &&
-                                       strlen(service->config_entry) > 0)
+       if (service->config_entry && strlen(service->config_entry) > 0)
                g_key_file_set_string(keyfile, service->identifier,
                                "Config.ident", service->config_entry);
  
 +#if defined TIZEN_EXT
 +      if ((service->type == CONNMAN_SERVICE_TYPE_WIFI &&
 +                      service->security == CONNMAN_SERVICE_SECURITY_8021X)
 +#if defined TIZEN_EXT_EAP_ON_ETHERNET
 +      || (service->type == CONNMAN_SERVICE_TYPE_ETHERNET)
 +#endif
 +      ) {
 +              if (service->eap != NULL && strlen(service->eap) > 0)
 +                      g_key_file_set_string(keyfile, service->identifier,
 +                                      "EAP", service->eap);
 +              else
 +                      g_key_file_remove_key(keyfile, service->identifier,
 +                                      "EAP", NULL);
 +
 +              if (service->phase2 != NULL && strlen(service->phase2) > 0)
 +                      g_key_file_set_string(keyfile, service->identifier,
 +                                      "Phase2", service->phase2);
 +              else
 +                      g_key_file_remove_key(keyfile, service->identifier,
 +                                      "Phase2", NULL);
 +
 +              if (service->identity != NULL && strlen(service->identity) > 0)
 +                      g_key_file_set_string(keyfile, service->identifier,
 +                                      "Identity", service->identity);
 +              else
 +                      g_key_file_remove_key(keyfile, service->identifier,
 +                                      "Identity", NULL);
 +#if defined TIZEN_EXT_EAP_ON_ETHERNET
 +              if (service->anonymous_identity != NULL && strlen(service->anonymous_identity) > 0)
 +                      g_key_file_set_string(keyfile, service->identifier,
 +                                      "AnonymousIdentity", service->anonymous_identity);
 +              else
 +                      g_key_file_remove_key(keyfile, service->identifier,
 +                                      "AnonymousIdentity", NULL);
 +#endif
 +
 +              if (service->ca_cert_file != NULL && strlen(service->ca_cert_file) > 0)
 +                      g_key_file_set_string(keyfile, service->identifier,
 +                                      "CACertFile", service->ca_cert_file);
 +              else
 +                      g_key_file_remove_key(keyfile, service->identifier,
 +                                      "CACertFile", NULL);
 +
 +              if (service->client_cert_file != NULL && strlen(service->client_cert_file) > 0)
 +                      g_key_file_set_string(keyfile, service->identifier,
 +                                      "ClientCertFile", service->client_cert_file);
 +              else
 +                      g_key_file_remove_key(keyfile, service->identifier,
 +                                      "ClientCertFile", NULL);
 +
 +              if (service->private_key_file != NULL && strlen(service->private_key_file) > 0)
 +                      g_key_file_set_string(keyfile, service->identifier,
 +                                      "PrivateKeyFile", service->private_key_file);
 +              else
 +                      g_key_file_remove_key(keyfile, service->identifier,
 +                                      "PrivateKeyFile", NULL);
 +
 +              if (service->private_key_passphrase != NULL && strlen(service->private_key_passphrase) > 0)
 +                      g_key_file_set_string(keyfile, service->identifier,
 +                                      "PrivateKeyPassphrase", service->private_key_passphrase);
 +              else
 +                      g_key_file_remove_key(keyfile, service->identifier,
 +                                      "PrivateKeyPassphrase", NULL);
 +#if defined TIZEN_EXT_EAP_ON_ETHERNET
 +              if (service->phase1 != NULL && strlen(service->phase1) > 0)
 +                      g_key_file_set_string(keyfile, service->identifier,
 +                                      "Phase1", service->phase1);
 +              else
 +                      g_key_file_remove_key(keyfile, service->identifier,
 +                                      "Phase1", NULL);
 +              if (service->pac_file != NULL && strlen(service->pac_file) > 0)
 +                      g_key_file_set_string(keyfile, service->identifier,
 +                                      "PacFile", service->pac_file);
 +              else
 +                      g_key_file_remove_key(keyfile, service->identifier,
 +                                      "PacFile", NULL);
 +#endif
 +      }
 +
 +      if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
 +                      service->security == CONNMAN_SERVICE_SECURITY_DPP) {
 +              if (service->connector != NULL && strlen(service->connector) > 0)
 +                      g_key_file_set_string(keyfile, service->identifier,
 +                                      "Connector", service->connector);
 +              else
 +                      g_key_file_remove_key(keyfile, service->identifier,
 +                                      "Connector", NULL);
 +
 +              if (service->c_sign_key != NULL && strlen(service->c_sign_key) > 0)
 +                      g_key_file_set_string(keyfile, service->identifier,
 +                                      "CSignKey", service->c_sign_key);
 +              else
 +                      g_key_file_remove_key(keyfile, service->identifier,
 +                                      "CSignKey", NULL);
 +
 +              if (service->net_access_key != NULL && strlen(service->net_access_key) > 0)
 +                      g_key_file_set_string(keyfile, service->identifier,
 +                                      "NetAccessKey", service->net_access_key);
 +              else
 +                      g_key_file_remove_key(keyfile, service->identifier,
 +                                      "NetAccessKey", NULL);
 +      }
 +#endif
 +
  done:
        __connman_storage_save_service(keyfile, service->identifier);
  
        return err;
  }
  
 +#if defined TIZEN_EXT
 +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 ascending */
 +      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 saved_profiles *entry = data;
 +      g_free(entry->profile_name);
 +      g_free(entry);
 +}
 +
 +static void __connman_manage_saved_profiles()
 +{
 +      GKeyFile *keyfile;
 +      gchar **services = NULL;
 +      GTimeVal modified;
 +      int i, num_profiles = 0;
 +      GSequenceIter *iter;
 +      GSequence *profile_list;
 +      struct saved_profiles *entry;
 +
 +      profile_list = g_sequence_new(free_entry);
 +      if (!profile_list)
 +              return;
 +
 +      services = connman_storage_get_services();
 +
 +      /* Check the count of saved profiles */
 +      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;
 +
 +              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);
 +
 +              entry = g_try_new(struct saved_profiles, 1);
 +              if (!entry) {
 +                      g_sequence_free(profile_list);
 +                      g_key_file_free(keyfile);
 +                      g_strfreev(services);
 +                      return;
 +              }
 +
 +              entry->modified = modified;
 +              entry->profile_name = g_strdup(services[i]);
 +
 +              g_sequence_insert_sorted(profile_list, entry,
 +                              sort_entry, NULL);
 +
 +              num_profiles++;
 +      }
 +      DBG("number of profiles: %d", num_profiles);
 +
 +      if (num_profiles > MAX_WIFI_PROFILES) {
 +              iter = g_sequence_get_begin_iter(profile_list);
 +
 +              entry = g_sequence_get(iter);
 +
 +              if (__connman_storage_remove_service(entry->profile_name) == false)
 +                      DBG("Failed to remove service profile: %s", entry->profile_name);
 +      }
 +
 +      g_sequence_free(profile_list);
 +      g_strfreev(services);
 +}
 +#endif
 +
  void __connman_service_save(struct connman_service *service)
  {
        if (!service)
                return;
  
        service_save(service);
 +#if defined TIZEN_EXT
 +      /*
 +       * Description: Manage the wireless profiles saved in connman.
 +       * If the number of saved profiles is more than 200, remove the
 +       * profile that is not updated for longer duration.
 +       */
 +      __connman_manage_saved_profiles();
 +#endif
  }
  
  static enum connman_service_state combine_state(
@@@ -2133,9 -1089,6 +2169,9 @@@ static int nameserver_add(struct connma
        if (index < 0)
                return -ENXIO;
  
 +#if defined TIZEN_EXT
 +      DBG("Resolver append nameserver: %s", nameserver);
 +#endif
        ret = connman_resolver_append(index, NULL, nameserver);
        if (ret >= 0)
                nameservers_changed(service);
@@@ -2150,115 -1103,14 +2186,115 @@@ static int nameserver_add_all(struct co
  
        if (service->nameservers_config) {
                while (service->nameservers_config[i]) {
 +#if defined TIZEN_EXT
 +                      DBG("type %d add service->nameservers_config[%d]:%s",type,
 +                          i, service->nameservers_config[i]);
 +                      if(strncmp(service->nameservers_config[i], "::", 2) == 0) {
 +                              DBG("Invalid nameserver");
 +                              i++;
 +                              continue;
 +                      }
 +
 +                      switch(type) {
 +                      case CONNMAN_IPCONFIG_TYPE_IPV4:
 +                              if (connman_inet_check_ipaddress(
 +                                      service->nameservers_config[i]) == AF_INET &&
 +                                  service->dns_config_method_ipv4 ==
 +                                  CONNMAN_DNSCONFIG_METHOD_MANUAL) {
 +                                      nameserver_add(service, type,
 +                                                     service->nameservers_config[i]);
 +                              }
 +                              break;
 +                      case CONNMAN_IPCONFIG_TYPE_IPV6:
 +                              if (connman_inet_check_ipaddress(
 +                                      service->nameservers_config[i]) == AF_INET6 &&
 +                                  service->dns_config_method_ipv6 ==
 +                                      CONNMAN_DNSCONFIG_METHOD_MANUAL) {
 +                                      nameserver_add(service, type,
 +                                                     service->nameservers_config[i]);
 +                              }
 +                              break;
 +                      case CONNMAN_IPCONFIG_TYPE_ALL:
 +                              if (connman_inet_check_ipaddress(
 +                                      service->nameservers_config[i]) == AF_INET &&
 +                                  service->dns_config_method_ipv4 ==
 +                                      CONNMAN_DNSCONFIG_METHOD_MANUAL) {
 +                                      nameserver_add(service, type,
 +                                                     service->nameservers_config[i]);
 +                              }
 +                              if (connman_inet_check_ipaddress(
 +                                      service->nameservers_config[i]) == AF_INET6 &&
 +                                  service->dns_config_method_ipv6 ==
 +                                      CONNMAN_DNSCONFIG_METHOD_MANUAL) {
 +                                      nameserver_add(service, type,
 +                                                     service->nameservers_config[i]);
 +                              }
 +                              break;
 +                      case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
 +                              DBG("CONNMAN_IPCONFIG_TYPE_UNKNOWN do nothing");
 +                              break;
 +                      default:
 +                              DBG("default case do nothing");
 +                              break;
 +                      }
 +#else
                        nameserver_add(service, type,
                                service->nameservers_config[i]);
 +#endif
                        i++;
                }
        } else if (service->nameservers) {
                while (service->nameservers[i]) {
 +#if defined TIZEN_EXT
 +                      DBG("type %d service->nameservers[%d]: %s",type,
 +                          i, service->nameservers[i]);
 +
 +                      switch(type) {
 +                      case CONNMAN_IPCONFIG_TYPE_IPV4:
 +                              if (connman_inet_check_ipaddress(
 +                                      service->nameservers[i]) == AF_INET &&
 +                                      service->dns_config_method_ipv4 ==
 +                                              CONNMAN_DNSCONFIG_METHOD_DHCP) {
 +                                      nameserver_add(service, type,
 +                                                     service->nameservers[i]);
 +                              }
 +                              break;
 +                      case CONNMAN_IPCONFIG_TYPE_IPV6:
 +                              if (connman_inet_check_ipaddress(
 +                                      service->nameservers[i]) == AF_INET6 &&
 +                                      service->dns_config_method_ipv6 ==
 +                                              CONNMAN_DNSCONFIG_METHOD_DHCP) {
 +                                      nameserver_add(service, type,
 +                                                     service->nameservers[i]);
 +                              }
 +                              break;
 +                      case CONNMAN_IPCONFIG_TYPE_ALL:
 +                              if (connman_inet_check_ipaddress(
 +                                      service->nameservers[i]) == AF_INET &&
 +                                      service->dns_config_method_ipv4 ==
 +                                              CONNMAN_DNSCONFIG_METHOD_DHCP) {
 +                                      nameserver_add(service, type,
 +                                                     service->nameservers[i]);
 +                              }
 +                              if (connman_inet_check_ipaddress(
 +                                      service->nameservers[i]) == AF_INET6 &&
 +                                      service->dns_config_method_ipv6 ==
 +                                              CONNMAN_DNSCONFIG_METHOD_DHCP) {
 +                                      nameserver_add(service, type,
 +                                                     service->nameservers[i]);
 +                              }
 +                              break;
 +                      case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
 +                              DBG("CONNMAN_IPCONFIG_TYPE_UNKNOWN do nothing");
 +                              break;
 +                      default:
 +                              DBG("default case do nothing");
 +                              break;
 +                      }
 +#else
                        nameserver_add(service, type,
                                service->nameservers[i]);
 +#endif
                        i++;
                }
        }
        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;
@@@ -2290,9 -1136,6 +2326,9 @@@ static int nameserver_remove(struct con
        if (index < 0)
                return -ENXIO;
  
 +#if defined TIZEN_EXT
 +      DBG("Resolver remove nameserver: %s", nameserver);
 +#endif
        ret = connman_resolver_remove(index, NULL, nameserver);
        if (ret >= 0)
                nameservers_changed(service);
  static int nameserver_remove_all(struct connman_service *service,
                                enum connman_ipconfig_type type)
  {
 +#if defined TIZEN_EXT
 +      /**
 +        * Skip this function if there is any connected profiles
 +        * that use same interface
 +        */
 +      if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
 +                      __connman_service_get_connected_count_of_iface(service) > 0)
 +              return 0;
 +#endif
        int index, i = 0;
  
        index = __connman_service_get_index(service);
  
        while (service->nameservers_config && service->nameservers_config[i]) {
  
 +#if defined TIZEN_EXT
 +              DBG("type %d Remove service->nameservers_config[%d]: %s",
 +                    type, i, service->nameservers_config[i]);
 +              switch(type) {
 +              case CONNMAN_IPCONFIG_TYPE_IPV4:
 +                      if (connman_inet_check_ipaddress(
 +                              service->nameservers_config[i]) == AF_INET &&
 +                              (service->dns_config_method_ipv4 ==
 +                                      CONNMAN_DNSCONFIG_METHOD_DHCP ||
 +                              service->dns_config_method_ipv4 ==
 +                                      CONNMAN_DNSCONFIG_METHOD_MANUAL)) {
 +                              nameserver_remove(service, type,
 +                                                service->nameservers_config[i]);
 +                      }
 +                      break;
 +              case CONNMAN_IPCONFIG_TYPE_IPV6:
 +                      if (connman_inet_check_ipaddress(
 +                              service->nameservers_config[i]) == AF_INET6 &&
 +                              (service->dns_config_method_ipv6 ==
 +                                      CONNMAN_DNSCONFIG_METHOD_DHCP ||
 +                              service->dns_config_method_ipv6 ==
 +                                      CONNMAN_DNSCONFIG_METHOD_MANUAL)) {
 +                              nameserver_remove(service, type,
 +                                                service->nameservers_config[i]);
 +                      }
 +                      break;
 +              case CONNMAN_IPCONFIG_TYPE_ALL:
 +                      if (connman_inet_check_ipaddress(
 +                              service->nameservers_config[i]) == AF_INET &&
 +                              (service->dns_config_method_ipv4 ==
 +                                      CONNMAN_DNSCONFIG_METHOD_DHCP ||
 +                              service->dns_config_method_ipv4 ==
 +                                      CONNMAN_DNSCONFIG_METHOD_MANUAL)) {
 +                              nameserver_remove(service, type,
 +                                                service->nameservers_config[i]);
 +                      }
 +                      if (connman_inet_check_ipaddress(
 +                              service->nameservers_config[i]) == AF_INET6 &&
 +                              (service->dns_config_method_ipv6 ==
 +                                      CONNMAN_DNSCONFIG_METHOD_DHCP ||
 +                              service->dns_config_method_ipv6 ==
 +                                      CONNMAN_DNSCONFIG_METHOD_MANUAL)) {
 +                              nameserver_remove(service, type,
 +                                                service->nameservers_config[i]);
 +                      }
 +                      break;
 +              case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
 +                      DBG("CONNMAN_IPCONFIG_TYPE_UNKNOWN do nothing");
 +                      break;
 +              default:
 +                      DBG("default case do nothing");
 +                      break;
 +              }
 +#else
                nameserver_remove(service, type,
                                service->nameservers_config[i]);
 +#endif
                i++;
        }
  
        i = 0;
        while (service->nameservers && service->nameservers[i]) {
 +#if defined TIZEN_EXT
 +              DBG("type %d Remove service->nameservers[%d]: %s",type, i,
 +                    service->nameservers[i]);
 +              switch(type) {
 +                      case CONNMAN_IPCONFIG_TYPE_IPV4:
 +                              if (connman_inet_check_ipaddress(
 +                                      service->nameservers[i]) == AF_INET &&
 +                                      (service->dns_config_method_ipv4 ==
 +                                              CONNMAN_DNSCONFIG_METHOD_MANUAL ||
 +                                      service->dns_config_method_ipv4 ==
 +                                              CONNMAN_DNSCONFIG_METHOD_DHCP)) {
 +                                      nameserver_remove(service, type,
 +                                                        service->nameservers[i]);
 +                              }
 +                              break;
 +                      case CONNMAN_IPCONFIG_TYPE_IPV6:
 +                              if (connman_inet_check_ipaddress(
 +                                      service->nameservers[i]) == AF_INET6 &&
 +                                      (service->dns_config_method_ipv6 ==
 +                                              CONNMAN_DNSCONFIG_METHOD_MANUAL ||
 +                                      service->dns_config_method_ipv6 ==
 +                                              CONNMAN_DNSCONFIG_METHOD_DHCP)) {
 +                                      nameserver_remove(service, type,
 +                                                        service->nameservers[i]);
 +                              }
 +                              break;
 +                      case CONNMAN_IPCONFIG_TYPE_ALL:
 +                              if (connman_inet_check_ipaddress(
 +                                      service->nameservers[i]) == AF_INET &&
 +                                      (service->dns_config_method_ipv4 ==
 +                                              CONNMAN_DNSCONFIG_METHOD_MANUAL ||
 +                                      service->dns_config_method_ipv4 ==
 +                                              CONNMAN_DNSCONFIG_METHOD_DHCP)) {
 +                                      nameserver_remove(service, type,
 +                                                        service->nameservers[i]);
 +                              }
 +                              if (connman_inet_check_ipaddress(
 +                                      service->nameservers[i]) == AF_INET6 &&
 +                                      (service->dns_config_method_ipv6 ==
 +                                              CONNMAN_DNSCONFIG_METHOD_MANUAL ||
 +                                      service->dns_config_method_ipv6 ==
 +                                              CONNMAN_DNSCONFIG_METHOD_DHCP)) {
 +                                      nameserver_remove(service, type,
 +                                                        service->nameservers[i]);
 +                              }
 +                              break;
 +                      case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
 +                              DBG("CONNMAN_IPCONFIG_TYPE_UNKNOWN do nothing");
 +                              break;
 +                      default:
 +                              DBG("default case do nothing");
 +                              break;
 +              }
 +#else
                nameserver_remove(service, type, service->nameservers[i]);
 +#endif
                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;
   * inserted to resolver via netlink message (see rtnl.c:rtnl_newnduseropt()
   * for details) and not through service.c
   */
 +#if defined TIZEN_EXT
 +int __connman_service_nameserver_append(struct connman_service *service,
 +                              const char *nameserver, bool is_auto,
 +                              enum connman_ipconfig_type type)
 +#else
  int __connman_service_nameserver_append(struct connman_service *service,
                                const char *nameserver, bool is_auto)
 +#endif
  {
        char **nameservers;
        int len, i;
  
        if (nameservers) {
                for (i = 0; nameservers[i]; i++) {
 +#if defined TIZEN_EXT
 +                      DBG("nameservers[%d] %s, nameserver %s", i, nameservers[i], nameserver);
 +#endif
                        if (g_strcmp0(nameservers[i], nameserver) == 0)
                                return -EEXIST;
                }
        nameservers[len] = g_strdup(nameserver);
        nameservers[len + 1] = NULL;
  
 +#ifdef TIZEN_EXT
 +      if(type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
 +         service->dns_config_method_ipv4 == CONNMAN_DNSCONFIG_METHOD_UNKNOWN)
 +              service->dns_config_method_ipv4 = CONNMAN_DNSCONFIG_METHOD_DHCP;
 +
 +      if(type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
 +         service->dns_config_method_ipv6 == CONNMAN_DNSCONFIG_METHOD_UNKNOWN)
 +              service->dns_config_method_ipv6 = CONNMAN_DNSCONFIG_METHOD_DHCP;
 +#endif
 +
        if (is_auto) {
                service->nameservers_auto = nameservers;
        } else {
        return 0;
  }
  
 +#if defined TIZEN_EXT
 +int __connman_service_nameserver_remove(struct connman_service *service,
 +                              const char *nameserver, bool is_auto,
 +                              enum connman_ipconfig_type type)
 +#else
  int __connman_service_nameserver_remove(struct connman_service *service,
                                const char *nameserver, bool is_auto)
 +#endif
  {
        char **servers, **nameservers;
        bool found = false;
@@@ -2589,14 -1283,8 +2625,14 @@@ set_servers
                service->nameservers_auto = nameservers;
        } else {
                service->nameservers = nameservers;
 +#if defined TIZEN_EXT
 +              DBG("nameserver remove ip_type: %d", type);
 +              nameserver_remove(service, type,
 +                              nameserver);
 +#else
                nameserver_remove(service, CONNMAN_IPCONFIG_TYPE_ALL,
                                nameserver);
 +#endif
        }
  
        return 0;
@@@ -2765,6 -1453,12 +2801,12 @@@ static void start_online_check(struct c
                        "Default service remains in READY state.");
                return;
        }
+       enable_online_to_ready_transition =
+               connman_setting_get_bool("EnableOnlineToReadyTransition");
+       online_check_initial_interval =
+               connman_setting_get_uint("OnlineCheckInitialInterval");
+       online_check_max_interval =
+               connman_setting_get_uint("OnlineCheckMaxInterval");
  
        if (type != CONNMAN_IPCONFIG_TYPE_IPV4 || check_proxy_setup(service)) {
                cancel_online_check(service);
@@@ -2873,93 -1567,8 +2915,93 @@@ static void reset_stats(struct connman_
        g_timer_reset(service->stats_roaming.timer);
  }
  
 +#if defined TIZEN_EXT
 +static gboolean __connman_service_is_internet_profile(
 +              struct connman_service *cellular)
 +{
 +      const char internet_suffix[] = "_1";
 +
 +      DBG("Service path: %s", cellular->path);
 +
 +      if (g_str_has_suffix(cellular->path, internet_suffix) == TRUE)
 +              return TRUE;
 +
 +      return FALSE;
 +}
 +
 +struct connman_service *connman_service_get_default_connection(void)
 +{
 +      GList *list;
 +      struct connman_service *service;
 +      struct connman_service *default_service = NULL;
 +
 +      for (list = service_list; list; list = list->next) {
 +              service = list->data;
 +
 +              DBG("service: %p %s %s %s", service, service->name,
 +                              state2string(service->state),
 +                              __connman_service_type2string(service->type));
 +
 +#if defined TIZEN_MAINTAIN_ONLINE
 +              if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
 +                              service->state == CONNMAN_SERVICE_STATE_ONLINE) {
 +#else
 +              if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
 +                              is_connected(service->state) == TRUE) {
 +#endif
 +                      return service;
 +              } else if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
 +                              __connman_service_is_internet_profile(service) == TRUE) {
 +                      if (default_service == NULL)
 +                              default_service = service;
 +                      else if (is_connected(service->state) == TRUE &&
 +                                      is_connected(default_service->state) == FALSE)
 +                              default_service = service;
 +              } else if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET &&
 +                              is_connected(service->state) == TRUE) {
 +                      if (default_service == NULL)
 +                              default_service = service;
 +              } else if (service->type == CONNMAN_SERVICE_TYPE_BLUETOOTH &&
 +                              is_connected(service->state) == TRUE) {
 +                      if (default_service == NULL)
 +                              default_service = service;
 +              }
 +      }
 +
 +      return default_service;
 +}
 +
 +struct connman_service *connman_service_get_connected_service(const char *ifname)
 +{
 +      GList *list;
 +      const char *svc_ifname;
 +      struct connman_service *service;
 +
 +      if (!ifname)
 +              return NULL;
 +
 +      for (list = service_list; list; list = list->next) {
 +              service = list->data;
 +
 +              if (!is_connected(service->state))
 +                      continue;
 +
 +              svc_ifname = connman_device_get_string(
 +                              connman_network_get_device(service->network), "Interface");
 +
 +              if (svc_ifname && g_strcmp0(svc_ifname, ifname) == 0)
 +                      return service;
 +      }
 +
 +      return NULL;
 +}
 +#endif
 +
  struct connman_service *connman_service_get_default(void)
  {
 +#if defined TIZEN_MAINTAIN_ONLINE
 +      return connman_service_get_default_connection();
 +#else
        struct connman_service *service;
  
        if (!service_list)
                return NULL;
  
        return service;
 +#endif
  }
  
  bool __connman_service_index_is_default(int index)
  
  static void default_changed(void)
  {
 +#if defined TIZEN_EXT
 +      struct connman_service *service = connman_service_get_default_connection();
 +#else
        struct connman_service *service = connman_service_get_default();
 +#endif
  
        if (service == current_default)
                return;
                current_default ? current_default->identifier : "");
        DBG("new default %p %s", service, service ? service->identifier : "");
  
 +#if defined TIZEN_EXT
 +      current_default = service;
 +
 +      __connman_service_timeserver_changed(service, NULL);
 +#else
        __connman_service_timeserver_changed(current_default, NULL);
  
        current_default = service;
 +#endif
  
        if (service) {
                if (service->hostname &&
                                connman_setting_get_bool("AllowDomainnameUpdates"))
                        __connman_utsname_set_domainname(service->domainname);
  
+               if (__connman_service_is_connected_state(service,
+                                               CONNMAN_IPCONFIG_TYPE_IPV4))
+                       __connman_service_wispr_start(service,
+                                               CONNMAN_IPCONFIG_TYPE_IPV4);
+               if (__connman_service_is_connected_state(service,
+                                               CONNMAN_IPCONFIG_TYPE_IPV6))
+                       __connman_service_wispr_start(service,
+                                               CONNMAN_IPCONFIG_TYPE_IPV6);
                /*
                 * Connect VPN automatically when new default service
                 * is set and connected, unless new default is VPN
        __connman_notifier_default_changed(service);
  }
  
 +#if defined TIZEN_EXT
 +static void append_struct(gpointer value, gpointer user_data);
 +
 +static void emit_state_changed_with_properties(struct connman_service *service)
 +{
 +      DBusMessage *signal;
 +      DBusMessageIter iter;
 +
 +      if (!service)
 +              return;
 +
 +      signal = dbus_message_new_signal(service->path, CONNMAN_SERVICE_INTERFACE,
 +                      "StateChangedProperties");
 +      if (!signal)
 +              return;
 +
 +      dbus_message_iter_init_append(signal, &iter);
 +      append_struct(service, &iter);
 +
 +      g_dbus_send_message(connection, signal);
 +
 +      return;
 +}
 +#endif
 +
  static void state_changed(struct connman_service *service)
  {
        const char *str;
        if (!str)
                return;
  
 +#if !defined TIZEN_EXT
        if (!allow_property_changed(service))
                return;
 +#else
 +      DBG(" %s, %s", str, service->path);
 +#endif
  
        connman_dbus_property_changed_basic(service->path,
                                CONNMAN_SERVICE_INTERFACE, "State",
                                                DBUS_TYPE_STRING, &str);
 +
 +#if defined TIZEN_EXT
 +      emit_state_changed_with_properties(service);
 +#endif
 +}
 +
 +#if defined TIZEN_EXT
 +static void connect_reason_changed(struct connman_service *service)
 +{
 +#if defined TIZEN_EXT_INS
 +      struct connman_device *device;
 +#endif
 +      if (!service->path)
 +              return;
 +
 +      if (!allow_property_changed(service))
 +              return;
 +
 +#if defined TIZEN_EXT_INS
 +      if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER) {
 +              device = connman_network_get_device(service->network);
 +              if (device) {
 +                      bool need_save = false;
 +
 +                      need_save |= connman_device_set_last_user_selection_ident(device, service->identifier);
 +                      need_save |= connman_device_set_last_user_selection_time(device, time(NULL));
 +
 +                      DBG("last user selection ident[%s] time[%ld]",
 +                              connman_device_get_last_user_selection_ident(device),
 +                              connman_device_get_last_user_selection_time(device));
 +
 +                      if (need_save)
 +                              connman_device_save_last_user_selection(device);
 +              }
 +      }
 +#endif
 +
 +      connman_dbus_property_changed_basic(service->path,
 +                                      CONNMAN_SERVICE_INTERFACE,
 +                                      "ConnectReason",
 +                                      DBUS_TYPE_INT32,
 +                                      &service->connect_reason);
 +}
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
 +
 +#if defined TIZEN_EXT
 +static void disconnection_requested_changed(struct connman_service *service)
 +{
 +      dbus_bool_t disconnection_requested;
 +
 +      if (!service->path)
 +              return;
 +
 +      if (!allow_property_changed(service))
 +              return;
 +
 +      disconnection_requested = service->disconnection_requested;
 +      connman_dbus_property_changed_basic(service->path,
 +                                          CONNMAN_SERVICE_INTERFACE,
 +                                          "DisconnectionRequested",
 +                                          DBUS_TYPE_BOOLEAN,
 +                                          &disconnection_requested);
 +}
 +
 +void connman_service_set_disconnection_requested(struct connman_service *service,
 +                                               bool disconnection_requested)
 +{
 +      if (service == NULL)
 +              return;
 +
 +      service->disconnection_requested = disconnection_requested;
 +      disconnection_requested_changed(service);
  }
 +#endif
  
  static void strength_changed(struct connman_service *service)
  {
                                        DBUS_TYPE_BYTE, &service->strength);
  }
  
 +#if defined TIZEN_EXT
 +static bool update_last_connected_bssid(struct connman_service *service)
 +{
 +      const unsigned char *last_connected_bssid;
 +
 +      if (!service->network)
 +              return false;
 +
 +      last_connected_bssid = connman_network_get_last_connected_bssid(service->network);
 +      if (memcmp(last_connected_bssid, invalid_bssid, WIFI_BSSID_LEN_MAX) == 0)
 +              return false;
 +
 +      if (memcmp(last_connected_bssid, service->last_connected_bssid, WIFI_BSSID_LEN_MAX) != 0) {
 +              memcpy(service->last_connected_bssid, last_connected_bssid, WIFI_BSSID_LEN_MAX);
 +              return true;
 +      }
 +
 +      return false;
 +}
 +#endif
 +
  static void favorite_changed(struct connman_service *service)
  {
        dbus_bool_t favorite;
@@@ -3261,6 -1746,8 +3313,8 @@@ bool connman_service_set_autoconnect(st
        service->autoconnect = autoconnect;
        autoconnect_changed(service);
  
+       connman_network_set_autoconnect(service->network, autoconnect);
        return true;
  }
  
@@@ -3284,16 -1771,10 +3338,16 @@@ static void append_security(DBusMessage
                case CONNMAN_SERVICE_SECURITY_PSK:
                case CONNMAN_SERVICE_SECURITY_WPA:
                case CONNMAN_SERVICE_SECURITY_RSN:
 +#if defined TIZEN_EXT
 +              case CONNMAN_SERVICE_SECURITY_SAE:
 +#endif
                        str = "wps";
                        dbus_message_iter_append_basic(iter,
                                                DBUS_TYPE_STRING, &str);
                        break;
 +#if defined TIZEN_EXT
 +              case CONNMAN_SERVICE_SECURITY_OWE:
 +#endif
                case CONNMAN_SERVICE_SECURITY_UNKNOWN:
                case CONNMAN_SERVICE_SECURITY_NONE:
                case CONNMAN_SERVICE_SECURITY_WEP:
@@@ -3334,57 -1815,6 +3388,57 @@@ static void append_ethernet(DBusMessage
                                                                        iter);
  }
  
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +static void append_eap_over_ethernet(DBusMessageIter *iter, void *user_data)
 +{
 +      struct connman_service *service = user_data;
 +      dbus_bool_t val;
 +
 +      val = service->use_eapol;
 +      connman_dbus_dict_append_basic(iter, "UseEapol",
 +                      DBUS_TYPE_BOOLEAN, &val);
 +      if (service->use_eapol) {
 +              if (service->eap)
 +                      connman_dbus_dict_append_basic(iter, "EAP",
 +                                      DBUS_TYPE_STRING, &service->eap);
 +
 +              if (service->identity)
 +                      connman_dbus_dict_append_basic(iter, "Identity",
 +                                      DBUS_TYPE_STRING, &service->identity);
 +
 +              if (service->anonymous_identity)
 +                      connman_dbus_dict_append_basic(iter, "AnonymousIdentity",
 +                                      DBUS_TYPE_STRING, &service->anonymous_identity);
 +
 +              if (service->ca_cert_file)
 +                      connman_dbus_dict_append_basic(iter, "CACertFile",
 +                                      DBUS_TYPE_STRING, &service->ca_cert_file);
 +
 +              if (service->client_cert_file)
 +                      connman_dbus_dict_append_basic(iter, "ClientCertFile",
 +                                      DBUS_TYPE_STRING, &service->client_cert_file);
 +
 +              if (service->private_key_file)
 +                      connman_dbus_dict_append_basic(iter, "PrivateKeyFile",
 +                                      DBUS_TYPE_STRING, &service->private_key_file);
 +
 +              if (service->phase2)
 +                      connman_dbus_dict_append_basic(iter, "Phase2",
 +                                      DBUS_TYPE_STRING, &service->phase2);
 +
 +              if (service->phase1)
 +                      connman_dbus_dict_append_basic(iter, "Phase1",
 +                                      DBUS_TYPE_STRING, &service->phase1);
 +
 +              if (service->pac_file)
 +                      connman_dbus_dict_append_basic(iter, "PacFile",
 +                                      DBUS_TYPE_STRING, &service->pac_file);
 +
 +              /* Should we include passphrase? */
 +      }
 +}
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
  static void append_ipv4(DBusMessageIter *iter, void *user_data)
  {
        struct connman_service *service = user_data;
@@@ -3444,143 -1874,20 +3498,143 @@@ static void append_nameservers(DBusMess
        }
  }
  
 +#if defined TIZEN_EXT
 +static void append_nameserver_manual(DBusMessageIter *iter,
 +              struct connman_service *service, const char *server)
 +{
 +      bool available = true;
 +
 +      if (service)
 +              available = nameserver_available(service,
 +                              CONNMAN_IPCONFIG_TYPE_ALL, server);
 +
 +      if (available)
 +              dbus_message_iter_append_basic(iter,
 +                              DBUS_TYPE_STRING, &server);
 +}
 +
 +static void append_nameserver_dhcp(DBusMessageIter *iter,
 +              struct connman_service *service, const char *server)
 +{
 +      bool available = true;
 +
 +      if (service)
 +              available = nameserver_available(service,
 +                              CONNMAN_IPCONFIG_TYPE_ALL, server);
 +
 +      if (available)
 +              dbus_message_iter_append_basic(iter,
 +                              DBUS_TYPE_STRING, &server);
 +}
 +#endif
 +
  static void append_dns(DBusMessageIter *iter, void *user_data)
  {
        struct connman_service *service = user_data;
 +#if defined TIZEN_EXT
 +      int i;
 +#endif
  
        if (!is_connected(service->state))
                return;
  
 +#ifdef TIZEN_EXT
 +      const char *str;
 +
 +      str = __connman_dnsconfig_method2string(service->dns_config_method_ipv4);
 +      if(str != NULL) {
 +              char *str1 = g_strdup_printf("ipv4.%s", str);
 +              dbus_message_iter_append_basic(iter,
 +                      DBUS_TYPE_STRING, &str1);
 +              g_free(str1);
 +      }
 +
 +      str = __connman_dnsconfig_method2string(service->dns_config_method_ipv6);
 +      if(str != NULL) {
 +              char *str1 = g_strdup_printf("ipv6.%s", str);
 +              dbus_message_iter_append_basic(iter,
 +                      DBUS_TYPE_STRING, &str1);
 +              g_free(str1);
 +      }
 +#endif
 +
        if (service->nameservers_config) {
 +#if defined TIZEN_EXT
 +              i = 0;
 +              while (service->nameservers_config[i]) {
 +                      if (connman_inet_check_ipaddress(
 +                              service->nameservers_config[i]) == AF_INET &&
 +                              service->dns_config_method_ipv4 ==
 +                                      CONNMAN_DNSCONFIG_METHOD_MANUAL) {
 +                              append_nameserver_manual(iter, service,
 +                                              service->nameservers_config[i]);
 +                      }
 +
 +                      if (connman_inet_check_ipaddress(
 +                              service->nameservers_config[i]) == AF_INET6 &&
 +                              service->dns_config_method_ipv6 ==
 +                                      CONNMAN_DNSCONFIG_METHOD_MANUAL) {
 +                              append_nameserver_manual(iter, service,
 +                                              service->nameservers_config[i]);
 +                      }
 +                      i++;
 +              }
 +              /* In case of mixed DNS Config Type one of IPv4/IPv6 can be
 +               * dynamic while other is static so try to append the DNS
 +               * Address which is dynamic also */
 +              if (service->nameservers != NULL) {
 +                      i = 0;
 +                      while (service->nameservers[i]) {
 +                              if (connman_inet_check_ipaddress(
 +                                      service->nameservers[i]) == AF_INET &&
 +                                      service->dns_config_method_ipv4 ==
 +                                              CONNMAN_DNSCONFIG_METHOD_DHCP) {
 +                                      append_nameserver_dhcp(iter, service,
 +                                                      service->nameservers[i]);
 +                              }
 +
 +                              if (connman_inet_check_ipaddress(
 +                                      service->nameservers[i]) == AF_INET6 &&
 +                                      service->dns_config_method_ipv6 ==
 +                                              CONNMAN_DNSCONFIG_METHOD_DHCP) {
 +                                      append_nameserver_dhcp(iter, service,
 +                                                      service->nameservers[i]);
 +                              }
 +                              i++;
 +                      }
 +              }
 +#else
                append_nameservers(iter, service, service->nameservers_config);
 +#endif
                return;
        } else {
                if (service->nameservers)
 +#if defined TIZEN_EXT
 +              {
 +                      i = 0;
 +                      while (service->nameservers[i]) {
 +                              if (connman_inet_check_ipaddress(
 +                                      service->nameservers[i]) == AF_INET &&
 +                                      service->dns_config_method_ipv4 ==
 +                                              CONNMAN_DNSCONFIG_METHOD_DHCP) {
 +                                      append_nameserver_dhcp(iter, service,
 +                                                      service->nameservers[i]);
 +                              }
 +
 +                              if (connman_inet_check_ipaddress(
 +                                      service->nameservers[i]) == AF_INET6 &&
 +                                      service->dns_config_method_ipv6 ==
 +                                              CONNMAN_DNSCONFIG_METHOD_DHCP) {
 +                                      append_nameserver_dhcp(iter, service,
 +                                                      service->nameservers[i]);
 +                              }
 +                              i++;
 +                      }
 +              }
 +#else
                        append_nameservers(iter, service,
                                        service->nameservers);
 +#endif
  
                if (service->nameservers_auto)
                        append_nameservers(iter, service,
@@@ -3602,46 -1909,10 +3656,46 @@@ static void append_dnsconfig(DBusMessag
  {
        struct connman_service *service = user_data;
  
 +#ifdef TIZEN_EXT
 +      /* Append DNS Config Type */
 +      const char *str;
 +      str = __connman_dnsconfig_method2string(service->dns_config_method_ipv4);
 +      if(str != NULL) {
 +              char *str1 = g_strdup_printf("ipv4.%s", str);
 +              dbus_message_iter_append_basic(iter,
 +                      DBUS_TYPE_STRING, &str1);
 +              g_free(str1);
 +      }
 +
 +      str = __connman_dnsconfig_method2string(service->dns_config_method_ipv6);
 +      if(str != NULL) {
 +              char *str1 = g_strdup_printf("ipv6.%s", str);
 +              dbus_message_iter_append_basic(iter,
 +                      DBUS_TYPE_STRING, &str1);
 +              g_free(str1);
 +      }
 +#endif
 +
        if (!service->nameservers_config)
                return;
  
 +#if defined TIZEN_EXT
 +      int i = 0;
 +      while (service->nameservers_config[i]) {
 +              if (connman_inet_check_ipaddress(service->nameservers_config[i]) == AF_INET &&
 +                              service->dns_config_method_ipv4 == CONNMAN_DNSCONFIG_METHOD_MANUAL) {
 +                      append_nameserver_manual(iter, NULL, service->nameservers_config[i]);
 +              }
 +
 +              if (connman_inet_check_ipaddress(service->nameservers_config[i]) == AF_INET6 &&
 +                              service->dns_config_method_ipv6 == CONNMAN_DNSCONFIG_METHOD_MANUAL) {
 +                      append_nameserver_manual(iter, NULL, service->nameservers_config[i]);
 +              }
 +              i++;
 +      }
 +#else
        append_nameservers(iter, NULL, service->nameservers_config);
 +#endif
  }
  
  static void append_ts(DBusMessageIter *iter, void *user_data)
@@@ -4256,154 -2527,6 +4310,154 @@@ int connman_service_iterate_services(co
        return ret;
  }
  
 +#if defined TIZEN_EXT
 +static void append_security_list(DBusMessageIter *iter, void *user_data)
 +{
 +      GSList *sec_list = (GSList *)user_data;
 +      const char *sec_str;
 +
 +      if (sec_list) {
 +              GSList *list;
 +              for (list = sec_list; list; list = list->next) {
 +                      sec_str = (const char *)list->data;
 +
 +                      dbus_message_iter_append_basic(iter,
 +                                      DBUS_TYPE_STRING, &sec_str);
 +              }
 +      }
 +}
 +
 +static void append_wifi_ext_info(DBusMessageIter *dict,
 +                                      struct connman_network *network)
 +{
 +      char bssid_buff[WIFI_BSSID_STR_LEN] = {0,};
 +      char *bssid_str = bssid_buff;
 +      const void *ssid;
 +      unsigned int ssid_len;
 +      unsigned char *bssid;
 +      unsigned int maxrate;
 +      int maxspeed;
 +      unsigned int keymgmt;
 +      uint16_t frequency;
 +      const char *enc_mode;
 +      const char *str;
 +      gboolean passpoint;
 +      gboolean pmf_required;
 +      char country_code_buff[WIFI_COUNTRY_CODE_LEN + 1] = {0,};
 +      char *country_code_str = country_code_buff;
 +      unsigned char *country_code;
 +      uint16_t connection_mode;
 +      GSList *sec_list = NULL;
 +
 +      ssid = connman_network_get_blob(network, "WiFi.SSID", &ssid_len);
 +      bssid = connman_network_get_bssid(network);
 +      maxrate = connman_network_get_maxrate(network);
 +      maxspeed = connman_network_get_maxspeed(network);
 +      frequency = connman_network_get_frequency(network);
 +      enc_mode = connman_network_get_enc_mode(network);
 +      passpoint = connman_network_get_bool(network, "WiFi.HS20AP");
 +      keymgmt = connman_network_get_keymgmt(network);
 +      pmf_required = connman_network_get_bool(network, "WiFi.PMFRequired");
 +      country_code = connman_network_get_countrycode(network);
 +      connection_mode = connman_network_get_connection_mode(network);
 +      sec_list = (GSList *)connman_network_get_sec_list(network);
 +
 +      snprintf(bssid_str, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bssid));
 +
 +      snprintf(country_code_str, (WIFI_COUNTRY_CODE_LEN + 1), "%c%c",
 +               country_code[0], country_code[1]);
 +
 +      connman_dbus_dict_append_array(dict, "SecurityList",
 +                                      DBUS_TYPE_STRING,
 +                                      append_security_list, sec_list);
 +
 +      connman_dbus_dict_append_fixed_array(dict, "SSID",
 +                                      DBUS_TYPE_BYTE, &ssid, ssid_len);
 +      connman_dbus_dict_append_basic(dict, "BSSID",
 +                                      DBUS_TYPE_STRING, &bssid_str);
 +      connman_dbus_dict_append_basic(dict, "MaxRate",
 +                                      DBUS_TYPE_UINT32, &maxrate);
 +      connman_dbus_dict_append_basic(dict, "MaxSpeed",
 +                                      DBUS_TYPE_INT32, &maxspeed);
 +      connman_dbus_dict_append_basic(dict, "Frequency",
 +                                      DBUS_TYPE_UINT16, &frequency);
 +      connman_dbus_dict_append_basic(dict, "EncryptionMode",
 +                                      DBUS_TYPE_STRING, &enc_mode);
 +      connman_dbus_dict_append_basic(dict, "Passpoint",
 +                                      DBUS_TYPE_BOOLEAN, &passpoint);
 +      connman_dbus_dict_append_basic(dict, "Keymgmt",
 +                                      DBUS_TYPE_UINT32, &keymgmt);
 +      connman_dbus_dict_append_basic(dict, "PmfReq",
 +                                      DBUS_TYPE_BOOLEAN, &pmf_required);
 +      connman_dbus_dict_append_basic(dict, "Country", DBUS_TYPE_STRING,
 +                                     &country_code_str);
 +      connman_dbus_dict_append_basic(dict, "ConnMode",
 +                                      DBUS_TYPE_UINT16, &connection_mode);
 +
 +      str = connman_network_get_string(network, "WiFi.Security");
 +      if (str != NULL && g_str_equal(str, "ieee8021x") == TRUE) {
 +              str = connman_network_get_string(network, "WiFi.EAP");
 +              if (str != NULL)
 +                      connman_dbus_dict_append_basic(dict, "EAP",
 +                                      DBUS_TYPE_STRING, &str);
 +
 +              str = connman_network_get_string(network, "WiFi.Phase2");
 +              if (str != NULL)
 +                      connman_dbus_dict_append_basic(dict, "Phase2",
 +                                      DBUS_TYPE_STRING, &str);
 +
 +              str = connman_network_get_string(network, "WiFi.Identity");
 +              if (str != NULL)
 +                      connman_dbus_dict_append_basic(dict, "Identity",
 +                                      DBUS_TYPE_STRING, &str);
 +
 +              str = connman_network_get_string(network, "WiFi.CACertFile");
 +              if (str != NULL)
 +                      connman_dbus_dict_append_basic(dict, "CACertFile",
 +                                      DBUS_TYPE_STRING, &str);
 +
 +              str = connman_network_get_string(network,
 +                              "WiFi.ClientCertFile");
 +              if (str != NULL)
 +                      connman_dbus_dict_append_basic(dict, "ClientCertFile",
 +                                      DBUS_TYPE_STRING, &str);
 +
 +              str = connman_network_get_string(network,
 +                              "WiFi.PrivateKeyFile");
 +              if (str != NULL)
 +                      connman_dbus_dict_append_basic(dict, "PrivateKeyFile",
 +                                      DBUS_TYPE_STRING, &str);
 +      }
 +}
 +
 +static void append_bssid_info(DBusMessageIter *iter, void *user_data)
 +{
 +      GSList *bssid_list = NULL;
 +      struct connman_network *network = user_data;
 +      struct connman_bssids *bssids;
 +      char bssid_buf[MAC_ADDRESS_LENGTH] = {0,};
 +      char *bssid_str = bssid_buf;
 +
 +      bssid_list = (GSList *)connman_network_get_bssid_list(network);
 +      if(bssid_list) {
 +              GSList *list;
 +              for (list = bssid_list; list; list = list->next) {
 +                      bssids = (struct connman_bssids *)list->data;
 +                      g_snprintf(bssid_buf, MAC_ADDRESS_LENGTH, MACSTR, MAC2STR(bssids->bssid));
 +
 +                      connman_dbus_dict_append_basic(iter, "BSSID",
 +                                      DBUS_TYPE_STRING, &bssid_str);
 +
 +                      connman_dbus_dict_append_basic(iter, "Strength",
 +                                      DBUS_TYPE_UINT16, &bssids->strength);
 +
 +                      connman_dbus_dict_append_basic(iter, "Frequency",
 +                                      DBUS_TYPE_UINT16, &bssids->frequency);
 +              }
 +      }
 +}
 +#endif
 +
  static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
                                        struct connman_service *service)
  {
        const char *str;
        GSList *list;
  
 +#if defined TIZEN_EXT
 +      unsigned int frequency = 0U;
 +      unsigned char *wifi_vsie;
 +      unsigned int wifi_vsie_len;
 +      GSList *vsie_list = NULL;
 +
 +      if (service->network) {
 +              frequency = connman_network_get_frequency(service->network);
 +              connman_dbus_dict_append_basic(dict, "Frequency",
 +                              DBUS_TYPE_UINT16, &frequency);
 +              vsie_list = (GSList *)connman_network_get_vsie_list(service->network);
 +      }
 +
 +      if (vsie_list) {
 +              GSList *list;
 +              for (list = vsie_list; list; list = list->next) {
 +                      wifi_vsie = (unsigned char *)list->data;
 +                      wifi_vsie_len = wifi_vsie[1] + 2;
 +
 +                      connman_dbus_dict_append_fixed_array(dict, "Vsie", DBUS_TYPE_BYTE,
 +                                      &wifi_vsie, wifi_vsie_len);
 +              }
 +      }
 +#endif
 +
        str = __connman_service_type2string(service->type);
        if (str)
                connman_dbus_dict_append_basic(dict, "Type",
                connman_dbus_dict_append_basic(dict, "State",
                                                DBUS_TYPE_STRING, &str);
  
 +#ifdef TIZEN_EXT
 +      str = state2string(service->state_ipv6);
 +      if (str != NULL)
 +              connman_dbus_dict_append_basic(dict, "StateIPv6",
 +                              DBUS_TYPE_STRING, &str);
 +#endif
 +
        str = error2string(service->error);
        if (str)
                connman_dbus_dict_append_basic(dict, "Error",
        case CONNMAN_SERVICE_TYPE_GPS:
        case CONNMAN_SERVICE_TYPE_VPN:
        case CONNMAN_SERVICE_TYPE_P2P:
 +#if defined TIZEN_EXT_WIFI_MESH
 +      case CONNMAN_SERVICE_TYPE_MESH:
 +#endif
                break;
        case CONNMAN_SERVICE_TYPE_CELLULAR:
                val = service->roaming;
                                                append_ethernet, service);
                break;
        case CONNMAN_SERVICE_TYPE_WIFI:
 +#if defined TIZEN_EXT
 +              if (service->network != NULL) {
 +                      append_wifi_ext_info(dict, service->network);
 +                      connman_dbus_dict_append_dict(dict, "BSSID.List",
 +                                      append_bssid_info, service->network);
 +              }
 +
 +              connman_dbus_dict_append_dict(dict, "Ethernet",
 +                                              append_ethernet, service);
 +
 +              service->disconnect_reason = connman_network_get_disconnect_reason(service->network);
 +              connman_dbus_dict_append_basic(dict, "DisconnectReason",
 +                              DBUS_TYPE_INT32, &service->disconnect_reason);
 +
 +              connman_dbus_dict_append_basic(dict, "AssocStatusCode",
 +                              DBUS_TYPE_INT32, &service->assoc_status_code);
 +
 +              val = service->hidden_service;
 +              connman_dbus_dict_append_basic(dict, "Hidden",
 +                              DBUS_TYPE_BOOLEAN, &val);
 +
 +              break;
 +#endif
        case CONNMAN_SERVICE_TYPE_ETHERNET:
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +              connman_dbus_dict_append_dict(dict, "EapOverEthernet",
 +                                              append_eap_over_ethernet, service);
 +              /* fall through */
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
        case CONNMAN_SERVICE_TYPE_BLUETOOTH:
        case CONNMAN_SERVICE_TYPE_GADGET:
                connman_dbus_dict_append_dict(dict, "Ethernet",
                connman_network_append_acddbus(dict, service->network);
  }
  
 +#if defined TIZEN_EXT && defined TIZEN_EXT_INS
 +static void append_ins_bssid_info(DBusMessageIter *iter, void *user_data)
 +{
 +      GSList *bssid_list = NULL;
 +      struct connman_network *network = user_data;
 +      struct connman_bssids *bssids;
 +      char bssid_buf[MAC_ADDRESS_LENGTH] = {0,};
 +      char *bssid_str = bssid_buf;
 +
 +      bssid_list = (GSList *)connman_network_get_bssid_list(network);
 +      if(bssid_list) {
 +              GSList *list;
 +              for (list = bssid_list; list; list = list->next) {
 +                      bssids = (struct connman_bssids *)list->data;
 +                      g_snprintf(bssid_buf, MAC_ADDRESS_LENGTH, MACSTR, MAC2STR(bssids->bssid));
 +
 +                      connman_dbus_dict_append_basic(iter, "BSSID",
 +                                      DBUS_TYPE_STRING, &bssid_str);
 +
 +                      connman_dbus_dict_append_basic(iter, "ScoreINS",
 +                                      DBUS_TYPE_INT32, &bssids->ins_score);
 +
 +                      connman_dbus_dict_append_basic(iter, "ScoreLastConnected",
 +                                      DBUS_TYPE_INT32, &bssids->score_last_connected_bssid);
 +
 +                      connman_dbus_dict_append_basic(iter, "ScoreAssocReject",
 +                                      DBUS_TYPE_INT32, &bssids->score_assoc_reject);
 +
 +                      connman_dbus_dict_append_basic(iter, "Frequency",
 +                                      DBUS_TYPE_UINT16, &bssids->frequency);
 +
 +                      connman_dbus_dict_append_basic(iter, "ScoreFrequency",
 +                                      DBUS_TYPE_INT32, &bssids->score_frequency);
 +
 +                      connman_dbus_dict_append_basic(iter, "Strength",
 +                                      DBUS_TYPE_UINT16, &bssids->strength);
 +
 +                      connman_dbus_dict_append_basic(iter, "ScoreStrength",
 +                                      DBUS_TYPE_INT32, &bssids->score_strength);
 +              }
 +      }
 +}
 +
 +static void append_ins_properties(DBusMessageIter *dict,
 +                                      struct connman_service *service)
 +{
 +      const char *str;
 +      unsigned int frequency = 0U;
 +
 +      if (service->name)
 +              connman_dbus_dict_append_basic(dict, "Name",
 +                                      DBUS_TYPE_STRING, &service->name);
 +
 +      connman_dbus_dict_append_basic(dict, "ScoreINS",
 +                              DBUS_TYPE_INT32, &service->ins_score);
 +
 +      connman_dbus_dict_append_basic(dict, "ScoreLastUserSelection",
 +                              DBUS_TYPE_INT32, &service->score_last_user_selection);
 +
 +      connman_dbus_dict_append_basic(dict, "ScoreLastConnected",
 +                              DBUS_TYPE_INT32, &service->score_last_connected);
 +
 +      str = security2string(service->security);
 +      if (str)
 +              connman_dbus_dict_append_basic(dict, "Security",
 +                              DBUS_TYPE_STRING, &str);
 +
 +      connman_dbus_dict_append_basic(dict, "ScoreSecurityPriority",
 +                              DBUS_TYPE_INT32, &service->score_security_priority);
 +
 +      connman_dbus_dict_append_basic(dict, "Strength",
 +                              DBUS_TYPE_BYTE, &service->strength);
 +
 +      connman_dbus_dict_append_basic(dict, "ScoreStrength",
 +                              DBUS_TYPE_INT32, &service->score_strength);
 +
 +      connman_dbus_dict_append_basic(dict, "ScoreInternetConnection",
 +                              DBUS_TYPE_INT32, &service->score_internet_connection);
 +
 +      if (service->network) {
 +              frequency = connman_network_get_frequency(service->network);
 +              connman_dbus_dict_append_basic(dict, "Frequency",
 +                              DBUS_TYPE_UINT16, &frequency);
 +
 +              connman_dbus_dict_append_basic(dict, "ScoreFrequency",
 +                              DBUS_TYPE_INT32, &service->score_frequency);
 +
 +              connman_dbus_dict_append_dict(dict, "BSSID.List",
 +                              append_ins_bssid_info, service->network);
 +      }
 +}
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
 +
  static void append_struct_service(DBusMessageIter *iter,
                connman_dbus_append_cb_t function,
                struct connman_service *service)
@@@ -4726,34 -2693,6 +4780,34 @@@ static void append_struct(gpointer valu
        append_struct_service(iter, append_dict_properties, service);
  }
  
 +#if defined TIZEN_EXT && defined TIZEN_EXT_INS
 +static void append_dict_ins_properties(DBusMessageIter *dict, void *user_data)
 +{
 +      struct connman_service *service = user_data;
 +
 +      append_ins_properties(dict, service);
 +}
 +
 +static void append_ins_struct(gpointer value, gpointer user_data)
 +{
 +      struct connman_service *service = value;
 +      DBusMessageIter *iter = user_data;
 +
 +      if (!service->path)
 +              return;
 +
 +      if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
 +              return;
 +
 +      append_struct_service(iter, append_dict_ins_properties, service);
 +}
 +
 +void __connman_ins_list_struct(DBusMessageIter *iter)
 +{
 +      g_list_foreach(service_list, append_ins_struct, iter);
 +}
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
 +
  void __connman_service_list_struct(DBusMessageIter *iter)
  {
        g_list_foreach(service_list, append_struct, iter);
@@@ -4910,54 -2849,6 +4964,54 @@@ char **connman_service_get_timeservers(
        return service->timeservers;
  }
  
 +#if defined TIZEN_EXT
 +/*
 + * Description: Telephony plug-in requires manual PROXY setting function
 + */
 +int connman_service_set_proxy(struct connman_service *service,
 +                                      const char *proxy, gboolean active)
 +{
 +      char **proxies_array = NULL;
 +
 +      if (service == NULL)
 +              return -EINVAL;
 +
 +      switch (service->type) {
 +      case CONNMAN_SERVICE_TYPE_CELLULAR:
 +      case CONNMAN_SERVICE_TYPE_ETHERNET:
 +      case CONNMAN_SERVICE_TYPE_WIFI:
 +              break;
 +
 +      default:
 +              return -EINVAL;
 +      }
 +
 +      g_strfreev(service->proxies);
 +      service->proxies = NULL;
 +
 +      if (proxy != NULL)
 +              proxies_array = g_strsplit(proxy, " ", 0);
 +
 +      service->proxies = proxies_array;
 +
 +      if (proxy == NULL) {
 +              service->proxy_config = CONNMAN_SERVICE_PROXY_METHOD_DIRECT;
 +              DBG("proxy changed (%d)", active);
 +      } else {
 +              service->proxy_config = CONNMAN_SERVICE_PROXY_METHOD_MANUAL;
 +              DBG("proxy chagned %s (%d)", proxy, active);
 +      }
 +
 +      if (active == TRUE) {
 +              proxy_changed(service);
 +
 +              __connman_notifier_proxy_changed(service);
 +      }
 +
 +      return 0;
 +}
 +#endif
 +
  void connman_service_set_proxy_method(struct connman_service *service,
                                        enum connman_service_proxy_method method)
  {
@@@ -5007,54 -2898,6 +5061,54 @@@ const char *connman_service_get_proxy_u
        return service->pac;
  }
  
 +#if defined TIZEN_EXT
 +void connman_service_set_internet_connection(struct connman_service *service,
 +                                                      bool internet_connection)
 +{
 +      if (!service)
 +              return;
 +
 +      if (service->is_internet_connection != internet_connection) {
 +              service->is_internet_connection = internet_connection;
 +
 +              g_get_current_time(&service->modified);
 +              service_save(service);
 +      }
 +}
 +
 +bool connman_service_get_internet_connection(struct connman_service *service)
 +{
 +      if (!service)
 +              return false;
 +
 +      return service->is_internet_connection;
 +}
 +
 +DBusMessage *connman_service_create_dbus_service_reply(DBusMessage *msg,
 +                                                      struct connman_service *service)
 +{
 +      DBusMessage *reply;
 +      DBusMessageIter array, dict;
 +
 +      reply = dbus_message_new_method_return(msg);
 +      if (!reply)
 +              return NULL;
 +
 +      dbus_message_iter_init_append(reply, &array);
 +
 +      if (service)
 +              dbus_message_iter_append_basic(&array, DBUS_TYPE_OBJECT_PATH,
 +                                                              &service->path);
 +
 +      connman_dbus_dict_open(&array, &dict);
 +      if (service)
 +              append_properties(&dict, FALSE, service);
 +      connman_dbus_dict_close(&array, &dict);
 +
 +      return reply;
 +}
 +#endif
 +
  void __connman_service_set_proxy_autoconfig(struct connman_service *service,
                                                        const char *url)
  {
@@@ -5093,18 -2936,6 +5147,18 @@@ const char *connman_service_get_proxy_a
        return NULL;
  }
  
 +#if defined TIZEN_EXT
 +int connman_service_get_ipv6_dns_method(struct connman_service *service)
 +{
 +      if (!service) {
 +              DBG("Service is NULL");
 +              return -1;
 +      }
 +
 +      return service->dns_config_method_ipv6;
 +}
 +#endif
 +
  void __connman_service_set_timeservers(struct connman_service *service,
                                char **timeservers)
  {
@@@ -5232,22 -3063,6 +5286,22 @@@ void __connman_service_set_pac(struct c
        proxy_changed(service);
  }
  
 +#if defined TIZEN_EXT
 +void __connman_service_set_proxy(struct connman_service *service,
 +                                       const char *proxies)
 +{
 +       char **proxies_array = NULL;
 +
 +       g_strfreev(service->proxies);
 +       service->proxies = NULL;
 +
 +       if (proxies != NULL)
 +               proxies_array = g_strsplit(proxies, " ", 0);
 +
 +       service->proxies = proxies_array;
 +}
 +#endif
 +
  void __connman_service_set_identity(struct connman_service *service,
                                        const char *identity)
  {
@@@ -5367,9 -3182,7 +5421,9 @@@ int __connman_service_check_passphrase(
        case CONNMAN_SERVICE_SECURITY_UNKNOWN:
        case CONNMAN_SERVICE_SECURITY_NONE:
        case CONNMAN_SERVICE_SECURITY_WPA:
 +#if !defined TIZEN_EXT
        case CONNMAN_SERVICE_SECURITY_RSN:
 +#endif
  
                DBG("service security '%s' (%d) not handled",
                                security2string(security), security);
                return -EOPNOTSUPP;
  
        case CONNMAN_SERVICE_SECURITY_PSK:
 +#if defined TIZEN_EXT
 +      case CONNMAN_SERVICE_SECURITY_RSN:
 +      /* TO CHECK: We need to check the key length supported by SAE */
 +      case CONNMAN_SERVICE_SECURITY_SAE:
 +#endif
                /* A raw key is always 64 bytes length,
                 * its content is in hex representation.
                 * A PSK key must be between [8..63].
                break;
  
        case CONNMAN_SERVICE_SECURITY_8021X:
 +#if defined TIZEN_EXT
 +      case CONNMAN_SERVICE_SECURITY_OWE:
 +      case CONNMAN_SERVICE_SECURITY_DPP:
 +#endif
                break;
        }
  
@@@ -5430,19 -3234,6 +5484,19 @@@ int __connman_service_set_passphrase(st
                        service->security != CONNMAN_SERVICE_SECURITY_8021X)
                return -EINVAL;
  
 +#if defined TIZEN_EXT
 +      if (service->immutable &&
 +                      service->security != CONNMAN_SERVICE_SECURITY_DPP)
 +              return -EINVAL;
 +      /* The encrypted passphrase is used here
 +       * and validation is done by net-config before being encrypted.
 +       */
 +      err = 0;
 +      if (service->security != CONNMAN_SERVICE_SECURITY_PSK &&
 +                      service->security != CONNMAN_SERVICE_SECURITY_RSN &&
 +                      service->security != CONNMAN_SERVICE_SECURITY_SAE &&
 +                      service->security != CONNMAN_SERVICE_SECURITY_WEP)
 +#endif
        err = __connman_service_check_passphrase(service->security, passphrase);
  
        if (err < 0)
@@@ -5466,28 -3257,6 +5520,28 @@@ const char *__connman_service_get_passp
        return service->passphrase;
  }
  
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +int __connman_service_get_use_eapol(struct connman_service *service)
 +{
 +      if (!service) {
 +              DBG("Service is NULL");
 +              return -1;
 +      }
 +
 +      return service->use_eapol;
 +}
 +
 +int __connman_service_get_connect_reason(struct connman_service *service)
 +{
 +      if (!service) {
 +              DBG("Service is NULL");
 +              return -1;
 +      }
 +
 +      return service->connect_reason;
 +}
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
  static DBusMessage *get_properties(DBusConnection *conn,
                                        DBusMessage *msg, void *user_data)
  {
@@@ -5714,15 -3483,28 +5768,28 @@@ static void do_auto_connect(struct conn
                return;
  
        /*
+        * Only user interaction should get VPN or WIFI connected in failure
+        * state.
+        */
+       if (service->state == CONNMAN_SERVICE_STATE_FAILURE &&
+                               reason != CONNMAN_SERVICE_CONNECT_REASON_USER &&
+                               (service->type == CONNMAN_SERVICE_TYPE_VPN ||
+                               service->type == CONNMAN_SERVICE_TYPE_WIFI))
+               return;
+       /*
+        * Do not use the builtin auto connect, instead rely on the
+        * native auto connect feature of the service.
+        */
+       if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_NATIVE)
+               return;
+       /*
         * Run service auto connect for other than VPN services. Afterwards
         * start also VPN auto connect process.
         */
        if (service->type != CONNMAN_SERVICE_TYPE_VPN)
                __connman_service_auto_connect(reason);
-       /* Only user interaction should get VPN connected in failure state. */
-       else if (service->state == CONNMAN_SERVICE_STATE_FAILURE &&
-                               reason != CONNMAN_SERVICE_CONNECT_REASON_USER)
-               return;
  
        vpn_auto_connect();
  }
@@@ -5801,14 -3583,6 +5868,6 @@@ int __connman_service_reset_ipconfig(st
        return err;
  }
  
- /*
-  * We set the timeout to 1 sec so that we have a chance to get
-  * necessary IPv6 router advertisement messages that might have
-  * DNS data etc.
-  */
- #define ONLINE_CHECK_INITIAL_INTERVAL 1
- #define ONLINE_CHECK_MAX_INTERVAL 12
  void __connman_service_wispr_start(struct connman_service *service,
                                        enum connman_ipconfig_type type)
  {
  
        if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
                service->online_check_interval_ipv4 =
-                                       ONLINE_CHECK_INITIAL_INTERVAL;
+                                       online_check_initial_interval;
        else
                service->online_check_interval_ipv6 =
-                                       ONLINE_CHECK_INITIAL_INTERVAL;
+                                       online_check_initial_interval;
  
        __connman_wispr_start(service, type);
  }
@@@ -5889,10 -3663,6 +5948,10 @@@ static DBusMessage *set_property(DBusCo
                GString *str;
                int index;
                const char *gw;
 +#if defined TIZEN_EXT
 +              enum connman_ipconfig_type ip_type = CONNMAN_IPCONFIG_TYPE_ALL;
 +              DBG("%s", name);
 +#endif
  
                if (__connman_provider_is_immutable(service->provider) ||
                                service->immutable)
                gw = __connman_ipconfig_get_gateway_from_index(index,
                        CONNMAN_IPCONFIG_TYPE_ALL);
  
 +#if !defined TIZEN_EXT
                if (gw && strlen(gw))
                        __connman_service_nameserver_del_routes(service,
                                                CONNMAN_IPCONFIG_TYPE_ALL);
  
 +#endif
                dbus_message_iter_recurse(&value, &entry);
  
 +#if defined TIZEN_EXT
 +              /* IPv4/IPv6 Last DNS config method */
 +              int last_dns_ipv4 = service->dns_config_method_ipv4;
 +              int last_dns_ipv6 = service->dns_config_method_ipv6;
 +              DBG("Last DNS Config Method IPv4: %d IPv6: %d", last_dns_ipv4, last_dns_ipv6);
 +#endif
 +
                while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
                        const char *val;
                        dbus_message_iter_get_basic(&entry, &val);
                        dbus_message_iter_next(&entry);
 +#ifdef TIZEN_EXT
 +                      /* First unpack the DNS Config Method */
 +                      DBG("DNS Config Method: %s", val);
 +                      if((g_strcmp0(val, "ipv4.manual") == 0)) {
 +                              service->dns_config_method_ipv4 =
 +                                      CONNMAN_DNSCONFIG_METHOD_MANUAL;
 +
 +                              if(last_dns_ipv4 != CONNMAN_DNSCONFIG_METHOD_MANUAL) {
 +                                      if(ip_type == CONNMAN_IPCONFIG_TYPE_UNKNOWN)
 +                                              ip_type = CONNMAN_IPCONFIG_TYPE_IPV4;
 +                                      else
 +                                              ip_type = CONNMAN_IPCONFIG_TYPE_ALL;
 +                              }
 +                              continue;
 +                      } else if(g_strcmp0(val, "ipv4.dhcp") == 0) {
 +                              service->dns_config_method_ipv4 =
 +                                      CONNMAN_DNSCONFIG_METHOD_DHCP;
 +                              if(last_dns_ipv4 == CONNMAN_DNSCONFIG_METHOD_MANUAL)
 +                                      ip_type = CONNMAN_IPCONFIG_TYPE_IPV4;
 +
 +                              continue;
 +                      } else if(g_strcmp0(val, "ipv6.manual") == 0) {
 +                              service->dns_config_method_ipv6 =
 +                                      CONNMAN_DNSCONFIG_METHOD_MANUAL;
 +                              if(last_dns_ipv6 != CONNMAN_DNSCONFIG_METHOD_MANUAL) {
 +                                      if(ip_type == CONNMAN_IPCONFIG_TYPE_UNKNOWN)
 +                                              ip_type = CONNMAN_IPCONFIG_TYPE_IPV6;
 +                                      else
 +                                              ip_type = CONNMAN_IPCONFIG_TYPE_ALL;
 +                              }
 +                              continue;
 +                      } else if(g_strcmp0(val, "ipv6.dhcp") == 0) {
 +                              service->dns_config_method_ipv6 =
 +                                      CONNMAN_DNSCONFIG_METHOD_DHCP;
 +                              if(last_dns_ipv6 == CONNMAN_DNSCONFIG_METHOD_MANUAL)
 +                                      ip_type = CONNMAN_IPCONFIG_TYPE_IPV6;
  
 +                              continue;
 +                      }
 +#endif
                        if (!val[0])
                                continue;
  
                                g_string_append(str, val);
                }
  
 +#if defined TIZEN_EXT
 +              if (service->dns_config_method_ipv4 == CONNMAN_DNSCONFIG_METHOD_DHCP &&
 +                      service->dns_config_method_ipv6 == CONNMAN_DNSCONFIG_METHOD_DHCP) {
 +                                      DBG("Both IPv4 and IPv6 DNS Method DHCP");
 +                                      ip_type = CONNMAN_IPCONFIG_TYPE_ALL;
 +              }
 +              if (gw && strlen(gw))
 +                      __connman_service_nameserver_del_routes(service,
 +                                              ip_type);
 +
 +              DBG("%s ip_type: %d nameserver remove all", name, ip_type);
 +              nameserver_remove_all(service, ip_type);
 +#else
                nameserver_remove_all(service, CONNMAN_IPCONFIG_TYPE_ALL);
 +#endif
                g_strfreev(service->nameservers_config);
  
                if (str->len > 0) {
                if (gw && strlen(gw))
                        __connman_service_nameserver_add_routes(service, gw);
  
 +#if defined TIZEN_EXT
 +              DBG("%s ip_type: %d nameserver add all", name, ip_type);
 +              nameserver_add_all(service, ip_type);
 +#else
                nameserver_add_all(service, CONNMAN_IPCONFIG_TYPE_ALL);
 +#endif
                dns_configuration_changed(service);
  
                if (__connman_service_is_connected_state(service,
  
                service_save(service);
                timeservers_configuration_changed(service);
-               if (service == connman_service_get_default())
-                       __connman_timeserver_sync(service);
+               __connman_timeserver_conf_update(service);
  
        } else if (g_str_equal(name, "Domains.Configuration")) {
                DBusMessageIter entry;
                }
  
                service_save(service);
 +#if defined TIZEN_EXT
 +              /* When AP is connected using WPS without SSID then its password needs
 +               * to be saved for autoconnection */
 +      } else if (g_str_equal(name, "Passphrase")) {
 +              char *passphrase;
 +
 +              if (type != DBUS_TYPE_STRING)
 +                      return __connman_error_invalid_arguments(msg);
 +
 +              dbus_message_iter_get_basic(&value, &passphrase);
 +
 +              __connman_service_set_passphrase(service, passphrase);
 +#endif
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      } else if (g_str_equal(name, "EapOverEthernet")) {
 +              int err = connman_service_set_eapol_property(service, &value);
 +              if (err < 0)
 +                      return __connman_error_failed(msg, -err);
 +
 +              service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_USER;
 +              service_save(service);
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
        } else
                return __connman_error_invalid_property(msg);
  
@@@ -6258,10 -3937,8 +6315,10 @@@ static void set_error(struct connman_se
        if (!service->path)
                return;
  
 +#if !defined TIZEN_EXT
        if (!allow_property_changed(service))
                return;
 +#endif
  
        str = error2string(service->error);
  
@@@ -6412,9 -4089,6 +6469,9 @@@ void __connman_service_set_active_sessi
                case CONNMAN_SERVICE_TYPE_GPS:
                case CONNMAN_SERVICE_TYPE_VPN:
                case CONNMAN_SERVICE_TYPE_P2P:
 +#if defined TIZEN_EXT_WIFI_MESH
 +              case CONNMAN_SERVICE_TYPE_MESH:
 +#endif
                        break;
                }
  
@@@ -6447,9 -4121,6 +6504,9 @@@ static void preferred_tech_add_by_type(
                tech_data->preferred_list =
                        g_list_append(tech_data->preferred_list, service);
  
 +#if defined TIZEN_EXT
 +              if (!simplified_log)
 +#endif
                DBG("type %d service %p %s", tech_data->type, service,
                                service->name);
        }
@@@ -6477,17 -4148,6 +6534,17 @@@ static GList *preferred_tech_list_get(v
                                        CONNMAN_SERVICE_CONNECT_REASON_USER) {
                                DBG("service %p name %s is user connected",
                                                service, service->name);
 +#if defined TIZEN_EXT
 +                              /* We can connect to a favorite service like
 +                               * wifi even we have a userconnect for cellular
 +                               * because we have refount for cellular service
 +                               */
 +                              if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
 +                                      break;
 +
 +                              if (service->type == CONNMAN_SERVICE_TYPE_BLUETOOTH)
 +                                      break;
 +#endif
                                return NULL;
                        }
                }
@@@ -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)
@@@ -6549,66 -4209,33 +6608,72 @@@ static bool auto_connect_service(GList 
        bool ignore[MAX_CONNMAN_SERVICE_TYPES] = { };
        bool autoconnecting = false;
        GList *list;
 +#if defined TIZEN_EXT
 +      GSList *wifi_ignore = NULL;
 +#endif
  
        DBG("preferred %d sessions %d reason %s", preferred, active_count,
                reason2string(reason));
  
        ignore[CONNMAN_SERVICE_TYPE_VPN] = true;
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +      /* Don't auto connect wifi if mesh interface is created */
 +      if (connman_mesh_is_interface_created())
 +              ignore[CONNMAN_SERVICE_TYPE_WIFI] = true;
 +#endif
 +
        for (list = services; list; list = list->next) {
                service = list->data;
  
 +#if defined TIZEN_EXT
 +              if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
 +                      int index = connman_network_get_index(service->network);
 +                      if (g_slist_find(wifi_ignore, GINT_TO_POINTER(index)) != NULL)
 +                              continue;
 +              } else
 +#endif
                if (ignore[service->type]) {
                        DBG("service %p type %s ignore", service,
                                __connman_service_type2string(service->type));
                        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)) {
 +#if defined TIZEN_EXT
 +                      if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
 +                              int index = connman_network_get_index(service->network);
 +                              wifi_ignore = g_slist_prepend(wifi_ignore, GINT_TO_POINTER(index));
 +
 +                              autoconnecting = true;
 +                              continue;
 +                      }
 +#else
                        if (autoconnect_no_session_active(service))
                                        return true;
 -
 +#endif
                        ignore[service->type] = true;
                        autoconnecting = true;
  
                        if (preferred)
                               continue;
  
 +#if defined TIZEN_EXT
 +                      DBG("Service is not favorite, autoconnecting %d",
 +                                      autoconnecting);
 +                      g_slist_free(wifi_ignore);
 +#endif
                        return autoconnecting;
                }
  
 +#if defined TIZEN_EXT
 +              DBG("service %p identifier %s roaming %d ignore %d "
 +                              "ipconfig_usable %d autoconnect %d state %d",
 +                              service,
 +                              service->identifier, service->roaming,
 +                              service->ignore, is_ipconfig_usable(service),
 +                              service->autoconnect, service->state);
 +#endif
                if (is_ignore(service) || service->state !=
                                CONNMAN_SERVICE_STATE_IDLE)
                        continue;
 -
 +#if defined TIZEN_EXT
 +              if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
 +#endif
                if (autoconnect_already_connecting(service, autoconnecting)) {
                        DBG("service %p type %s has no users", service,
                                __connman_service_type2string(service->type));
                DBG("service %p %s %s", service, service->name,
                        (preferred) ? "preferred" : reason2string(reason));
  
 +#if defined TIZEN_EXT
 +              __connman_service_connect(service, reason);
 +#else
                if (__connman_service_connect(service, reason) == 0)
                        service_indicate_state(service);
  
                if (autoconnect_no_session_active(service))
                        return true;
 -
 +#endif
 +#if defined TIZEN_EXT
 +              if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
 +                      int index = connman_network_get_index(service->network);
 +                      wifi_ignore = g_slist_prepend(wifi_ignore, GINT_TO_POINTER(index));
 +                      autoconnecting = true;
 +              }
 +#endif
                ignore[service->type] = true;
        }
 -
 +#if defined TIZEN_EXT
 +      g_slist_free(wifi_ignore);
 +#endif
        return autoconnecting;
  }
  
@@@ -6700,21 -4300,6 +6765,21 @@@ static gboolean run_auto_connect(gpoint
        return FALSE;
  }
  
 +#if defined TIZEN_EXT
 +bool __connman_service_get_auto_connect_mode(void)
 +{
 +      return auto_connect_mode;
 +}
 +
 +void __connman_service_set_auto_connect_mode(bool enable)
 +{
 +      DBG("set auto_connect_mode = %d", enable);
 +
 +      if (auto_connect_mode != enable)
 +              auto_connect_mode = enable;
 +}
 +#endif
 +
  void __connman_service_auto_connect(enum connman_service_connect_reason reason)
  {
        DBG("");
        if (autoconnect_id != 0)
                return;
  
 +#if defined TIZEN_EXT
 +      if (auto_connect_mode == FALSE) {
 +              DBG("Currently, not auto connection mode");
 +              return;
 +      }
 +#endif
 +
        if (!__connman_session_policy_autoconnect(reason))
                return;
  
 +#if defined TIZEN_EXT
 +      /* Adding Timeout of 500ms before trying to auto connect.
 +       * This is done because of below scenario
 +       * 1. Device is connected to AP1
 +       * 2. WPS Connection request is initiated for AP2
 +       * 3. Immediately WPS Connection is Cancelled
 +       * When WPS Connection Connection is initiated for AP2 then
 +       * sometimes there is a scenario where connman gets in ASSOCIATED
 +       * state with AP1 due to autoconnect and subsequently the connection
 +       * initiated by AP1 fails and connman service for AP1 comes in
 +       * FAILURE state due to this when connection with AP2 is cancelled
 +       * then autoconnect with AP1 doesn't works because its autoconnection
 +       * is ignored as its last state was FAILURE rather than IDLE */
 +      autoconnect_id = g_timeout_add(500, run_auto_connect,
 +#else
        autoconnect_id = g_idle_add(run_auto_connect,
 +#endif
                                                GUINT_TO_POINTER(reason));
  }
  
@@@ -6983,47 -4545,21 +7048,47 @@@ static DBusMessage *connect_service(DBu
                                        DBusMessage *msg, void *user_data)
  {
        struct connman_service *service = user_data;
 +#if defined TIZEN_EXT
 +      int err = 0;
 +#else
        int index, err = 0;
        GList *list;
 +#endif
 +
 +      DBG("service %p", service);
 +
 +#if defined TIZEN_EXT
 +      /*
 +       * Description: TIZEN implements system global connection management.
 +       */
 +      if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
 +              connman_service_user_pdn_connection_ref(service);
  
 -      DBG("service %p", service);
 +      /*Reset the Disconnect Reason while issue connect request*/
 +      service->disconnect_reason = 0;
 +
 +      /*Reset the association status code while issue connect request*/
 +      service->assoc_status_code = 0;
 +
 +      /* Reset the disconnection_requested while issue connect request*/
 +      connman_service_set_disconnection_requested(service, false);
 +#endif
  
        if (service->pending)
                return __connman_error_in_progress(msg);
  
 +#if !defined TIZEN_EXT
        index = __connman_service_get_index(service);
  
        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;
        }
        if (err == -EINPROGRESS)
                return __connman_error_operation_timeout(msg);
 +#endif
  
        service->ignore = false;
  
@@@ -7061,20 -4596,6 +7126,20 @@@ static DBusMessage *disconnect_service(
  
        DBG("service %p", service);
  
 +#if defined TIZEN_EXT
 +      /*
 +       * Description: TIZEN implements system global connection management.
 +       */
 +      if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR) {
 +              if (connman_service_user_pdn_connection_unref_and_test(service) != TRUE)
 +                      return __connman_error_failed(msg, EISCONN);
 +
 +              if (is_connected(service->state) == TRUE &&
 +                              service == connman_service_get_default_connection())
 +                      return __connman_error_failed(msg, EISCONN);
 +      }
 +#endif
 +
        service->ignore = true;
  
        err = __connman_service_disconnect(service);
        return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
  }
  
 +#if defined TIZEN_EXT
 +static void __connman_service_cleanup_network_8021x(struct connman_service *service)
 +{
 +      if (service == NULL)
 +              return;
 +
 +      DBG("service %p ", service);
 +
 +      connman_network_set_string(service->network, "WiFi.EAP", NULL);
 +      connman_network_set_string(service->network, "WiFi.Identity", NULL);
 +      connman_network_set_string(service->network, "WiFi.CACertFile", NULL);
 +      connman_network_set_string(service->network, "WiFi.ClientCertFile", NULL);
 +      connman_network_set_string(service->network, "WiFi.PrivateKeyFile", NULL);
 +      connman_network_set_string(service->network, "WiFi.PrivateKeyPassphrase", NULL);
 +      connman_network_set_string(service->network, "WiFi.Phase2", NULL);
 +      connman_network_set_string(service->network, "WiFi.AnonymousIdentity", NULL);
 +}
 +static void __connman_service_cleanup_network_dpp(struct connman_service *service)
 +{
 +      if (service == NULL)
 +              return;
 +
 +      DBG("service %p ", service);
 +
 +      connman_network_set_string(service->network, "WiFi.Connector", NULL);
 +      connman_network_set_string(service->network, "WiFi.CSignKey", NULL);
 +      connman_network_set_string(service->network, "WiFi.NetAccessKey", NULL);
 +}
 +#endif
 +
  bool __connman_service_remove(struct connman_service *service)
  {
        if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET ||
                        __connman_provider_is_immutable(service->provider))
                return false;
  
 +#if !defined TIZEN_EXT
        if (!service->favorite && !is_idle(service->state))
                return false;
 +#endif
  
        __connman_service_disconnect(service);
  
        g_free(service->eap);
        service->eap = NULL;
  
 +#if defined TIZEN_EXT
 +      g_free(service->ca_cert_file);
 +      service->ca_cert_file = NULL;
 +
 +      g_free(service->client_cert_file);
 +      service->client_cert_file = NULL;
 +
 +      g_free(service->private_key_file);
 +      service->private_key_file = NULL;
 +
 +      g_free(service->private_key_passphrase);
 +      service->private_key_passphrase = NULL;
 +
 +      g_free(service->phase2);
 +      service->phase2 = NULL;
 +
 +      __connman_service_cleanup_network_8021x(service);
 +
 +      __connman_ipconfig_set_method(service->ipconfig_ipv4, CONNMAN_IPCONFIG_METHOD_DHCP);
 +      __connman_ipconfig_set_method(service->ipconfig_ipv6, CONNMAN_IPCONFIG_METHOD_AUTO);
 +      connman_service_set_proxy(service, NULL, false);
 +
 +      __connman_service_nameserver_clear(service);
 +
 +      g_strfreev(service->nameservers_config);
 +      service->nameservers_config = NULL;
 +
 +      g_free(service->connector);
 +      service->connector = NULL;
 +
 +      g_free(service->c_sign_key);
 +      service->c_sign_key = NULL;
 +
 +      g_free(service->net_access_key);
 +      service->net_access_key = NULL;
 +
 +      __connman_service_cleanup_network_dpp(service);
 +#endif
 +
        service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
  
        __connman_service_set_favorite(service, false);
  
        __connman_ipconfig_ipv6_reset_privacy(service->ipconfig_ipv6);
  
 +#if defined TIZEN_EXT
 +      /* Reset IP Method and DNS Method to DHCP */
 +      __connman_ipconfig_set_method(service->ipconfig_ipv4,
 +                      CONNMAN_IPCONFIG_METHOD_DHCP);
 +      service->dns_config_method_ipv4 = CONNMAN_DNSCONFIG_METHOD_DHCP;
 +      g_strfreev(service->nameservers_config);
 +      service->nameservers_config = NULL;
 +#endif
 +
 +#if defined TIZEN_EXT
 +      __connman_storage_remove_service(service->identifier);
 +#else
        service_save(service);
 +#endif
  
        return true;
  }
@@@ -7329,9 -4766,6 +7394,9 @@@ static void service_append_added_foreac
                append_struct(service, iter);
                g_hash_table_remove(services_notify->add, service->path);
        } else {
 +#if defined TIZEN_EXT
 +              if (!simplified_log)
 +#endif
                DBG("changed %s", service->path);
  
                append_struct_service(iter, NULL, service);
@@@ -7392,27 -4826,22 +7457,22 @@@ static void service_schedule_changed(vo
        services_notify->id = g_timeout_add(100, service_send_changed, NULL);
  }
  
- static DBusMessage *move_service(DBusConnection *conn,
-                                       DBusMessage *msg, void *user_data,
-                                                               bool before)
+ int __connman_service_move(struct connman_service *service,
+                               struct connman_service *target, bool before)
  {
-       struct connman_service *service = user_data;
-       struct connman_service *target;
-       const char *path;
        enum connman_ipconfig_method target4, target6;
        enum connman_ipconfig_method service4, service6;
  
        DBG("service %p", service);
  
-       dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
-                                                       DBUS_TYPE_INVALID);
+       if (!service)
+               return -EINVAL;
  
        if (!service->favorite)
-               return __connman_error_not_supported(msg);
+               return -EOPNOTSUPP;
  
-       target = find_service(path);
        if (!target || !target->favorite || target == service)
-               return __connman_error_invalid_service(msg);
+               return -EINVAL;
  
        if (target->type == CONNMAN_SERVICE_TYPE_VPN) {
                /*
                        connman_info("Cannot move service. "
                                "No routes defined for provider %s",
                                __connman_provider_get_ident(target->provider));
-                       return __connman_error_invalid_service(msg);
+                       return -EINVAL;
                }
  
-               set_split_routing(target, true);
+               __connman_service_set_split_routing(target, true);
        } else
-               set_split_routing(target, false);
+               __connman_service_set_split_routing(target, false);
  
-       set_split_routing(service, false);
+       __connman_service_set_split_routing(service, false);
  
        target4 = __connman_ipconfig_get_method(target->ipconfig_ipv4);
        target6 = __connman_ipconfig_get_method(target->ipconfig_ipv6);
                if (service6 != CONNMAN_IPCONFIG_METHOD_OFF) {
                        if (!check_suitable_state(target->state_ipv6,
                                                        service->state_ipv6))
-                               return __connman_error_invalid_service(msg);
+                               return -EINVAL;
                }
        }
  
                if (service4 != CONNMAN_IPCONFIG_METHOD_OFF) {
                        if (!check_suitable_state(target->state_ipv4,
                                                        service->state_ipv4))
-                               return __connman_error_invalid_service(msg);
+                               return -EINVAL;
                }
        }
  
                if (target6 != CONNMAN_IPCONFIG_METHOD_OFF) {
                        if (!check_suitable_state(target->state_ipv6,
                                                        service->state_ipv6))
-                               return __connman_error_invalid_service(msg);
+                               return -EINVAL;
                }
        }
  
                if (target4 != CONNMAN_IPCONFIG_METHOD_OFF) {
                        if (!check_suitable_state(target->state_ipv4,
                                                        service->state_ipv4))
-                               return __connman_error_invalid_service(msg);
+                               return -EINVAL;
                }
        }
  
  
        service_schedule_changed();
  
+       return 0;
+ }
+ static DBusMessage *move_service(DBusConnection *conn,
+                                       DBusMessage *msg, void *user_data,
+                                                               bool before)
+ {
+       struct connman_service *service = user_data;
+       struct connman_service *target;
+       const char *path;
+       int err;
+       DBG("service %p", service);
+       dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+                                                       DBUS_TYPE_INVALID);
+       target = find_service(path);
+       err = __connman_service_move(service, target, before);
+       switch (err) {
+       case 0:
+               break;
+       case -EINVAL:
+               return __connman_error_invalid_service(msg);
+       case -EOPNOTSUPP:
+               return __connman_error_not_supported(msg);
+       default:
+               connman_warn("unsupported error code %d in move_service()",
+                                                                       err);
+               break;
+       }
        return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
  }
  
@@@ -7525,45 -4987,8 +7618,45 @@@ static DBusMessage *reset_counters(DBus
        return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
  }
  
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +static DBusMessage *is_eapol_enabled(DBusConnection *conn,
 +                                      DBusMessage *msg, void *user_data)
 +{
 +      struct connman_service *service = user_data;
 +      DBG("service: %p path: %s UseEapol: %d", service, service->path, service->use_eapol);
 +
 +      dbus_bool_t eapol_status = service->use_eapol;
 +
 +      DBusMessage *reply = dbus_message_new_method_return(msg);
 +      if (!reply) {
 +              DBG("Failed to initialize reply");
 +              return NULL;
 +      }
 +
 +      dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &eapol_status, DBUS_TYPE_INVALID);
 +      return reply;
 +}
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 +
 +#if defined TIZEN_EXT
 +static DBusMessage *downgrade_service(DBusConnection *conn,
 +                                      DBusMessage *msg, void *user_data)
 +{
 +      struct connman_service *service = user_data;
 +
 +      downgrade_state(service);
 +      __connman_connection_update_gateway();
 +      start_online_check(service, CONNMAN_IPCONFIG_TYPE_IPV4);
 +
 +      return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 +}
 +#endif
 +
  static void service_schedule_added(struct connman_service *service)
  {
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        DBG("service %p", service);
  
        g_hash_table_remove(services_notify->remove, service->path);
@@@ -7590,10 -5015,6 +7683,10 @@@ static void service_schedule_removed(st
  
  static bool allow_property_changed(struct connman_service *service)
  {
 +#if defined TIZEN_EXT
 +      if (service->path == NULL)
 +              return FALSE;
 +#endif
        if (g_hash_table_lookup_extended(services_notify->add, service->path,
                                        NULL, NULL))
                return false;
@@@ -7623,22 -5044,12 +7716,22 @@@ static const GDBusMethodTable service_m
                        GDBUS_ARGS({ "service", "o" }), NULL,
                        move_after) },
        { GDBUS_METHOD("ResetCounters", NULL, NULL, reset_counters) },
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      { GDBUS_METHOD("IsEapolEnabled", NULL, GDBUS_ARGS({ "eapol", "b" }), is_eapol_enabled) },
 +#endif
 +#if defined TIZEN_EXT
 +      { GDBUS_METHOD("Downgrade", NULL, NULL, downgrade_service) },
 +#endif
        { },
  };
  
  static const GDBusSignalTable service_signals[] = {
        { GDBUS_SIGNAL("PropertyChanged",
                        GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
 +#if defined TIZEN_EXT
 +      { GDBUS_SIGNAL("StateChangedProperties",
 +                      GDBUS_ARGS({ "properties", "a{sv}" })) },
 +#endif
        { },
  };
  
@@@ -7727,16 -5138,6 +7820,16 @@@ static void service_free(gpointer user_
        g_free(service->phase2);
        g_free(service->config_file);
        g_free(service->config_entry);
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      g_free(service->pac_file);
 +      g_free(service->phase1);
 +#endif
 +
 +#if defined TIZEN_EXT
 +      g_free(service->connector);
 +      g_free(service->c_sign_key);
 +      g_free(service->net_access_key);
 +#endif
  
        if (service->stats.timer)
                g_timer_destroy(service->stats.timer);
@@@ -7764,9 -5165,6 +7857,9 @@@ static void stats_init(struct connman_s
  
  static void service_initialize(struct connman_service *service)
  {
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        DBG("service %p", service);
  
        service->refcount = 1;
  
        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,224 -5282,65 +7993,269 @@@ 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;
        struct connman_service *service_b = (void *) b;
        enum connman_service_state state_a, state_b;
        bool a_connected, b_connected;
 +#if defined TIZEN_EXT && defined TIZEN_EXT_INS
 +      int score_a;
 +      int score_b;
 +#else /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
        gint strength;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
  
        state_a = service_a->state;
        state_b = service_b->state;
        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;
  
                        return 1;
        }
  
 +#if defined TIZEN_EXT && defined TIZEN_EXT_INS
 +      score_a = calculate_score(service_a);
 +      score_b = calculate_score(service_b);
 +      if (score_b != score_a)
 +              return score_b - score_a;
 +#else /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
        strength = (gint) service_b->strength - (gint) service_a->strength;
        if (strength)
                return strength;
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
  
        return g_strcmp0(service_a->name, service_b->name);
  }
  
 +#if defined TIZEN_EXT && defined TIZEN_EXT_INS
 +static void print_service_sort(gpointer data, gpointer user_data)
 +{
 +      struct connman_service *service = data;
 +
 +      if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
 +              return;
 +
 +      DBG("name[%-20s] total[%2d] last_usr[%2d] last_conn[%2d] "
 +              "freq[%2d] sec[%2d] internet[%2d] strength[%2d]",
 +              service->name, service->ins_score, service->score_last_user_selection,
 +              service->score_last_connected, service->score_frequency,
 +              service->score_security_priority, service->score_internet_connection,
 +              service->score_strength);
 +}
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
 +
  static void service_list_sort(void)
  {
        if (service_list && service_list->next) {
                service_list = g_list_sort(service_list, service_compare);
 +#if defined TIZEN_EXT && defined TIZEN_EXT_INS
 +              g_list_foreach(service_list, print_service_sort, NULL);
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
                service_schedule_changed();
        }
  }
@@@ -8375,53 -5570,6 +8512,53 @@@ void __connman_service_mark_dirty(void
        services_dirty = true;
  }
  
 +#if defined TIZEN_EXT
 +/**
 +  * Returns profile count if there is any connected profiles
 +  * that use same interface
 +  */
 +int __connman_service_get_connected_count_of_iface(
 +                                      struct connman_service *service)
 +{
 +      GList *list;
 +      int count = 0;
 +      int index1 = 0;
 +      int index2 = 0;
 +
 +      DBG("");
 +
 +      index1 = __connman_service_get_index(service);
 +
 +      if (index1 <= 0)
 +              return 0;
 +
 +      for (list = service_list; list; list = list->next) {
 +              struct connman_service *service2 = list->data;
 +
 +              if (service == service2)
 +                      continue;
 +
 +              index2 = __connman_service_get_index(service2);
 +
 +              if (is_connected(service2->state) && index2 > 0 && index1 == index2)
 +                      count++;
 +
 +              index2 = 0;
 +      }
 +
 +      DBG("Interface index %d, count %d", index1, count);
 +
 +      return count;
 +}
 +
 +void __connman_service_set_storage_reload(struct connman_service *service,
 +                                      bool storage_reload)
 +{
 +      if (service != NULL)
 +              service->storage_reload = storage_reload;
 +}
 +#endif
 +
  /**
   * __connman_service_set_favorite_delayed:
   * @service: service structure
@@@ -8434,10 -5582,6 +8571,10 @@@ int __connman_service_set_favorite_dela
                                        bool favorite,
                                        bool delay_ordering)
  {
 +#if defined TIZEN_EXT
 +      if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
 +              return -EIO;
 +#endif
        if (service->hidden)
                return -EOPNOTSUPP;
  
@@@ -8552,28 -5696,6 +8689,28 @@@ void __connman_service_set_string(struc
                service->phase2 = g_strdup(value);
        } else if (g_str_equal(key, "Passphrase"))
                __connman_service_set_passphrase(service, value);
 +#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
 +      else if (g_str_equal(key, "Phase1")) {
 +              g_free(service->phase1);
 +              service->phase1 = g_strdup(value);
 +      } else if (g_str_equal(key, "PacFile")) {
 +              g_free(service->pac_file);
 +              service->pac_file = g_strdup(value);
 +      }
 +#endif
 +#if defined TIZEN_EXT
 +       else if (g_str_equal(key, "Connector")) {
 +              g_free(service->connector);
 +              service->connector = g_strdup(value);
 +       }      else if (g_str_equal(key, "CSignKey")) {
 +              g_free(service->c_sign_key);
 +              service->c_sign_key = g_strdup(value);
 +       }      else if (g_str_equal(key, "NetAccessKey")) {
 +              g_free(service->net_access_key);
 +              service->net_access_key = g_strdup(value);
 +      } else
 +              DBG("Unknown key: %s", key);
 +#endif
  }
  
  void __connman_service_set_search_domains(struct connman_service *service,
@@@ -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();
        }
  }
@@@ -8690,14 -5805,18 +8828,18 @@@ static void request_input_cb(struct con
                goto done;
        }
  
-       if (service->hidden && name_len > 0 && name_len <= 32) {
-               device = connman_network_get_device(service->network);
-               security = connman_network_get_string(service->network,
-                                                       "WiFi.Security");
-               err = __connman_device_request_hidden_scan(device,
-                                               name, name_len,
-                                               identity, passphrase,
-                                               security, user_data);
+       if (service->hidden) {
+               if (name_len > 0 && name_len <= 32) {
+                       device = connman_network_get_device(service->network);
+                       security = connman_network_get_string(service->network,
+                                                               "WiFi.Security");
+                       err = __connman_device_request_hidden_scan(device,
+                                                               name, name_len,
+                                                               identity, passphrase,
+                                                               security, user_data);
+               } else {
+                       err = -EINVAL;
+               }
                if (err < 0)
                        __connman_service_return_error(service, -err,
                                                        user_data);
@@@ -8786,154 -5905,21 +8928,154 @@@ static int service_update_preferred_ord
        tech_array = connman_setting_get_uint_list("PreferredTechnologies");
        if (tech_array) {
  
 -              for (i = 0; tech_array[i] != 0; i += 1) {
 -                      if (default_service->type == tech_array[i])
 -                              return -EALREADY;
 +              for (i = 0; tech_array[i] != 0; i += 1) {
 +                      if (default_service->type == tech_array[i])
 +                              return -EALREADY;
 +
 +                      if (new_service->type == tech_array[i]) {
 +                              switch_default_service(default_service,
 +                                              new_service);
 +                              __connman_connection_update_gateway();
 +                              return 0;
 +                      }
 +              }
 +      }
 +
 +      return -EALREADY;
 +}
 +
 +#if defined TIZEN_EXT
 +static gboolean __connman_service_can_drop(struct connman_service *service)
 +{
 +      if (is_connected(service->state) == TRUE || is_connecting(service->state) == TRUE) {
 +              if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
 +                      return TRUE;
 +              else if (connman_service_is_no_ref_user_pdn_connection(service) == TRUE)
 +                      return TRUE;
 +      }
 +      return FALSE;
 +}
 +
 +static struct connman_device *default_connecting_device = NULL;
 +
 +static void __connman_service_disconnect_default(struct connman_service *service)
 +{
 +      struct connman_device *default_device = NULL;
 +      struct connman_network *network = __connman_service_get_network(service);
 +
 +      if (!network)
 +              return;
 +
 +      if (default_connecting_device == NULL)
 +              return;
 +
 +      default_device = connman_network_get_device(network);
 +
 +      DBG("Disconnecting service %p %s", service, service->path);
 +      DBG("Disconnecting device %p %p %s",
 +                      default_connecting_device,
 +                      default_device,
 +                      connman_device_get_string(default_device, "Name"));
 +
 +      if (default_connecting_device == default_device)
 +              default_connecting_device = NULL;
 +}
 +
 +#if defined TIZEN_MAINTAIN_ONLINE
 +static void __connman_service_connect_default(struct connman_service *current,
 +                                                                enum connman_service_state old_state)
 +#else
 +static void __connman_service_connect_default(struct connman_service *current)
 +#endif
 +{
 +      int err;
 +      GList *list;
 +      bool default_internet;
 +      struct connman_service *service;
 +      struct connman_service *default_service = NULL;
 +      struct connman_device *default_device = NULL;
 +
 +      if (current->type == CONNMAN_SERVICE_TYPE_CELLULAR) {
 +              switch (current->state) {
 +              case CONNMAN_SERVICE_STATE_UNKNOWN:
 +              case CONNMAN_SERVICE_STATE_ASSOCIATION:
 +              case CONNMAN_SERVICE_STATE_CONFIGURATION:
 +                      return;
 +              default:
 +                      break;
 +              }
 +
 +              if (default_connecting_device &&
 +                              __connman_service_is_internet_profile(current) == TRUE) {
 +                      if (current->network == NULL)
 +                              return;
 +
 +                      default_device = connman_network_get_device(current->network);
 +                      if (default_connecting_device == default_device) {
 +                              DBG("Cellular service[%s]  %p %s",
 +                                              state2string(current->state), current, current->path);
 +                              DBG("Cellular device %p %p %s",
 +                                              default_connecting_device, default_device,
 +                                              connman_device_get_string(default_device, "Name"));
 +
 +                              default_connecting_device = NULL;
 +                      }
 +              }
 +
 +              return;
 +#if defined TIZEN_MAINTAIN_ONLINE
 +      } else if (current->state == CONNMAN_SERVICE_STATE_READY &&
 +                         old_state == CONNMAN_SERVICE_STATE_ONLINE) {
 +              DBG("Device is downgraded: online --> ready");
 +#endif
 +      } else if (is_connected(current->state) == TRUE || is_connecting(current->state) == TRUE)
 +              return;
 +
 +      /* Always-on: keep default cellular connection as possible */
 +      for (list = service_list; list; list = list->next) {
 +              service = list->data;
 +
 +              if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR ||
 +                              __connman_service_is_internet_profile(service) != TRUE ||
 +                              service->network == NULL) {
 +                      continue;
 +              }
 +
 +              default_internet =
 +                              connman_network_get_bool(service->network, "DefaultInternet");
 +
 +              DBG("service: %p %s %s %s (default: %d)", service, service->name,
 +                              __connman_service_type2string(service->type),
 +                              state2string(service->state), default_internet);
 +
 +              if (default_internet) {
 +                      default_service = service;
 +                      if (is_connected(default_service->state) == TRUE ||
 +                                      is_connecting(default_service->state) == TRUE)
 +                              return;
  
 -                      if (new_service->type == tech_array[i]) {
 -                              switch_default_service(default_service,
 -                                              new_service);
 -                              __connman_connection_update_gateway();
 -                              return 0;
 +                      default_device = connman_network_get_device(default_service->network);
 +                      if (default_connecting_device == default_device) {
 +                              DBG("Device is connecting (%p)", default_connecting_device);
 +                              return;
                        }
 +
 +                      default_connecting_device = default_device;
 +                      default_service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_USER;
 +
 +                      err = __connman_network_connect(default_service->network);
 +                      DBG("Connecting default service %p %s [%d]",
 +                                      default_service, default_service->path, err);
 +                      DBG("Connecting device %p %s", default_connecting_device,
 +                                      connman_device_get_string(default_connecting_device, "Name"));
 +                      if (err < 0 && err != -EINPROGRESS) {
 +                              default_connecting_device = NULL;
 +                      } else
 +                              break;
                }
        }
 -
 -      return -EALREADY;
  }
 +#endif
  
  static void single_connected_tech(struct connman_service *allowed)
  {
  
        DBG("keeping %p %s", allowed, allowed->path);
  
 +#if defined TIZEN_EXT
 +      if (!allowed || allowed->type == CONNMAN_SERVICE_TYPE_CELLULAR)
 +              return;
 +#endif
 +
        for (iter = service_list; iter; iter = iter->next) {
                service = iter->data;
  
 +#if defined TIZEN_EXT
 +              if (service != allowed && service->type != allowed->type &&
 +                              __connman_service_can_drop(service) == TRUE)
 +#else
                if (!is_connected(service->state))
                        break;
  
                if (service == allowed)
                        continue;
 +#endif
  
                services = g_slist_prepend(services, service);
        }
                service = list->data;
  
                DBG("disconnecting %p %s", service, service->path);
 +#if defined TIZEN_EXT
 +              __connman_service_disconnect_default(service);
 +#endif
                __connman_service_disconnect(service);
        }
  
        g_slist_free(services);
  }
  
 +#if defined TIZEN_EXT
 +static void set_priority_connected_service(void)
 +{
 +      struct connman_service *service;
 +      GList *list;
 +
 +      for (list = service_list; list; list = list->next) {
 +              service = list->data;
 +
 +              if (is_connected(service->state) == FALSE)
 +                      service->order = 5;
 +              else
 +#if defined TIZEN_MAINTAIN_ONLINE
 +              {
 +                      if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
 +                              service->state == CONNMAN_SERVICE_STATE_ONLINE)
 +                              service->order = 6;
 +                      else if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
 +                              service->order = 6;
 +                      else
 +                              service->order = 5;
 +              }
 +#else
 +                      service->order = 6;
 +#endif
 +      }
 +}
 +#endif
 +
  static const char *get_dbus_sender(struct connman_service *service)
  {
        if (!service->pending)
@@@ -9054,14 -5998,6 +9196,14 @@@ static int service_indicate_state(struc
                searchdomain_remove_all(service);
  
        service->state = new_state;
 +#if defined TIZEN_EXT
 +      if (!is_connected(old_state) && is_connected(new_state))
 +              connman_device_send_connected_signal(
 +                              connman_network_get_device(service->network), true);
 +      else if (is_connected(old_state) && !is_connected(new_state))
 +              connman_device_send_connected_signal(
 +                              connman_network_get_device(service->network), false);
 +#endif
        state_changed(service);
  
        if (!is_connected(old_state) && is_connected(new_state))
                        __connman_ipconfig_disable_ipv6(
                                                service->ipconfig_ipv6);
  
 +#if !defined TIZEN_MAINTAIN_ONLINE
                if (connman_setting_get_bool("SingleConnectedTechnology"))
                        single_connected_tech(service);
                else if (service->type != CONNMAN_SERVICE_TYPE_VPN)
                        vpn_auto_connect();
 +#else
 +              if (service->type != CONNMAN_SERVICE_TYPE_VPN)
 +                      vpn_auto_connect();
 +#endif
 +
 +#if defined TIZEN_EXT
 +              if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
 +                      set_priority_connected_service();
 +#endif
  
                break;
  
        case CONNMAN_SERVICE_STATE_ONLINE:
 +#if defined TIZEN_MAINTAIN_ONLINE
 +#if defined TIZEN_EXT
 +              if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
 +                      set_priority_connected_service();
 +#endif
 +
 +              if (connman_setting_get_bool("SingleConnectedTechnology"))
 +                      single_connected_tech(service);
 +#endif
  
 +#if defined TIZEN_EXT
 +              if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
 +                      connman_service_set_internet_connection(service, true);
 +#endif
                break;
  
        case CONNMAN_SERVICE_STATE_DISCONNECT:
  
                __connman_wpad_stop(service);
  
 +#if defined TIZEN_EXT
 +              /**
 +               * Skip the functions if there is any connected profiles
 +               * that use same interface
 +               */
 +              if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR ||
 +                      __connman_service_get_connected_count_of_iface(
 +                                                      service) <= 0) {
 +#endif
                domain_changed(service);
                proxy_changed(service);
 +#if defined TIZEN_EXT
 +              }
 +#endif
  
                /*
                 * Previous services which are connected and which states
                break;
  
        case CONNMAN_SERVICE_STATE_FAILURE:
 +#if defined TIZEN_EXT
 +              if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
 +                      service->order = 5;
 +              __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
 +#endif
                if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER) {
                        connman_agent_report_error(service, service->path,
                                                error2string(service->error),
                                                report_error_cb,
                                                get_dbus_sender(service),
                                                NULL);
+                       goto notifier;
                }
                service_complete(service);
                break;
  
        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 &&
@@@ -9329,23 -6170,6 +9473,23 @@@ int __connman_service_indicate_error(st
  
        set_error(service, error);
  
 +/* default internet service: fix not cleared if pdp activation*/
 +#if defined TIZEN_EXT
 +              /*
 +               * If connection failed for default service(DefaultInternet),
 +               * default_connecting_device should be cleared.
 +               */
 +              if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
 +                              service->error == CONNMAN_SERVICE_ERROR_CONNECT_FAILED)
 +                      __connman_service_disconnect_default(service);
 +
 +              if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
 +                              service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY) {
 +                      g_free(service->passphrase);
 +                      service->passphrase = NULL;
 +              }
 +#endif
 +
        __connman_service_ipconfig_indicate_state(service,
                                                CONNMAN_SERVICE_STATE_FAILURE,
                                                CONNMAN_IPCONFIG_TYPE_IPV4);
@@@ -9420,15 -6244,6 +9564,15 @@@ enum connman_service_state __connman_se
        return CONNMAN_SERVICE_STATE_UNKNOWN;
  }
  
 +#if defined TIZEN_EXT
 +void connman_check_proxy_setup_and_wispr_start(struct connman_service *service){
 +
 +      DBG("check the proxy and start wispr");
 +      check_proxy_setup(service);
 +      return;
 +}
 +#endif
 +
  /*
   * How many networks are connected at the same time. If more than 1,
   * then set the rp_filter setting properly (loose mode routing) so that network
@@@ -9499,13 -6314,7 +9643,13 @@@ static gboolean redo_wispr_ipv4(gpointe
  {
        struct connman_service *service = user_data;
  
 +#if defined TIZEN_MAINTAIN_ONLINE
 +      DBG("");
 +
 +      __connman_wispr_start(service, CONNMAN_IPCONFIG_TYPE_IPV4);
 +#else
        redo_wispr(service, CONNMAN_IPCONFIG_TYPE_IPV4);
 +#endif
  
        return FALSE;
  }
@@@ -9519,11 -6328,13 +9663,13 @@@ static gboolean redo_wispr_ipv6(gpointe
        return FALSE;
  }
  
- int __connman_service_online_check_failed(struct connman_service *service,
-                                       enum connman_ipconfig_type type)
+ void __connman_service_online_check(struct connman_service *service,
+                                       enum connman_ipconfig_type type,
+                                       bool success)
  {
        GSourceFunc redo_func;
-       int *interval;
+       unsigned int *interval;
+       enum connman_service_state current_state;
  
        if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
                interval = &service->online_check_interval_ipv4;
                redo_func = redo_wispr_ipv6;
        }
  
+       if(!enable_online_to_ready_transition)
+               goto redo_func;
+       if (success) {
+               *interval = online_check_max_interval;
+       } else {
+               current_state = service->state;
+               downgrade_state(service);
+               if (current_state != service->state)
+                       *interval = online_check_initial_interval;
+               if (service != connman_service_get_default()) {
+                       return;
+               }
+       }
+ redo_func:
        DBG("service %p type %s interval %d", service,
                __connman_ipconfig_type2string(type), *interval);
  
                                redo_func, connman_service_ref(service));
  
        /* Increment the interval for the next time, set a maximum timeout of
-        * ONLINE_CHECK_MAX_INTERVAL * ONLINE_CHECK_MAX_INTERVAL seconds.
+        * online_check_max_interval seconds * online_check_max_interval seconds.
         */
-       if (*interval < ONLINE_CHECK_MAX_INTERVAL)
+       if (*interval < online_check_max_interval)
                (*interval)++;
-       return EAGAIN;
  }
  
  int __connman_service_ipconfig_indicate_state(struct connman_service *service,
                        connman_warn("ipconfig state %d ipconfig method %d",
                                new_state, method);
  
 +#if defined TIZEN_EXT
 +              if (old_state != CONNMAN_SERVICE_STATE_READY &&
 +                              old_state != CONNMAN_SERVICE_STATE_ONLINE)
 +#endif
                new_state = CONNMAN_SERVICE_STATE_IDLE;
                break;
  
        if (old_state == new_state)
                return -EALREADY;
  
 +#if defined TIZEN_EXT
 +      __sync_synchronize();
 +      if (service->user_pdn_connection_refcount > 0 &&
 +                      service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
 +              if (new_state == CONNMAN_SERVICE_STATE_FAILURE ||
 +                              new_state == CONNMAN_SERVICE_STATE_DISCONNECT ||
 +                              new_state == CONNMAN_SERVICE_STATE_IDLE) {
 +                      service->user_pdn_connection_refcount = 0;
 +                      __sync_synchronize();
 +              }
 +#endif
 +
        DBG("service %p (%s) old state %d (%s) new state %d (%s) type %d (%s)",
                service, service ? service->identifier : NULL,
                old_state, state2string(old_state),
        case CONNMAN_SERVICE_STATE_CONFIGURATION:
                break;
        case CONNMAN_SERVICE_STATE_READY:
 +#if defined TIZEN_EXT
 +              if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
 +                              __connman_service_is_internet_profile(service) != TRUE) {
 +                      if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
 +                              service_rp_filter(service, TRUE);
 +
 +                      break;
 +              }
 +#endif
 +              if (connman_setting_get_bool("EnableOnlineCheck"))
 +                      if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
 +#if !defined TIZEN_EXT
 +                              check_proxy_setup(service);
 +#endif
 +#if defined TIZEN_MAINTAIN_ONLINE
 +/*                            if (old_state == CONNMAN_SERVICE_STATE_ONLINE) */
 +                                      check_proxy_setup(service);
 +#endif
 +                      } else {
 +                              __connman_service_wispr_start(service, type);
 +                      }
 +              else
 +                      connman_info("Online check disabled. "
 +                              "Default service remains in READY state.");
                if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
                        service_rp_filter(service, true);
                set_mdns(service, service->mdns_config);
  
        __connman_timeserver_sync(service);
  
 +#if defined TIZEN_EXT
 +      int ret = service_indicate_state(service);
 +      /*Sent the Ready changed signal again in case IPv4 IP set
 +        after IPv6 IP set*/
 +
 +      if(ret == -EALREADY && type == CONNMAN_IPCONFIG_TYPE_IPV4
 +                      && new_state == CONNMAN_SERVICE_STATE_READY) {
 +              DBG("Notify IPv4 state new/old %d/%d", new_state,old_state);
 +              state_changed(service);
 +      }
 +
 +      return ret;
 +#endif
        return service_indicate_state(service);
  }
  
@@@ -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;
        if (service->hidden)
                return -EPERM;
  
 +#if defined TIZEN_EXT
 +      GList *list;
 +      int index;
 +
 +      index = __connman_service_get_index(service);
 +
 +      for (list = service_list; list; list = list->next) {
 +              struct connman_service *temp = list->data;
 +
 +              if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
 +                      break;
 +
 +              if (!is_connecting(temp->state) && !is_connected(temp->state))
 +                      break;
 +
 +              if (service == temp)
 +                      continue;
 +
 +              if (service->type != temp->type)
 +                      continue;
 +
 +              if (__connman_service_get_index(temp) == index &&
 +                              __connman_service_disconnect(temp) == -EINPROGRESS)
 +                      return -EINPROGRESS;
 +      }
 +#endif
 +
        switch (service->type) {
        case CONNMAN_SERVICE_TYPE_UNKNOWN:
        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
                return -EINVAL;
        case CONNMAN_SERVICE_TYPE_ETHERNET:
        case CONNMAN_SERVICE_TYPE_GADGET:
                switch (service->security) {
                case CONNMAN_SERVICE_SECURITY_UNKNOWN:
                case CONNMAN_SERVICE_SECURITY_NONE:
 +#if defined TIZEN_EXT
 +              case CONNMAN_SERVICE_SECURITY_OWE:
 +#endif
                        break;
                case CONNMAN_SERVICE_SECURITY_WEP:
                case CONNMAN_SERVICE_SECURITY_PSK:
                case CONNMAN_SERVICE_SECURITY_WPA:
                case CONNMAN_SERVICE_SECURITY_RSN:
 +#if defined TIZEN_EXT
 +              case CONNMAN_SERVICE_SECURITY_SAE:
 +#endif
                        if (service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY)
                                return -ENOKEY;
  
                        }
                        break;
  
 +#if defined TIZEN_EXT
 +              case CONNMAN_SERVICE_SECURITY_DPP:
 +                      if (has_valid_configuration_object(service) &&
 +                                      !service->network)
 +                              return -EINVAL;
 +                      break;
 +#endif
                case CONNMAN_SERVICE_SECURITY_8021X:
                        if (!service->eap) {
                                connman_warn("EAP type has not been found. "
                                return -EINVAL;
                        }
  
 +#if defined TIZEN_EXT
 +                      /*
 +                       * never request credentials if using EAP-TLS, EAP-SIM
 +                       * or EAP-AKA (EAP-TLS, EAP-SIM and EAP-AKA networks
 +                       * need to be fully provisioned)
 +                       */
 +                      DBG("service eap: %s", service->eap);
 +                      if (g_str_equal(service->eap, "tls") ||
 +                              g_str_equal(service->eap, "sim") ||
 +                              g_str_equal(service->eap, "aka") ||
 +                              g_str_equal(service->eap, "aka'") ||
 +                              g_str_equal(service->eap, "pwd") ||
 +                              g_str_equal(service->eap, "fast"))
 +                              break;
 +#else
                        /*
                         * never request credentials if using EAP-TLS
                         * (EAP-TLS networks need to be fully provisioned)
                        if (g_str_equal(service->eap, "tls"))
                                break;
  
 +#endif
                        /*
                         * Return -ENOKEY if either identity or passphrase is
                         * missing. Agent provided credentials can be used as
                case CONNMAN_SERVICE_SECURITY_PSK:
                case CONNMAN_SERVICE_SECURITY_WPA:
                case CONNMAN_SERVICE_SECURITY_RSN:
 +#if defined TIZEN_EXT
 +              case CONNMAN_SERVICE_SECURITY_SAE:
 +              case CONNMAN_SERVICE_SECURITY_OWE:
 +                      break;
 +              case CONNMAN_SERVICE_SECURITY_DPP:
 +                      prepare_dpp(service);
 +#endif
                        break;
                case CONNMAN_SERVICE_SECURITY_8021X:
                        prepare_8021x(service);
@@@ -10039,9 -6711,6 +10199,9 @@@ int __connman_service_connect(struct co
        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
                return -EINVAL;
  
        case CONNMAN_SERVICE_TYPE_ETHERNET:
  
        __connman_service_clear_error(service);
  
+       if (service->network && service->autoconnect &&
+                       __connman_network_native_autoconnect(service->network)) {
+               DBG("service %p switch connecting reason to native", service);
+               reason = CONNMAN_SERVICE_CONNECT_REASON_NATIVE;
+       }
        err = service_connect(service);
  
        DBG("service %p err %d", service, err);
  
        service->connect_reason = reason;
 +#if defined TIZEN_EXT
 +      connect_reason_changed(service);
 +#endif
  
        if (err >= 0)
                return 0;
@@@ -10147,14 -6819,6 +10313,14 @@@ int __connman_service_disconnect(struc
                __connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv6,
                                                        NULL);
  
 +#if defined TIZEN_EXT
 +      /**
 +        * Skip the functions If there is any connected profiles
 +        * that use same interface
 +        */
 +      if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR ||
 +              __connman_service_get_connected_count_of_iface(service) <= 0) {
 +#endif
        __connman_ipconfig_address_remove(service->ipconfig_ipv4);
        settings_changed(service, service->ipconfig_ipv4);
  
  
        __connman_ipconfig_disable(service->ipconfig_ipv4);
        __connman_ipconfig_disable(service->ipconfig_ipv6);
 +#if defined TIZEN_EXT
 +      }
 +#endif
  
        return err;
  }
  
 +int __connman_service_disconnect_all(void)
 +{
 +      struct connman_service *service;
 +      GSList *services = NULL, *list;
 +      GList *iter;
 +
 +      DBG("");
 +
 +      for (iter = service_list; iter; iter = iter->next) {
 +              service = iter->data;
 +
 +              if (!is_connected(service->state))
 +                      break;
 +
 +              services = g_slist_prepend(services, service);
 +      }
 +
 +      for (list = services; list; list = list->next) {
 +              struct connman_service *service = list->data;
 +
 +              service->ignore = true;
 +
 +              __connman_service_disconnect(service);
 +      }
 +
 +      g_slist_free(services);
 +
 +      return 0;
 +}
 +
  /**
   * lookup_by_identifier:
   * @identifier: service identifier
@@@ -10290,9 -6921,7 +10456,9 @@@ static struct connman_service *service_
        service = connman_service_create();
        if (!service)
                return NULL;
 -
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        DBG("service %p", service);
  
        service->identifier = g_strdup(identifier);
  
  static int service_register(struct connman_service *service)
  {
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
        DBG("service %p", service);
  
        if (service->path)
  
        DBG("path %s", service->path);
  
 +#if defined TIZEN_EXT
 +      int ret;
 +      service_load(service);
 +      ret = service_ext_load(service);
 +      if (ret == -ERANGE)
 +              service_ext_save(service);
 +      ret = __connman_config_provision_service(service);
 +      if (ret < 0 && !simplified_log)
 +              DBG("Failed to provision service");
 +#else
 +      if (__connman_config_provision_service(service) < 0)
 +              service_load(service);
 +#endif
 +
        g_dbus_register_interface(connection, service->path,
                                        CONNMAN_SERVICE_INTERFACE,
                                        service_methods, service_signals,
                                                        NULL, service, NULL);
  
+       if (__connman_config_provision_service(service) < 0)
+               service_load(service);
        service_list_sort();
  
        __connman_connection_update_gateway();
@@@ -10392,9 -7007,6 +10561,9 @@@ static void service_ip_bound(struct con
        struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
        enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
        enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
 +#if defined TIZEN_EXT
 +      int err;
 +#endif
  
        DBG("%s ip bound", ifname);
  
  
        if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
                        method == CONNMAN_IPCONFIG_METHOD_AUTO)
 +#if defined TIZEN_EXT
 +      {
 +              err = __connman_ipconfig_gateway_add(ipconfig, service);
 +
 +              if(err < 0)
 +                      DBG("Failed to add gateway");
 +      }
 +#else
                __connman_service_ipconfig_indicate_state(service,
                                                CONNMAN_SERVICE_STATE_READY,
                                                CONNMAN_IPCONFIG_TYPE_IPV6);
 +#endif
  
        settings_changed(service, ipconfig);
        address_updated(service, type);
@@@ -10681,36 -7284,10 +10850,36 @@@ static enum connman_service_security co
                return CONNMAN_SERVICE_SECURITY_WPA;
        else if (g_str_equal(security, "rsn"))
                return CONNMAN_SERVICE_SECURITY_RSN;
 +#if defined TIZEN_EXT
 +      else if (g_str_equal(security, "sae"))
 +              return CONNMAN_SERVICE_SECURITY_SAE;
 +      else if (g_str_equal(security, "owe"))
 +              return CONNMAN_SERVICE_SECURITY_OWE;
 +      else if (g_str_equal(security, "dpp"))
 +              return CONNMAN_SERVICE_SECURITY_DPP;
 +      else if (g_str_equal(security, "ft_psk") == TRUE)
 +              return CONNMAN_SERVICE_SECURITY_PSK;
 +      else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
 +              return CONNMAN_SERVICE_SECURITY_8021X;
 +#endif
        else
                return CONNMAN_SERVICE_SECURITY_UNKNOWN;
  }
  
 +#if defined TIZEN_EXT
 +int check_passphrase_ext(struct connman_network *network,
 +                                      const char *passphrase)
 +{
 +      const char *str;
 +      enum connman_service_security security;
 +
 +      str = connman_network_get_string(network, "WiFi.Security");
 +      security = convert_wifi_security(str);
 +
 +      return __connman_service_check_passphrase(security, passphrase);
 +}
 +#endif
 +
  static void update_wps_values(struct connman_service *service,
                                struct connman_network *network)
  {
@@@ -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
  struct connman_service * __connman_service_create_from_network(struct connman_network *network)
  {
        struct connman_service *service;
-       struct connman_device *device;
        const char *ident, *group;
        char *name;
        unsigned int *auto_connect_types, *favorite_types;
        service_register(service);
        service_schedule_added(service);
  
-       if (service->favorite) {
-               device = connman_network_get_device(service->network);
-               if (device && !connman_device_get_scanning(device,
-                                               CONNMAN_SERVICE_TYPE_UNKNOWN)) {
-                       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
-       }
+       trigger_autoconnect(service);
  
        __connman_notifier_service_add(service, service->name);
  
        return service;
  }
  
 +#if defined TIZEN_EXT
 +void __connman_service_notify_strength_changed(struct connman_network *network)
 +{
 +      struct connman_service *service;
 +      uint8_t strength = 0;
 +
 +      service = connman_service_lookup_from_network(network);
 +      if (!service)
 +              return;
 +
 +      if (!service->network)
 +              return;
 +
 +      strength = connman_network_get_strength(service->network);
 +      if (strength == service->strength)
 +              return;
 +
 +      service->strength = strength;
 +      if (!simplified_log)
 +              DBG("Strength %d", strength);
 +      strength_changed(service);
 +      service_list_sort();
 +}
 +#endif
 +
  void __connman_service_update_from_network(struct connman_network *network)
  {
        bool need_sort = false;
        bool roaming;
        const char *name;
        bool stats_enable;
 +#if defined TIZEN_EXT
 +      bool need_save = false;
 +#endif
  
        service = connman_service_lookup_from_network(network);
        if (!service)
        if (!service->network)
                return;
  
 +#if defined TIZEN_EXT
 +      if (service->storage_reload) {
 +              service_load(service);
 +              __connman_service_set_storage_reload(service, false);
 +      }
 +#endif
 +
        name = connman_network_get_string(service->network, "Name");
        if (g_strcmp0(service->name, name) != 0) {
                g_free(service->name);
@@@ -11018,16 -7548,6 +11200,16 @@@ roaming
        roaming_changed(service);
  
  sorting:
 +#if defined TIZEN_EXT
 +      need_save |= update_last_connected_bssid(service);
 +      need_save |= update_assoc_reject(service);
 +      if (need_save) {
 +              g_get_current_time(&service->modified);
 +              service_ext_save(service);
 +              need_sort = true;
 +      }
 +#endif
 +
        if (need_sort) {
                service_list_sort();
        }
@@@ -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;
  
        remove_unprovisioned_services();
  
 +#if defined TIZEN_EXT && defined TIZEN_EXT_INS
 +      ins_setting_init();
 +#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
 +
        return 0;
  }
  
diff --combined src/session.c
@@@ -195,9 -195,6 +195,9 @@@ static char *service2bearer(enum connma
        case CONNMAN_SERVICE_TYPE_GPS:
        case CONNMAN_SERVICE_TYPE_P2P:
        case CONNMAN_SERVICE_TYPE_UNKNOWN:
 +#if defined TIZEN_EXT_WIFI_MESH
 +      case CONNMAN_SERVICE_TYPE_MESH:
 +#endif
                return "";
        }
  
@@@ -1756,16 -1753,8 +1756,16 @@@ static bool session_match_service(struc
                service_type = connman_service_get_type(service);
                ifname = connman_service_get_interface(service);
  
 +
 +#if defined TIZEN_EXT
 +              if (bearer_type == current_service_type) {
 +                      g_free(ifname);
 +                      return false;
 +              }
 +#else
                if (bearer_type == current_service_type)
                        return false;
 +#endif
  
                if (bearer_type == service_type &&
                        (session->info->config.allowed_interface == NULL ||
@@@ -1815,7 -1804,7 +1815,7 @@@ static void session_activate(struct con
                struct connman_service *service;
                struct connman_service_info *info;
                GSList *service_list = NULL;
-               enum connman_service_state state = CONNMAN_SESSION_STATE_DISCONNECTED;
+               enum connman_service_state state = CONNMAN_SERVICE_STATE_DISCONNECT;
  
                g_hash_table_iter_init(&iter, service_hash);
  
diff --combined src/shared/util.c
index 73c24ae,bda2d2b..bda2d2b
mode 100755,100644..100755
@@@ -28,6 -28,7 +28,7 @@@
  #include <stdio.h>
  #include <ctype.h>
  #include <stdarg.h>
+ #include <string.h>
  
  #include "src/shared/util.h"
  
diff --combined src/technology.c
  
  #include <errno.h>
  #include <string.h>
 +#if defined TIZEN_EXT
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <net/if.h>
 +#endif
  
  #include <gdbus.h>
  
@@@ -48,19 -43,6 +48,19 @@@ static GHashTable *rfkill_list
  
  static bool global_offlinemode;
  
 +#if defined TIZEN_EXT
 +struct connman_scan_pending {
 +      char *ifname;
 +      connman_scan_type_e scan_type;
 +      DBusMessage *msg;
 +};
 +
 +struct connman_bssid_pending {
 +      char *ifname;
 +      unsigned char bssid[6];
 +};
 +#endif
 +
  struct connman_rfkill {
        unsigned int index;
        enum connman_service_type type;
@@@ -98,15 -80,6 +98,15 @@@ struct connman_technology 
        bool softblocked;
        bool hardblocked;
        bool dbus_registered;
 +#if defined TIZEN_EXT
 +      char **enabled_devices;
 +      unsigned int mac_policy;
 +      unsigned int preassoc_mac_policy;
 +      unsigned int random_mac_lifetime;
 +#endif
 +#if defined TIZEN_EXT_WIFI_MESH
 +      DBusMessage *mesh_dbus_msg;
 +#endif
  };
  
  static GSList *driver_list = NULL;
@@@ -177,10 -150,6 +177,10 @@@ static const char *get_name(enum connma
                return "Cellular";
        case CONNMAN_SERVICE_TYPE_P2P:
                return "P2P";
 +#if defined TIZEN_EXT_WIFI_MESH
 +      case CONNMAN_SERVICE_TYPE_MESH:
 +              return "Mesh";
 +#endif
        }
  
        return NULL;
@@@ -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);
  
@@@ -421,18 -379,6 +423,18 @@@ bool connman_technology_get_wifi_tether
        return true;
  }
  
 +#if defined TIZEN_EXT
 +const char *connman_techonology_get_path(enum connman_service_type type)
 +{
 +      struct connman_technology *technology = technology_find(type);
 +
 +      if (!technology)
 +              return NULL;
 +
 +      return technology->path;
 +}
 +#endif
 +
  static void free_rfkill(gpointer data)
  {
        struct connman_rfkill *rfkill = data;
@@@ -446,6 -392,7 +448,7 @@@ static void technology_load(struct conn
        gchar *identifier;
        GError *error = NULL;
        bool enable, need_saving = false;
+       char *enc;
  
        DBG("technology %p", technology);
  
        if (!identifier)
                goto done;
  
 +#ifdef TIZEN_EXT
 +      gsize length;
 +      technology->enabled_devices = g_key_file_get_string_list(keyfile,
 +                      identifier, "Enable.Devices", &length, NULL);
 +      if (technology->enabled_devices && length == 0) {
 +              g_strfreev(technology->enabled_devices);
 +              technology->enabled_devices = NULL;
 +      }
 +#endif
 +
        enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error);
        if (!error)
                technology->enable_persistent = enable;
        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);
  
@@@ -598,74 -509,6 +602,74 @@@ static bool connman_technology_load_off
        return offlinemode;
  }
  
 +#if defined TIZEN_EXT
 +static void append_devices(DBusMessageIter *iter, void *user_data)
 +{
 +      GSList *list;
 +      dbus_bool_t val;
 +      struct connman_technology *technology = user_data;
 +
 +      for (list = technology->device_list; list; list = list->next) {
 +              struct connman_device *device = list->data;
 +
 +              const char *str = connman_device_get_string(device, "Interface");
 +              struct connman_network *network = connman_device_get_default_network(device);
 +              struct connman_service *service = connman_service_lookup_from_network(network);
 +
 +              connman_dbus_dict_append_basic(iter, "Ifname",
 +                              DBUS_TYPE_STRING, &str);
 +
 +              val = connman_device_get_powered(device);
 +              connman_dbus_dict_append_basic(iter, "Powered",
 +                              DBUS_TYPE_BOOLEAN, &val);
 +
 +              if (__connman_service_is_connected_state(service, CONNMAN_IPCONFIG_TYPE_IPV4) ||
 +                              __connman_service_is_connected_state(service, CONNMAN_IPCONFIG_TYPE_IPV6))
 +                      val = TRUE;
 +              else
 +                      val = FALSE;
 +
 +              connman_dbus_dict_append_basic(iter, "Connected",
 +                              DBUS_TYPE_BOOLEAN, &val);
 +
 +              str = connman_device_get_string(device, "Address");
 +              connman_dbus_dict_append_basic(iter, "MAC.Address",
 +                              DBUS_TYPE_STRING, &str);
 +      }
 +}
 +
 +void __connman_technology_append_interfaces(DBusMessageIter *array,
 +                              enum connman_service_type type, const char *ifname)
 +{
 +      GSList *list;
 +      struct connman_technology *technology = NULL;
 +
 +      for (list = technology_list; list; list = list->next) {
 +              struct connman_technology *local_tech = list->data;
 +
 +              if (local_tech->type != type)
 +                      continue;
 +
 +              technology = local_tech;
 +              break;
 +      }
 +
 +      if (!technology)
 +              return;
 +
 +      for (list = technology->device_list; list; list = list->next) {
 +              struct connman_device *device = list->data;
 +              const char *str = connman_device_get_string(device, "Interface");
 +
 +              if (g_strcmp0(ifname, str) == 0)
 +                      continue;
 +
 +              dbus_message_iter_append_basic(array,
 +                              DBUS_TYPE_STRING, &str);
 +      }
 +}
 +#endif
 +
  static void append_properties(DBusMessageIter *iter,
                struct connman_technology *technology)
  {
                                        DBUS_TYPE_STRING,
                                        &technology->tethering_passphrase);
  
 +#if defined TIZEN_EXT
 +      connman_dbus_dict_append_basic(&dict, "MacPolicy",
 +                                      DBUS_TYPE_UINT32,
 +                                      &(technology->mac_policy));
 +
 +      connman_dbus_dict_append_basic(&dict, "PreassocMacPolicy",
 +                                      DBUS_TYPE_UINT32,
 +                                      &(technology->preassoc_mac_policy));
 +
 +      connman_dbus_dict_append_basic(&dict, "RandomMacLifetime",
 +                                      DBUS_TYPE_UINT32,
 +                                      &(technology->random_mac_lifetime));
 +
 +      if (technology->type == CONNMAN_SERVICE_TYPE_WIFI)
 +              connman_dbus_dict_append_dict(&dict, "Device.List",
 +                                      append_devices, technology);
 +      if (technology->regdom)
 +              connman_dbus_dict_append_basic(&dict, "CountryCode",
 +                                      DBUS_TYPE_STRING,
 +                                      &technology->regdom);
 +#endif
        connman_dbus_dict_close(iter, &dict);
  }
  
@@@ -834,11 -656,6 +838,11 @@@ static int technology_affect_devices(st
                return 0;
        }
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +      if (technology->type == CONNMAN_SERVICE_TYPE_MESH)
 +              return 0;
 +#endif
 +
        for (list = technology->device_list; list; list = list->next) {
                struct connman_device *device = list->data;
  
@@@ -873,10 -690,6 +877,10 @@@ static void powered_changed(struct conn
  
        __sync_synchronize();
        enabled = technology->enabled;
 +#if defined TIZEN_EXT
 +      DBG("ConnMan, Powered : %s, %s",
 +                      enabled ? "TRUE" : "FALSE",technology->path);
 +#endif
        connman_dbus_property_changed_basic(technology->path,
                        CONNMAN_TECHNOLOGY_INTERFACE, "Powered",
                        DBUS_TYPE_BOOLEAN, &enabled);
@@@ -1051,280 -864,6 +1055,280 @@@ make_reply
        return reply;
  }
  
 +#if defined TIZEN_EXT
 +int set_connman_bssid(enum bssid_type mode, char *bssid, const char *ifname)
 +{
 +      static int bssid_len;
 +      static const char *def_ifname = "default";
 +      static GSList *bssid_list = NULL;
 +      GSList *list;
 +      const char *local_ifname = ifname;
 +      bool found = false;
 +      struct connman_bssid_pending *bssid_info;
 +
 +      DBG("mode: %d, ifname: %s", mode, ifname);
 +
 +      if (!ifname)
 +              local_ifname = def_ifname;
 +
 +      for (list = bssid_list; list; list = list->next) {
 +              bssid_info = list->data;
 +
 +              if (g_strcmp0(bssid_info->ifname, local_ifname) == 0) {
 +                      found = true;
 +                      break;
 +              }
 +      }
 +
 +      if (mode == CHECK_BSSID) {
 +              if (found)
 +                      return 6;
 +
 +              return 0;
 +      }
 +
 +      if (mode == GET_BSSID && bssid) {
 +              if (found) {
 +                      memcpy(bssid, bssid_info->bssid, 6);
 +                      return 6;
 +              }
 +              return 0;
 +      }
 +
 +      if (mode == RESET_BSSID) {
 +              if (found) {
 +                      bssid_list = g_slist_remove(bssid_list, bssid_info);
 +                      g_free(bssid_info->ifname);
 +                      g_free(bssid_info);
 +              }
 +              return 0;
 +      }
 +
 +      if (mode != SET_BSSID || !bssid) {
 +              DBG("Invalid parameter");
 +              return 0;
 +      }
 +
 +      if (found) {
 +              bssid_list = g_slist_remove(bssid_list, bssid_info);
 +              g_free(bssid_info->ifname);
 +              g_free(bssid_info);
 +      }
 +
 +      bssid_info = g_try_malloc0(sizeof(struct connman_bssid_pending));
 +      if (!bssid_info) {
 +              DBG("Failed to allocate memory");
 +              return 0;
 +      }
 +
 +      unsigned char *bssid_data = bssid_info->bssid;
 +
 +      bssid_len = sscanf(bssid, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
 +              &bssid_data[0], &bssid_data[1], &bssid_data[2],
 +              &bssid_data[3], &bssid_data[4], &bssid_data[5]);
 +      if (bssid_len != 6) {
 +              DBG("Incorrect BSSID format. bssid_len = %d", bssid_len);
 +              g_free(bssid_info);
 +              return 0;
 +      }
 +
 +      DBG("SET BSSID len: %d, BSSID: %02x:%02x:%02x:%02x:%02x:%02x ifname: %s",
 +              bssid_len,
 +              bssid_data[0], bssid_data[1], bssid_data[2],
 +              bssid_data[3], bssid_data[4], bssid_data[5],
 +              ifname);
 +
 +      bssid_info->ifname = g_strdup(ifname);
 +      bssid_list = g_slist_prepend(bssid_list, bssid_info);
 +
 +      return bssid_len;
 +}
 +
 +void connman_technology_mac_policy_notify(struct connman_technology *technology,
 +                                                      unsigned int policy)
 +{
 +      DBG("Mac polict set to %u", policy);
 +
 +      technology->mac_policy = policy;
 +      technology_save(technology);
 +}
 +
 +void __connman_technology_notify_mac_policy_by_device(struct connman_device *device,
 +                                              int result, unsigned int policy)
 +{
 +      struct connman_technology *technology;
 +      enum connman_service_type type;
 +
 +      type = __connman_device_get_service_type(device);
 +      technology = technology_find(type);
 +
 +      if (!technology)
 +              return;
 +
 +      connman_technology_mac_policy_notify(technology, policy);
 +}
 +
 +static DBusMessage *set_mac_policy(struct connman_technology *technology,
 +                              DBusMessage *msg, unsigned int policy)
 +{
 +      DBusMessage *reply = NULL;
 +      int err = 0;
 +      unsigned int last_policy = technology->mac_policy;
 +
 +      if (technology->rfkill_driven && technology->hardblocked) {
 +              err = -EACCES;
 +              goto make_reply;
 +      }
 +
 +      for (GSList *list = technology->device_list; list; list = list->next) {
 +              struct connman_device *device = list->data;
 +
 +              err = connman_device_set_mac_policy(device, policy);
 +              if (err < 0)
 +                      break;
 +      }
 +
 +make_reply:
 +      if (err < 0) {
 +              if (err != -EACCES && err != -EOPNOTSUPP) {
 +                      for (GSList *list = technology->device_list; list; list = list->next) {
 +                              struct connman_device *device = list->data;
 +
 +                              connman_device_set_mac_policy(device, last_policy);
 +                      }
 +              }
 +
 +              reply = __connman_error_failed(msg, -err);
 +      } else {
 +              reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 +      }
 +
 +      return reply;
 +}
 +
 +void connman_technology_preassoc_mac_policy_notify(struct connman_technology *technology,
 +                                                      unsigned int policy)
 +{
 +      DBG("Preassoc mac polict set to %u", policy);
 +
 +      technology->preassoc_mac_policy = policy;
 +      technology_save(technology);
 +}
 +
 +void __connman_technology_notify_preassoc_mac_policy_by_device(struct connman_device *device,
 +                                              int result, unsigned int policy)
 +{
 +      struct connman_technology *technology;
 +      enum connman_service_type type;
 +
 +      type = __connman_device_get_service_type(device);
 +      technology = technology_find(type);
 +
 +      if (!technology)
 +              return;
 +
 +      connman_technology_preassoc_mac_policy_notify(technology, policy);
 +}
 +
 +static DBusMessage *set_preassoc_mac_policy(struct connman_technology *technology,
 +                              DBusMessage *msg, unsigned int policy)
 +{
 +      DBusMessage *reply = NULL;
 +      int err = 0;
 +      unsigned int last_policy = technology->preassoc_mac_policy;
 +
 +      if (technology->rfkill_driven && technology->hardblocked) {
 +              err = -EACCES;
 +              goto make_reply;
 +      }
 +
 +      for (GSList *list = technology->device_list; list; list = list->next) {
 +              struct connman_device *device = list->data;
 +
 +              err = connman_device_set_preassoc_mac_policy(device, policy);
 +              if (err < 0)
 +                      break;
 +      }
 +
 +make_reply:
 +      if (err < 0) {
 +              if (err != -EACCES && err != -EOPNOTSUPP) {
 +                      for (GSList *list = technology->device_list; list; list = list->next) {
 +                              struct connman_device *device = list->data;
 +
 +                              connman_device_set_preassoc_mac_policy(device, last_policy);
 +                      }
 +              }
 +
 +              reply = __connman_error_failed(msg, -err);
 +      } else {
 +              reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 +      }
 +
 +      return reply;
 +}
 +
 +void connman_technology_random_mac_lifetime_notify(struct connman_technology *technology,
 +                                                      unsigned int lifetime)
 +{
 +      DBG("Random mac lifetime set to %u", lifetime);
 +
 +      technology->random_mac_lifetime = lifetime;
 +      technology_save(technology);
 +}
 +
 +void __connman_technology_notify_random_mac_lifetime_by_device(struct connman_device *device,
 +                                              int result, unsigned int lifetime)
 +{
 +      struct connman_technology *technology;
 +      enum connman_service_type type;
 +
 +      type = __connman_device_get_service_type(device);
 +      technology = technology_find(type);
 +
 +      if (!technology)
 +              return;
 +
 +      connman_technology_random_mac_lifetime_notify(technology, lifetime);
 +}
 +
 +static DBusMessage *set_random_mac_lifetime(struct connman_technology *technology,
 +                              DBusMessage *msg, unsigned int lifetime)
 +{
 +      DBusMessage *reply = NULL;
 +      int err = 0;
 +      unsigned int last_lifetime = technology->random_mac_lifetime;
 +
 +      if (technology->rfkill_driven && technology->hardblocked) {
 +              err = -EACCES;
 +              goto make_reply;
 +      }
 +
 +      for (GSList *list = technology->device_list; list; list = list->next) {
 +              struct connman_device *device = list->data;
 +
 +              err = connman_device_set_random_mac_lifetime(device, lifetime);
 +      }
 +
 +make_reply:
 +      if (err < 0) {
 +              if (err != -EACCES && err != -EOPNOTSUPP) {
 +                      for (GSList *list = technology->device_list; list; list = list->next) {
 +                              struct connman_device *device = list->data;
 +
 +                              connman_device_set_random_mac_lifetime(device, last_lifetime);
 +                      }
 +              }
 +
 +              reply = __connman_error_failed(msg, -err);
 +      } else {
 +              reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 +      }
 +
 +      return reply;
 +}
 +#endif
 +
  static DBusMessage *set_property(DBusConnection *conn,
                                        DBusMessage *msg, void *data)
  {
                dbus_message_iter_get_basic(&value, &enable);
  
                return set_powered(technology, msg, enable);
 -      } else
 -              return __connman_error_invalid_property(msg);
 +#if defined TIZEN_EXT
 +      } else if (g_str_equal(name, "SetBSSID")) {
 +              char *key;
  
 -      return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 -}
 +              if (type != DBUS_TYPE_STRING)
 +                      return __connman_error_invalid_arguments(msg);
 +
 +              dbus_message_iter_get_basic(&value, &key);
 +              DBG("BSSID %s", key);
 +              set_connman_bssid(SET_BSSID, key, NULL);
 +      } else if (g_str_equal(name, "MacPolicy")) {
 +              dbus_uint32_t mac_policy;
 +
 +              if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
 +                      return __connman_error_not_supported(msg);
 +
 +              if (type != DBUS_TYPE_UINT32)
 +                      return __connman_error_invalid_arguments(msg);
 +
 +              dbus_message_iter_get_basic(&value, &mac_policy);
 +
 +              if (mac_policy <= 2)
 +                      return set_mac_policy(technology, msg, mac_policy);
 +              else
 +                      return __connman_error_invalid_arguments(msg);
 +
 +      } else if (g_str_equal(name, "PreassocMacPolicy")) {
 +              dbus_uint32_t preassoc_mac_policy;
 +
 +              if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
 +                      return __connman_error_not_supported(msg);
 +
 +              if (type != DBUS_TYPE_UINT32)
 +                      return __connman_error_invalid_arguments(msg);
 +
 +              dbus_message_iter_get_basic(&value, &preassoc_mac_policy);
 +
 +              if (preassoc_mac_policy <= 2)
 +                      return set_preassoc_mac_policy(technology, msg, preassoc_mac_policy);
 +              else
 +                      return __connman_error_invalid_arguments(msg);
 +
 +      } else if (g_str_equal(name, "RandomMacLifetime")) {
 +              dbus_uint32_t random_mac_lifetime;
 +
 +              if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
 +                      return __connman_error_not_supported(msg);
 +
 +              if (type != DBUS_TYPE_UINT32)
 +                      return __connman_error_invalid_arguments(msg);
 +
 +              dbus_message_iter_get_basic(&value, &random_mac_lifetime);
 +
 +              if (random_mac_lifetime > 0)
 +                      return set_random_mac_lifetime(technology, msg, random_mac_lifetime);
 +              else
 +                      return __connman_error_invalid_arguments(msg);
 +
 +      } else if (g_str_equal(name, "CountryCode")) {
 +              const char *str;
 +
 +              dbus_message_iter_get_basic(&value, &str);
 +              DBG("country code %s", str);
 +              connman_technology_set_regdom(str);
 +#endif
 +      } else
 +              return __connman_error_invalid_property(msg);
 +
 +      return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 +}
  
  static void reply_scan_pending(struct connman_technology *technology, int err)
  {
        DBG("technology %p err %d", technology, err);
  
        while (technology->scan_pending) {
 +#if defined TIZEN_EXT
 +              struct connman_scan_pending *pending_data = technology->scan_pending->data;
 +              DBusMessage *msg = pending_data->msg;
 +#else
                DBusMessage *msg = technology->scan_pending->data;
 +#endif
 +              DBG("reply to %s", dbus_message_get_sender(msg));
 +
 +              if (err == 0)
 +                      reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 +              else
 +                      reply = __connman_error_failed(msg, -err);
 +              g_dbus_send_message(connection, reply);
 +              dbus_message_unref(msg);
 +
 +              technology->scan_pending =
 +                      g_slist_delete_link(technology->scan_pending,
 +                                      technology->scan_pending);
 +#if defined TIZEN_EXT
 +              g_free(pending_data->ifname);
 +              g_free(pending_data);
 +#endif
 +      }
 +}
 +
 +#if defined TIZEN_EXT
 +dbus_bool_t __connman_technology_notify_scan_changed(const char *key, void *val)
 +{
 +      DBG("key %s", key);
 +      DBusMessage *signal;
 +      DBusMessageIter iter;
 +      dbus_bool_t result = FALSE;
 +
 +      signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
 +                      CONNMAN_MANAGER_INTERFACE, "ScanChanged");
 +      if (!signal)
 +              return result;
 +
 +      dbus_message_iter_init_append(signal, &iter);
 +      if (key)
 +              connman_dbus_property_append_basic(&iter, key, DBUS_TYPE_BOOLEAN, val);
 +      else
 +              connman_dbus_property_append_basic(&iter, "", DBUS_TYPE_BOOLEAN, val);
 +
 +      result = dbus_connection_send(connection, signal, NULL);
 +      dbus_message_unref(signal);
 +
 +      DBG("Successfuly sent signal");
 +
 +      return result;
 +}
 +
 +void __connman_technology_notify_scan_done(const char *ifname, int val)
 +{
 +      DBG("");
 +      DBusMessage *signal;
 +      DBusMessageIter iter;
 +
 +      signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
 +                      CONNMAN_MANAGER_INTERFACE, "ScanDone");
 +      if (!signal)
 +              return;
 +
 +      dbus_message_iter_init_append(signal, &iter);
 +      if (ifname)
 +              connman_dbus_property_append_basic(&iter, ifname,
 +                              DBUS_TYPE_INT32, &val);
 +      else
 +              connman_dbus_property_append_basic(&iter, "",
 +                              DBUS_TYPE_INT32, &val);
 +
 +      dbus_connection_send(connection, signal, NULL);
 +      dbus_message_unref(signal);
 +
 +      DBG("Successfuly sent ScanDone signal");
 +}
 +
 +static void reply_scan_pending_device(
 +              struct connman_technology *technology, const char *ifname, int count)
 +{
 +      DBusMessage *reply;
 +      GSList *list;
 +      dbus_bool_t status = 0;
 +      connman_scan_type_e scan_type = CONNMAN_SCAN_TYPE_UNKNOWN;
 +
 +      DBG("technology %p ifname %s count %d", technology, ifname, count);
 +
 +      list = technology->scan_pending;
 +
 +      while (list) {
 +              struct connman_scan_pending *pending_data = list->data;
 +              DBusMessage *msg = pending_data->msg;
 +              list = list->next;
 +
 +              if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN)
 +                      scan_type = pending_data->scan_type;
 +
 +              if (count != 0 && g_strcmp0(pending_data->ifname, ifname) != 0)
 +                      continue;
 +
 +              scan_type = pending_data->scan_type;
  
                DBG("reply to %s", dbus_message_get_sender(msg));
 +              reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 +
 +              g_dbus_send_message(connection, reply);
 +              dbus_message_unref(msg);
 +
 +              technology->scan_pending =
 +                              g_slist_remove(technology->scan_pending, pending_data);
 +
 +              g_free(pending_data->ifname);
 +              g_free(pending_data);
 +      }
 +
 +      if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN)
 +              scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
 +
 +      __connman_technology_notify_scan_changed(ifname, &status);
 +      __connman_technology_notify_scan_done(ifname, scan_type);
 +}
 +
 +static void __connman_technology_notify_device_detected(
 +              struct connman_technology *technology, const char *ifname, bool val)
 +{
 +      DBG("");
 +      DBusMessage *signal;
 +      DBusMessageIter iter;
 +      dbus_bool_t detected = val;
 +
 +      if (!ifname)
 +              return;
 +
 +      signal = dbus_message_new_signal(technology->path,
 +                      CONNMAN_TECHNOLOGY_INTERFACE, "DeviceDetected");
 +      if (!signal)
 +              return;
 +
 +      dbus_message_iter_init_append(signal, &iter);
 +      dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &ifname);
 +      dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &detected);
 +
 +      dbus_connection_send(connection, signal, NULL);
 +      dbus_message_unref(signal);
 +
 +      DBG("Successfuly sent DeviceDetected signal");
 +}
 +
 +void __connman_technology_notify_roaming_state(const char *ifname,
 +              const char *state, const char *cur_bssid, const char *dst_bssid)
 +{
 +      DBG("");
 +      DBusMessage *signal;
 +      DBusMessageIter array, dict;
 +
 +      signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
 +                      CONNMAN_MANAGER_INTERFACE, "RoamingStateChanged");
 +      if (!signal)
 +              return;
 +
 +      dbus_message_iter_init_append(signal, &array);
 +
 +      connman_dbus_dict_open(&array, &dict);
 +
 +      if (ifname)
 +              connman_dbus_dict_append_basic(&dict, "Interface",
 +                                      DBUS_TYPE_STRING, &ifname);
 +      if (state)
 +              connman_dbus_dict_append_basic(&dict, "State",
 +                                      DBUS_TYPE_STRING, &state);
 +      if (cur_bssid)
 +              connman_dbus_dict_append_basic(&dict, "ConnectedBSSID",
 +                                      DBUS_TYPE_STRING, &cur_bssid);
 +      if (dst_bssid)
 +              connman_dbus_dict_append_basic(&dict, "TargetBSSID",
 +                                      DBUS_TYPE_STRING, &dst_bssid);
 +
 +      connman_dbus_dict_close(&array, &dict);
 +
 +      dbus_connection_send(connection, signal, NULL);
 +      dbus_message_unref(signal);
 +
 +      DBG("Successfully sent Roaming State Changed signal");
 +}
 +#endif
 +
 +void __connman_technology_scan_started(struct connman_device *device)
 +{
 +      DBG("device %p", device);
 +#if defined TIZEN_EXT
 +      dbus_bool_t status = 1;
 +      const char *ifname = connman_device_get_string(device, "Interface");
 +
 +      __connman_technology_notify_scan_changed(ifname, &status);
 +#endif
 +}
 +
 +void __connman_technology_scan_stopped(struct connman_device *device,
 +                                      enum connman_service_type type)
 +{
 +      int count = 0;
 +      struct connman_technology *technology;
 +      GSList *list;
 +
 +      technology = technology_find(type);
 +
 +      DBG("technology %p device %p", technology, device);
 +
 +      if (!technology)
 +              return;
 +
 +      for (list = technology->device_list; list; list = list->next) {
 +              struct connman_device *other_device = list->data;
 +
 +              if (device == other_device)
 +                      continue;
 +
 +              if (connman_device_get_scanning(other_device, type))
 +                      count += 1;
 +      }
 +
 +#if defined TIZEN_EXT
 +      const char *ifname = connman_device_get_string(device, "Interface");
 +      reply_scan_pending_device(technology, ifname, count);
 +
 +      return;
 +#else
 +      if (count == 0)
 +              reply_scan_pending(technology, 0);
 +#endif
 +}
 +
 +void __connman_technology_notify_regdom_by_device(struct connman_device *device,
 +                                              int result, const char *alpha2)
 +{
 +      bool regdom_set = false;
 +      struct connman_technology *technology;
 +      enum connman_service_type type;
 +      GSList *tech_drivers;
 +
 +      type = __connman_device_get_service_type(device);
 +      technology = technology_find(type);
 +
 +      if (!technology)
 +              return;
 +
 +      if (result < 0) {
 +
 +              for (tech_drivers = technology->driver_list;
 +                   tech_drivers;
 +                   tech_drivers = g_slist_next(tech_drivers)) {
 +                      struct connman_technology_driver *driver =
 +                              tech_drivers->data;
 +
 +                      if (driver->set_regdom) {
 +                              driver->set_regdom(technology, alpha2);
 +                              regdom_set = true;
 +                      }
 +
 +              }
 +
 +              if (!regdom_set)
 +                      alpha2 = NULL;
 +      }
 +
 +      connman_technology_regdom_notify(technology, alpha2);
 +}
 +
 +static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
 +{
 +      struct connman_technology *technology = data;
 +      int err;
 +
 +      DBG("technology %p request from %s", technology,
 +                      dbus_message_get_sender(msg));
 +
 +      if (technology->type == CONNMAN_SERVICE_TYPE_P2P &&
 +                              !technology->enabled)
 +              return __connman_error_permission_denied(msg);
 +
 +#if !defined TIZEN_EXT
 +      dbus_message_ref(msg);
 +      technology->scan_pending =
 +              g_slist_prepend(technology->scan_pending, msg);
 +#endif
 +
 +      err = __connman_device_request_scan_full(technology->type);
 +      if (err < 0)
 +#if defined TIZEN_EXT
 +              return __connman_error_failed(msg, -err);
 +#else
 +              reply_scan_pending(technology, err);
 +#endif
 +
 +#if defined TIZEN_EXT
 +      struct connman_scan_pending *pending_data =
 +                      g_try_malloc0(sizeof(struct connman_scan_pending));
 +      if (!pending_data)
 +              return __connman_error_failed(msg, ENOMEM);
 +
 +      pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
 +      DBG("scan_type %d", pending_data->scan_type);
 +
 +      pending_data->msg = dbus_message_ref(msg);
 +
 +      technology->scan_pending =
 +              g_slist_prepend(technology->scan_pending, pending_data);
 +#endif
 +      return NULL;
 +}
 +
 +#if defined TIZEN_EXT
 +static DBusMessage *scan_device(DBusConnection *conn, DBusMessage *msg, void *data)
 +{
 +      struct connman_technology *technology = data;
 +      DBusMessageIter iter;
 +      const char *ifname;
 +      int err;
 +
 +      DBG("technology %p request from %s", technology,
 +                      dbus_message_get_sender(msg));
 +
 +      if (!dbus_message_iter_init(msg, &iter))
 +              return __connman_error_invalid_arguments(msg);
 +
 +      if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
 +              return __connman_error_invalid_arguments(msg);
 +
 +      dbus_message_iter_get_basic(&iter, &ifname);
 +      DBG("Interface name %s", ifname);
 +
 +      if (!ifname || strlen(ifname) == 0)
 +              return __connman_error_invalid_arguments(msg);
 +
 +      err = connman_device_request_device_scan(technology->type, ifname, true);
 +      if (err < 0)
 +              return __connman_error_failed(msg, -err);
 +
 +      struct connman_scan_pending *pending_data =
 +                      g_try_malloc0(sizeof(struct connman_scan_pending));
 +      if (!pending_data)
 +              return __connman_error_failed(msg, ENOMEM);
 +
 +      pending_data->ifname =  g_strdup(ifname);
 +      if (pending_data->ifname == NULL) {
 +              g_free(pending_data);
 +              return __connman_error_failed(msg, ENOMEM);
 +      }
 +
 +      pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
 +      DBG("scan_type %d", pending_data->scan_type);
 +
 +      pending_data->msg = dbus_message_ref(msg);
 +
 +      technology->scan_pending =
 +              g_slist_prepend(technology->scan_pending, pending_data);
 +
 +      return NULL;
 +}
 +
 +static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void *data)
 +{
 +      struct connman_technology *technology = data;
 +      GSList *specific_scan_list = NULL;
 +      int scan_type = 0;
 +      const char *name = NULL;
 +      const char *freq = NULL;
 +      const char *ifname = NULL;
 +      DBusMessageIter iter, dict;
 +      int err;
 +
 +      DBG("technology %p request from %s", technology,
 +                      dbus_message_get_sender(msg));
 +
 +      if (!dbus_message_iter_init(msg, &iter))
 +              return __connman_error_invalid_arguments(msg);
 +
 +      if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
 +              return __connman_error_invalid_arguments(msg);
 +
 +      dbus_message_iter_recurse(&iter, &dict);
 +      while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
 +              DBusMessageIter entry, value2;
 +              const char *key;
 +              int type;
 +
 +              dbus_message_iter_recurse(&dict, &entry);
 +              if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) {
 +                      g_slist_free_full(specific_scan_list, g_free);
 +                      return __connman_error_invalid_arguments(msg);
 +              }
 +
 +              dbus_message_iter_get_basic(&entry, &key);
 +              dbus_message_iter_next(&entry);
 +
 +              if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) {
 +                      g_slist_free_full(specific_scan_list, g_free);
 +                      return __connman_error_invalid_arguments(msg);
 +              }
 +
 +              dbus_message_iter_recurse(&entry, &value2);
 +              type = dbus_message_iter_get_arg_type(&value2);
 +              if (g_str_equal(key, "Ifname") && type == DBUS_TYPE_STRING) {
 +
 +                      dbus_message_iter_get_basic(&value2, &ifname);
 +                      DBG("ifname %s", ifname);
 +              } else if (g_str_equal(key, "SSID")) {
 +                      if (type != DBUS_TYPE_STRING) {
 +                              g_slist_free_full(specific_scan_list, g_free);
 +                              return __connman_error_invalid_arguments(msg);
 +                      }
 +
 +                      scan_type = CONNMAN_MULTI_SCAN_SSID; /* SSID based scan */
 +                      dbus_message_iter_get_basic(&value2, &name);
 +                      DBG("name %s", name);
 +                      specific_scan_list = g_slist_append(specific_scan_list, g_strdup(name));
 +              } else if (g_str_equal(key, "Frequency")) {
 +                      if (type != DBUS_TYPE_STRING) {
 +                              g_slist_free_full(specific_scan_list, g_free);
 +                              return __connman_error_invalid_arguments(msg);
 +                      }
 +
 +                      scan_type = CONNMAN_MULTI_SCAN_FREQ; /* Frequency based scan */
 +                      dbus_message_iter_get_basic(&value2, &freq);
 +                      DBG("freq %s", freq);
 +                      specific_scan_list = g_slist_append(specific_scan_list, GINT_TO_POINTER(atoi(freq)));
 +              } else if (g_str_equal(key, "SSID_Mixed")) {
 +                      if (type != DBUS_TYPE_STRING) {
 +                              g_slist_free_full(specific_scan_list, g_free);
 +                              return __connman_error_invalid_arguments(msg);
 +                      }
 +
 +                      scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
 +                      dbus_message_iter_get_basic(&value2, &name);
 +
 +                      connman_multi_scan_ap_s *ap =
 +                                      (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
 +                      if (ap) {
 +                              g_strlcpy(ap->str, name, strlen(name) + 1);
 +                              ap->flag = true;
 +                              specific_scan_list = g_slist_append(specific_scan_list, ap);
 +                      } else
 +                              DBG("Failed to allocate memory");
 +
 +              } else if (g_str_equal(key, "Frequency_Mixed")) {
 +                      if (type != DBUS_TYPE_STRING) {
 +                              g_slist_free_full(specific_scan_list, g_free);
 +                              return __connman_error_invalid_arguments(msg);
 +                      }
 +
 +                      scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
 +                      dbus_message_iter_get_basic(&value2, &freq);
 +
 +                      connman_multi_scan_ap_s *ap =
 +                                      (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
 +                      if (ap) {
 +                              g_strlcpy(ap->str, freq, strlen(freq) + 1);
 +                              ap->flag = false;
 +                              specific_scan_list = g_slist_append(specific_scan_list, ap);
 +                      } else
 +                              DBG("Failed to allocate memory");
 +              }
 +              dbus_message_iter_next(&dict);
 +      }
 +
 +      err = __connman_device_request_specific_scan(technology->type, ifname, scan_type, specific_scan_list);
 +      if (err < 0)
 +              return __connman_error_failed(msg, -err);
 +
 +      guint list_size = g_slist_length(specific_scan_list);
 +
 +      if (scan_type == CONNMAN_MULTI_SCAN_SSID ||
 +                      scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ)
 +              g_slist_free_full(specific_scan_list, g_free);
 +
 +      struct connman_scan_pending *pending_data =
 +                      g_try_malloc0(sizeof(struct connman_scan_pending));
 +      if (!pending_data)
 +              return __connman_error_failed(msg, ENOMEM);
 +
 +      if (ifname) {
 +              pending_data->ifname =  g_strdup(ifname);
 +              if (pending_data->ifname == NULL) {
 +                      g_free(pending_data);
 +                      return __connman_error_failed(msg, ENOMEM);
 +              }
 +      }
 +
 +      if (list_size == 1)
 +              pending_data->scan_type = CONNMAN_SCAN_TYPE_SPECIFIC_AP;
 +      else
 +              pending_data->scan_type = CONNMAN_SCAN_TYPE_MULTI_AP;
 +      DBG("list_size %u scan_type %d", list_size, pending_data->scan_type);
 +
 +      pending_data->msg = dbus_message_ref(msg);
 +
 +      technology->scan_pending =
 +              g_slist_prepend(technology->scan_pending, pending_data);
 +
 +      return NULL;
 +}
 +
 +static DBusMessage *get_5ghz_supported(DBusConnection *conn, DBusMessage *msg, void *data)
 +{
 +      DBusMessage *reply;
 +      DBusMessageIter iter, dict;
 +      GSList *list;
 +      struct connman_technology *technology = data;
 +      dbus_bool_t supported = false;
 +      const char *ifname = NULL;
 +
 +      DBG("technology %p", technology);
 +
 +      reply = dbus_message_new_method_return(msg);
 +      if (!reply)
 +              return NULL;
 +
 +      dbus_message_iter_init_append(reply, &iter);
 +      connman_dbus_dict_open(&iter, &dict);
 +
 +      for (list = technology->device_list; list; list = list->next) {
 +              struct connman_device *device = list->data;
 +
 +              supported = connman_device_get_wifi_5ghz_supported(device);
 +              ifname = connman_device_get_string(device, "Interface");
 +
 +              DBG("ifname %s supported : %d", ifname, supported);
 +              connman_dbus_dict_append_basic(&dict, ifname,
 +                                              DBUS_TYPE_BOOLEAN,
 +                                              &supported);
 +      }
 +
 +      connman_dbus_dict_close(&iter, &dict);
 +
 +      return reply;
 +}
 +
 +static DBusMessage *get_scan_state(DBusConnection *conn, DBusMessage *msg, void *data)
 +{
 +      DBusMessage *reply;
 +      DBusMessageIter iter, dict;
 +      GSList *list;
 +      struct connman_technology *technology = data;
 +      dbus_bool_t scanning = false;
 +      const char *ifname = NULL;
 +
 +      DBG("technology %p", technology);
 +
 +      reply = dbus_message_new_method_return(msg);
 +      if (!reply)
 +              return NULL;
 +
 +      dbus_message_iter_init_append(reply, &iter);
 +      connman_dbus_dict_open(&iter, &dict);
 +
 +      for (list = technology->device_list; list; list = list->next) {
 +              struct connman_device *device = list->data;
 +
 +              scanning = connman_device_get_scanning(device, technology->type);
 +              ifname = connman_device_get_string(device, "Interface");
 +
 +              DBG("ifname %s scanning : %d", ifname, scanning);
 +              connman_dbus_dict_append_basic(&dict, ifname,
 +                                              DBUS_TYPE_BOOLEAN,
 +                                              &scanning);
 +      }
 +
 +      connman_dbus_dict_close(&iter, &dict);
 +
 +      return reply;
 +}
 +
 +static DBusMessage *get_max_scan_ssid(DBusConnection *conn, DBusMessage *msg, void *data)
 +{
 +      DBusMessage *reply;
 +      DBusMessageIter iter, dict;
 +      GSList *list;
 +      struct connman_technology *technology = data;
 +      dbus_int32_t max_scan_ssids = 0;
 +      const char *ifname = NULL;
 +
 +      DBG("technology %p", technology);
 +
 +      reply = dbus_message_new_method_return(msg);
 +      if (!reply)
 +              return NULL;
 +
 +      dbus_message_iter_init_append(reply, &iter);
 +      connman_dbus_dict_open(&iter, &dict);
 +
 +      for (list = technology->device_list; list; list = list->next) {
 +              struct connman_device *device = list->data;
 +
 +              max_scan_ssids = connman_device_get_max_scan_ssids(device);
 +              ifname = connman_device_get_string(device, "Interface");
 +
 +              DBG("ifname %s max_scan_ssids : %d", ifname, max_scan_ssids);
 +              connman_dbus_dict_append_basic(&dict, ifname,
 +                              DBUS_TYPE_INT32,
 +                              &max_scan_ssids);
 +      }
 +
 +      connman_dbus_dict_close(&iter, &dict);
 +
 +      return reply;
 +}
 +
 +static int technology_enable_device(struct connman_technology *technology,
 +                              bool enable_device, const char *ifname, struct connman_device **device_out)
 +{
 +      int err = 0;
 +      GSList *list;
 +
 +      for (list = technology->device_list; list; list = list->next) {
 +              struct connman_device *device = list->data;
 +              const char *str = connman_device_get_string(device, "Interface");
 +
 +              if (g_strcmp0(str, ifname) != 0)
 +                      continue;
 +
 +              if (enable_device)
 +                      err = __connman_device_enable(device);
 +              else
 +                      err = __connman_device_disable(device);
 +
 +              *device_out = device;
 +              return err;
 +      }
 +
 +      return -ENXIO;
 +}
 +
 +static DBusMessage *technology_set_device_powered(struct connman_technology *technology,
 +                              DBusMessage *msg, bool powered, const char *ifname)
 +{
 +      DBusMessage *reply = NULL;
 +      struct connman_device *device = NULL;
 +      int err = 0;
 +
 +      err = technology_enable_device(technology, powered, ifname, &device);
 +
 +      if (err == -EINPROGRESS) {
 +              if (device)
 +                      connman_device_set_pending_reply(device, msg);
 +              return reply;
 +      } else if (err == -EALREADY) {
 +              if (powered)
 +                      reply = __connman_error_already_enabled(msg);
 +              else
 +                      reply = __connman_error_already_disabled(msg);
 +      } else if (err < 0)
 +              reply = __connman_error_failed(msg, -err);
 +      else
 +              reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 +
 +      return reply;
 +}
 +
 +static DBusMessage *set_device_power(DBusConnection *conn,
 +                                      DBusMessage *msg, void *data)
 +{
 +      struct connman_technology *technology = data;
 +      DBusMessageIter iter;
 +      const char *name;
 +      int len;
 +      dbus_bool_t enable;
 +
 +      DBG("conn %p", conn);
 +
 +      if (!dbus_message_iter_init(msg, &iter))
 +              return __connman_error_invalid_arguments(msg);
 +
 +      if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
 +              return __connman_error_invalid_arguments(msg);
 +
 +      dbus_message_iter_get_basic(&iter, &name);
 +      dbus_message_iter_next(&iter);
 +
 +      if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
 +              return __connman_error_invalid_arguments(msg);
 +
 +      DBG("interface name %s", name);
 +
 +      len = strlen(name);
 +
 +      if (len + 1 > IFNAMSIZ)
 +              return __connman_error_invalid_arguments(msg);
 +
 +      dbus_message_iter_get_basic(&iter, &enable);
 +      DBG("powered %s", enable ? "TRUE" : "FALSE");
 +
 +      return technology_set_device_powered(technology, msg, enable, name);
 +}
 +
 +static DBusMessage *set_bssid(DBusConnection *conn,
 +                                      DBusMessage *msg, void *data)
 +{
 +      DBusMessageIter iter;
 +      char *name, *bssid;
 +      int len;
 +
 +      DBG("conn %p", conn);
 +
 +      if (!dbus_message_iter_init(msg, &iter))
 +              return __connman_error_invalid_arguments(msg);
 +
 +      if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
 +              return __connman_error_invalid_arguments(msg);
 +
 +      dbus_message_iter_get_basic(&iter, &name);
 +      dbus_message_iter_next(&iter);
 +
 +      if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
 +              return __connman_error_invalid_arguments(msg);
 +
 +      dbus_message_iter_get_basic(&iter, &bssid);
 +
 +      DBG("interface name %s bssid %s", name, bssid);
 +
 +      len = strlen(name);
 +
 +      if (len + 1 > IFNAMSIZ)
 +              return __connman_error_invalid_arguments(msg);
 +
 +      set_connman_bssid(SET_BSSID, bssid, name);
 +
 +      return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 +}
 +static struct connman_technology *technology_get(enum connman_service_type type);
 +
 +void technology_save_device(struct connman_device *device)
 +{
 +      struct connman_technology *technology;
 +      enum connman_service_type type;
 +
 +      type = __connman_device_get_service_type(device);
 +
 +      if (type != CONNMAN_SERVICE_TYPE_WIFI)
 +              return;
 +
 +      technology = technology_get(type);
 +      if (!technology)
 +              return;
 +
 +      if (!g_slist_find(technology->device_list, device))
 +              return;
 +
 +      GKeyFile *keyfile;
 +      gchar *identifier;
 +      const char *name = get_name(technology->type);
 +
 +      DBG("technology %p type %d name %s", technology, technology->type,
 +                                                                      name);
 +      if (!name)
 +              return;
 +
 +      keyfile = __connman_storage_load_global();
 +      if (!keyfile)
 +              keyfile = g_key_file_new();
 +
 +      identifier = g_strdup_printf("%s", name);
 +      if (!identifier)
 +              goto done;
 +
 +      GSList *list = NULL;
 +      gchar **ifname_list = NULL;
 +      guint dev_count = g_slist_length(technology->device_list);
 +
 +      if (dev_count >= 1) {
 +              GString *ifname_str = g_string_new(NULL);
 +
 +              if (ifname_str) {
 +                      for (list = technology->device_list; list; list = list->next) {
 +                              struct connman_device *device = list->data;
 +
 +                              if (connman_device_get_powered(device)) {
 +                                      const char *ifname = connman_device_get_string(device, "Interface");
 +
 +                                      if (ifname_str->len > 0)
 +                                              g_string_append_printf(ifname_str, " %s", ifname);
 +                                      else
 +                                              g_string_append(ifname_str, ifname);
 +                              }
 +                      }
 +
 +                      if (ifname_str->len > 0) {
 +                              ifname_list = g_strsplit_set(ifname_str->str, " ", 0);
 +                              dev_count = g_strv_length(ifname_list);
 +                              g_key_file_set_string_list(keyfile, identifier, "Enable.Devices",
 +                                                              (const gchar **) ifname_list, dev_count);
 +
 +                              technology->enable_persistent = true;
 +                      } else {
 +                              g_key_file_remove_key(keyfile, identifier, "Enable.Devices", NULL);
 +                              technology->enable_persistent = false;
 +                      }
 +
 +                      g_strfreev(ifname_list);
 +                      g_string_free(ifname_str, TRUE);
 +              }
 +      }
 +
 +      g_key_file_set_boolean(keyfile, identifier, "Enable",
 +                              technology->enable_persistent);
 +
 +      g_key_file_set_boolean(keyfile, identifier, "Tethering",
 +                              technology->tethering_persistent);
 +
 +      if (technology->tethering_ident)
 +              g_key_file_set_string(keyfile, identifier,
 +                                      "Tethering.Identifier",
 +                                      technology->tethering_ident);
 +
 +      if (technology->tethering_passphrase)
 +              g_key_file_set_string(keyfile, identifier,
 +                                      "Tethering.Passphrase",
 +                                      technology->tethering_passphrase);
 +
 +done:
 +      g_free(identifier);
  
 -              if (err == 0)
 -                      reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 -              else
 -                      reply = __connman_error_failed(msg, -err);
 -              g_dbus_send_message(connection, reply);
 -              dbus_message_unref(msg);
 +      __connman_storage_save_global(keyfile);
  
 -              technology->scan_pending =
 -                      g_slist_delete_link(technology->scan_pending,
 -                                      technology->scan_pending);
 -      }
 +      g_key_file_free(keyfile);
  }
 +#endif
  
 -void __connman_technology_scan_started(struct connman_device *device)
 +#if defined TIZEN_EXT_WIFI_MESH
 +bool __connman_technology_get_connected(enum connman_service_type type)
  {
 -      DBG("device %p", device);
 +      struct connman_technology *technology;
 +
 +      technology = technology_find(type);
 +
 +      if (!technology)
 +              return false;
 +
 +      return technology->connected;
  }
  
 -void __connman_technology_scan_stopped(struct connman_device *device,
 -                                      enum connman_service_type type)
 +void __connman_technology_mesh_interface_create_finished(
 +                                                      enum connman_service_type type, bool success,
 +                                                      const char *error)
  {
 -      int count = 0;
 +      DBusMessage *reply;
        struct connman_technology *technology;
 -      GSList *list;
 -
 +      DBusMessage *msg;
        technology = technology_find(type);
  
 -      DBG("technology %p device %p", technology, device);
 +      DBG("technology %p success %d", technology, success);
  
        if (!technology)
                return;
  
 -      for (list = technology->device_list; list; list = list->next) {
 -              struct connman_device *other_device = list->data;
 -
 -              if (device == other_device)
 -                      continue;
 -
 -              if (connman_device_get_scanning(other_device, type))
 -                      count += 1;
 +      msg = technology->mesh_dbus_msg;
 +      if (!msg) {
 +              DBG("No pending dbus message");
 +              return;
        }
  
 -      if (count == 0)
 -              reply_scan_pending(technology, 0);
 +      if (success) {
 +              reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 +              __connman_device_request_scan(technology->type);
 +      } else
 +              reply = g_dbus_create_error(msg, CONNMAN_ERROR_INTERFACE
 +                              ".MeshInterfaceAddFailed", "%s", error);
 +      g_dbus_send_message(connection, reply);
 +      dbus_message_unref(msg);
 +      technology->mesh_dbus_msg = NULL;
  }
  
 -void __connman_technology_notify_regdom_by_device(struct connman_device *device,
 -                                              int result, const char *alpha2)
 +void __connman_technology_mesh_interface_remove_finished(
 +                                                      enum connman_service_type type, bool success)
  {
 -      bool regdom_set = false;
 +      DBusMessage *reply;
        struct connman_technology *technology;
 -      enum connman_service_type type;
 -      GSList *tech_drivers;
 -
 -      type = __connman_device_get_service_type(device);
 +      DBusMessage *msg;
        technology = technology_find(type);
  
 -      if (!technology)
 +      DBG("technology %p success %d", technology, success);
 +
 +      if (!technology || !technology->mesh_dbus_msg)
                return;
  
 -      if (result < 0) {
 +      msg = technology->mesh_dbus_msg;
 +      if (!msg) {
 +              DBG("No pending dbus message");
 +              return;
 +      }
  
 -              for (tech_drivers = technology->driver_list;
 -                   tech_drivers;
 -                   tech_drivers = g_slist_next(tech_drivers)) {
 -                      struct connman_technology_driver *driver =
 -                              tech_drivers->data;
 +      if (success)
 +              reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 +      else
 +              reply = __connman_error_failed(msg, EINVAL);
 +      g_dbus_send_message(connection, reply);
 +      dbus_message_unref(msg);
 +      technology->mesh_dbus_msg = NULL;
 +}
  
 -                      if (driver->set_regdom) {
 -                              driver->set_regdom(technology, alpha2);
 -                              regdom_set = true;
 -                      }
 +void __connman_technology_notify_abort_scan(enum connman_service_type type,
 +                                                      int result)
 +{
 +      DBusMessage *reply;
 +      struct connman_technology *technology;
 +      DBusMessage *msg;
 +      technology = technology_find(type);
  
 -              }
 +      DBG("technology %p result %d", technology, result);
  
 -              if (!regdom_set)
 -                      alpha2 = NULL;
 +      if (!technology || !technology->mesh_dbus_msg)
 +              return;
 +
 +      msg = technology->mesh_dbus_msg;
 +      if (!msg) {
 +              DBG("No pending dbus message");
 +              return;
        }
  
 -      connman_technology_regdom_notify(technology, alpha2);
 +      if (result < 0)
 +              reply = __connman_error_scan_abort_failed(msg);
 +      else
 +              reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 +
 +      g_dbus_send_message(connection, reply);
 +      dbus_message_unref(msg);
 +      technology->mesh_dbus_msg = NULL;
  }
  
 -static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
 +static DBusMessage *mesh_commands(DBusConnection *conn,
 +                                DBusMessage *msg, void *data)
  {
        struct connman_technology *technology = data;
 +      DBusMessageIter iter, value, dict;
 +      const char *cmd = NULL, *ifname = NULL, *parent_ifname = NULL;
        int err;
  
 -      DBG("technology %p request from %s", technology,
 -                      dbus_message_get_sender(msg));
 +      DBG("conn %p", conn);
  
 -      if (technology->type == CONNMAN_SERVICE_TYPE_P2P &&
 -                              !technology->enabled)
 -              return __connman_error_permission_denied(msg);
 +      if (technology->type != CONNMAN_SERVICE_TYPE_MESH)
 +              return __connman_error_invalid_arguments(msg);
  
 -      dbus_message_ref(msg);
 -      technology->scan_pending =
 -              g_slist_prepend(technology->scan_pending, msg);
 +      if (!dbus_message_iter_init(msg, &iter))
 +              return __connman_error_invalid_arguments(msg);
  
 -      err = __connman_device_request_scan_full(technology->type);
 -      if (err < 0)
 -              reply_scan_pending(technology, err);
 +      if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
 +              return __connman_error_invalid_arguments(msg);
 +
 +      dbus_message_iter_get_basic(&iter, &cmd);
 +      dbus_message_iter_next(&iter);
 +
 +      if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
 +              return __connman_error_invalid_arguments(msg);
 +
 +      dbus_message_iter_recurse(&iter, &value);
 +
 +      if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_ARRAY)
 +              return __connman_error_invalid_arguments(msg);
 +
 +      DBG("Mesh Command %s", cmd);
 +      if (g_str_equal(cmd, "MeshInterfaceAdd")) {
 +              dbus_message_iter_recurse(&value, &dict);
 +              const char *bridge_ifname = NULL;
 +              while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
 +                      DBusMessageIter entry, value2;
 +                      const char *key;
 +                      int type;
 +
 +                      dbus_message_iter_recurse(&dict, &entry);
 +
 +                      if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
 +                              return __connman_error_invalid_arguments(msg);
 +
 +                      dbus_message_iter_get_basic(&entry, &key);
 +                      dbus_message_iter_next(&entry);
 +
 +                      if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
 +                              return __connman_error_invalid_arguments(msg);
 +
 +                      dbus_message_iter_recurse(&entry, &value2);
 +
 +                      type = dbus_message_iter_get_arg_type(&value2);
 +
 +                      if (g_str_equal(key, "Ifname")) {
 +                              if (type != DBUS_TYPE_STRING)
 +                                      return __connman_error_invalid_arguments(msg);
 +
 +                              dbus_message_iter_get_basic(&value2, &ifname);
 +                      } else if (g_str_equal(key, "ParentIfname")) {
 +                              if (type != DBUS_TYPE_STRING)
 +                                      return __connman_error_invalid_arguments(msg);
 +
 +                              dbus_message_iter_get_basic(&value2, &parent_ifname);
 +                      } else if (g_str_equal(key, "BridgeIfname")) {
 +                              if (type != DBUS_TYPE_STRING)
 +                                      return __connman_error_invalid_arguments(msg);
 +
 +                              dbus_message_iter_get_basic(&value2, &bridge_ifname);
 +                      }
 +                      dbus_message_iter_next(&dict);
 +              }
 +              DBG("Mesh Ifname %s parent %s bridge %s", ifname, parent_ifname,
 +                                      bridge_ifname ? bridge_ifname : "NULL");
 +              err = __connman_mesh_add_virtual_interface(ifname, parent_ifname,
 +                                                         bridge_ifname);
 +
 +              if (err != 0) {
 +                      DBG("Failed to add virtual mesh interface");
 +                      return __connman_error_failed(msg, -err);
 +              }
 +
 +              DBG("Successfully added virtual mesh interface");
 +
 +              dbus_message_ref(msg);
 +              technology->mesh_dbus_msg = msg;
 +
 +      } else if (g_str_equal(cmd, "MeshInterfaceRemove")) {
 +              dbus_message_iter_recurse(&value, &dict);
 +              while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
 +                      DBusMessageIter entry, value2;
 +                      const char *key;
 +                      int type;
 +
 +                      dbus_message_iter_recurse(&dict, &entry);
  
 +                      if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
 +                              return __connman_error_invalid_arguments(msg);
 +
 +                      dbus_message_iter_get_basic(&entry, &key);
 +                      dbus_message_iter_next(&entry);
 +
 +                      if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
 +                              return __connman_error_invalid_arguments(msg);
 +
 +                      dbus_message_iter_recurse(&entry, &value2);
 +
 +                      type = dbus_message_iter_get_arg_type(&value2);
 +
 +                      if (g_str_equal(key, "Ifname")) {
 +                              if (type != DBUS_TYPE_STRING)
 +                                      return __connman_error_invalid_arguments(msg);
 +
 +                              dbus_message_iter_get_basic(&value2, &ifname);
 +                      }
 +                      dbus_message_iter_next(&dict);
 +              }
 +              DBG("Mesh Ifname %s", ifname);
 +              err = __connman_mesh_remove_virtual_interface(ifname);
 +
 +              if (err != 0) {
 +                      DBG("Failed to remove virtual mesh interface");
 +                      return __connman_error_failed(msg, -err);
 +              }
 +
 +              DBG("Successfully removed virtual mesh interface");
 +
 +              dbus_message_ref(msg);
 +              technology->mesh_dbus_msg = msg;
 +
 +      } else if (g_str_equal(cmd, "MeshCreateNetwork")) {
 +              struct connman_mesh *connman_mesh;
 +              const char *name = NULL;
 +              const char *sec_type = NULL;
 +              const char *mesh_ifname = NULL;
 +              char *identifier, *group, *address;
 +              unsigned int freq = 0;
 +              unsigned int ieee80211w = 0;
 +              GString *str;
 +              int i;
 +              dbus_message_iter_recurse(&value, &dict);
 +              while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
 +                      DBusMessageIter entry, value2;
 +                      const char *key;
 +                      int type;
 +
 +                      dbus_message_iter_recurse(&dict, &entry);
 +
 +                      if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
 +                              return __connman_error_invalid_arguments(msg);
 +
 +                      dbus_message_iter_get_basic(&entry, &key);
 +                      dbus_message_iter_next(&entry);
 +
 +                      if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
 +                              return __connman_error_invalid_arguments(msg);
 +
 +                      dbus_message_iter_recurse(&entry, &value2);
 +
 +                      type = dbus_message_iter_get_arg_type(&value2);
 +
 +                      if (g_str_equal(key, "Name")) {
 +                              if (type != DBUS_TYPE_STRING)
 +                                      return __connman_error_invalid_arguments(msg);
 +
 +                              dbus_message_iter_get_basic(&value2, &name);
 +                      } else if (g_str_equal(key, "Frequency")) {
 +                              if (type != DBUS_TYPE_UINT16)
 +                                      return __connman_error_invalid_arguments(msg);
 +
 +                              dbus_message_iter_get_basic(&value2, &freq);
 +                      } else if (g_str_equal(key, "Security")) {
 +                              if (type != DBUS_TYPE_STRING)
 +                                      return __connman_error_invalid_arguments(msg);
 +
 +                              dbus_message_iter_get_basic(&value2, &sec_type);
 +                      } else if (g_str_equal(key, "Pmf")) {
 +                              if (type != DBUS_TYPE_UINT16)
 +                                      return __connman_error_invalid_arguments(msg);
 +
 +                              dbus_message_iter_get_basic(&value2, &ieee80211w);
 +                      }
 +                      dbus_message_iter_next(&dict);
 +              }
 +
 +              if (name == NULL || sec_type == NULL || freq == 0)
 +                      return __connman_error_invalid_arguments(msg);
 +
 +              DBG("Name %s Frequency %d Security type %s Pmf %u",
 +                  name, freq, sec_type, ieee80211w);
 +
 +              if (g_strcmp0(sec_type, "none") != 0 &&
 +                  g_strcmp0(sec_type, "sae") != 0) {
 +                      DBG("Unsupported security");
 +                      return __connman_error_invalid_arguments(msg);
 +              }
 +
 +              mesh_ifname = connman_mesh_get_interface_name();
 +
 +              if (!connman_mesh_is_interface_created()) {
 +                      DBG("Mesh interface doesn't exists");
 +                      return __connman_error_invalid_command(msg);
 +              }
 +
 +              str = g_string_sized_new((strlen(name) * 2) + 24);
 +
 +              for (i = 0; name[i]; i++)
 +                      g_string_append_printf(str, "%02x", name[i]);
 +
 +              g_string_append_printf(str, "_mesh");
 +
 +              if (g_strcmp0(sec_type, "none") == 0)
 +                      g_string_append_printf(str, "_none");
 +              else if (g_strcmp0(sec_type, "sae") == 0)
 +                      g_string_append_printf(str, "_sae");
 +
 +              group = g_string_free(str, FALSE);
 +
 +              identifier = connman_inet_ifaddr(mesh_ifname);
 +              address = connman_inet_ifname2addr(mesh_ifname);
 +
 +              connman_mesh = connman_mesh_create(identifier, group);
 +              connman_mesh_set_name(connman_mesh, name);
 +              connman_mesh_set_address(connman_mesh, address);
 +              connman_mesh_set_security(connman_mesh, sec_type);
 +              connman_mesh_set_frequency(connman_mesh, freq);
 +              connman_mesh_set_index(connman_mesh, connman_inet_ifindex(mesh_ifname));
 +              connman_mesh_set_peer_type(connman_mesh,
 +                                         CONNMAN_MESH_PEER_TYPE_CREATED);
 +              connman_mesh_set_ieee80211w(connman_mesh, ieee80211w);
 +
 +              connman_mesh_register(connman_mesh);
 +              g_free(group);
 +              g_free(identifier);
 +              g_free(address);
 +              DBG("Successfully Created Mesh Network");
 +              return  g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 +
 +      } else if (g_str_equal(cmd, "AbortScan")) {
 +              DBG("Abort Scan method");
 +              err = __connman_device_abort_scan(technology->type);
 +              if (err != 0) {
 +                      DBG("Failed to abort scan");
 +                      return __connman_error_failed(msg, -err);
 +              }
 +
 +              DBG("Successfully requested to abort scan");
 +              dbus_message_ref(msg);
 +              technology->mesh_dbus_msg = msg;
 +
 +      } else if (g_str_equal(cmd, "MeshSpecificScan")) {
 +              const char *name = NULL;
 +              unsigned int freq = 0;
 +              dbus_message_iter_recurse(&value, &dict);
 +              while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
 +                      DBusMessageIter entry, value2;
 +                      const char *key;
 +                      int type;
 +
 +                      dbus_message_iter_recurse(&dict, &entry);
 +
 +                      if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
 +                              return __connman_error_invalid_arguments(msg);
 +
 +                      dbus_message_iter_get_basic(&entry, &key);
 +                      dbus_message_iter_next(&entry);
 +
 +                      if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
 +                              return __connman_error_invalid_arguments(msg);
 +
 +                      dbus_message_iter_recurse(&entry, &value2);
 +
 +                      type = dbus_message_iter_get_arg_type(&value2);
 +
 +                      if (g_str_equal(key, "Name")) {
 +                              if (type != DBUS_TYPE_STRING)
 +                                      return __connman_error_invalid_arguments(msg);
 +
 +                              dbus_message_iter_get_basic(&value2, &name);
 +                      } else if (g_str_equal(key, "Frequency")) {
 +                              if (type != DBUS_TYPE_UINT16)
 +                                      return __connman_error_invalid_arguments(msg);
 +
 +                              dbus_message_iter_get_basic(&value2, &freq);
 +                      }
 +                      dbus_message_iter_next(&dict);
 +              }
 +
 +              DBG("MeshID %s Frequency %d sender %s", name, freq,
 +                                              dbus_message_get_sender(msg));
 +
 +              struct connman_scan_pending *pending_data =
 +                              g_try_malloc0(sizeof(struct connman_scan_pending));
 +              if (!pending_data)
 +                      return __connman_error_failed(msg, ENOMEM);
 +
 +              pending_data->msg = dbus_message_ref(msg);
 +
 +              technology->scan_pending =
 +                      g_slist_prepend(technology->scan_pending, pending_data);
 +
 +              err = __connman_device_request_mesh_specific_scan(technology->type,
 +                                                                name, freq);
 +              if (err < 0)
 +                      reply_scan_pending(technology, err);
 +              else
 +                      DBG("Successfully requested to scan specific Mesh Network");
 +
 +      } else if (g_str_equal(cmd, "SetMeshGate")) {
 +              unsigned int hwmp_rootmode = 0;
 +              bool gate_announce = false;
 +              unsigned int stp = 0;
 +              int err;
 +              dbus_message_iter_recurse(&value, &dict);
 +              while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
 +                      DBusMessageIter entry, value2;
 +                      const char *key;
 +                      int type;
 +
 +                      dbus_message_iter_recurse(&dict, &entry);
 +
 +                      if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
 +                              return __connman_error_invalid_arguments(msg);
 +
 +                      dbus_message_iter_get_basic(&entry, &key);
 +                      dbus_message_iter_next(&entry);
 +
 +                      if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
 +                              return __connman_error_invalid_arguments(msg);
 +
 +                      dbus_message_iter_recurse(&entry, &value2);
 +
 +                      type = dbus_message_iter_get_arg_type(&value2);
 +
 +                      if (g_str_equal(key, "GateAnnounce")) {
 +                              if (type != DBUS_TYPE_BOOLEAN)
 +                                      return __connman_error_invalid_arguments(msg);
 +
 +                              dbus_message_iter_get_basic(&value2, &gate_announce);
 +                      } else if (g_str_equal(key, "HWMPRootMode")) {
 +                              if (type != DBUS_TYPE_UINT16)
 +                                      return __connman_error_invalid_arguments(msg);
 +
 +                              dbus_message_iter_get_basic(&value2, &hwmp_rootmode);
 +                      } else if (g_str_equal(key, "STP")) {
 +                              if (type != DBUS_TYPE_UINT16)
 +                                      return __connman_error_invalid_arguments(msg);
 +
 +                              dbus_message_iter_get_basic(&value2, &stp);
 +                      }
 +                      dbus_message_iter_next(&dict);
 +              }
 +
 +              DBG("GateAnnounce %d HWMPRootMode %d STP %d sender %s",
 +                  gate_announce, hwmp_rootmode, stp, dbus_message_get_sender(msg));
 +
 +              err = __connman_mesh_set_stp_gate_announce(gate_announce,
 +                                                         hwmp_rootmode,
 +                                                         stp);
 +
 +              if (err < 0)
 +                      return __connman_error_failed(msg, -err);
 +
 +              return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 +      } else
 +              return __connman_error_invalid_command(msg);
        return NULL;
  }
 +#endif
  
  static const GDBusMethodTable technology_methods[] = {
        { GDBUS_DEPRECATED_METHOD("GetProperties",
                        GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
                        NULL, set_property) },
        { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
 +#if defined TIZEN_EXT
 +      { GDBUS_ASYNC_METHOD("ScanDevice", GDBUS_ARGS({ "interface_name", "s" }),
 +                      NULL, scan_device) },
 +      { GDBUS_ASYNC_METHOD("SpecificScan", GDBUS_ARGS({ "specificscan", "a{sv}" }),
 +                      NULL, specific_scan) },
 +      { GDBUS_METHOD("GetScanState", NULL, GDBUS_ARGS({ "scan_state", "a{sv}" }),
 +                      get_scan_state) },
 +      { GDBUS_METHOD("Get5GhzSupported", NULL, GDBUS_ARGS({ "supported", "a{sv}" }),
 +                      get_5ghz_supported) },
 +      { GDBUS_METHOD("GetMaxScanSsid", NULL, GDBUS_ARGS({ "maxscanssid", "a{sv}" }),
 +                      get_max_scan_ssid) },
 +      { GDBUS_ASYNC_METHOD("SetDevicePower",
 +                      GDBUS_ARGS({ "ifname", "s" }, { "value", "b" }),
 +                      NULL, set_device_power) },
 +      { GDBUS_ASYNC_METHOD("SetBSSID",
 +                      GDBUS_ARGS({ "ifname", "s" }, { "bssid", "s" }),
 +                      NULL, set_bssid) },
 +#endif
 +#if defined TIZEN_EXT_WIFI_MESH
 +      { GDBUS_ASYNC_METHOD("MeshCommands",
 +                      GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
 +                      NULL, mesh_commands) },
 +#endif
        { },
  };
  
  static const GDBusSignalTable technology_signals[] = {
        { GDBUS_SIGNAL("PropertyChanged",
                        GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
 +#if defined TIZEN_EXT
 +      { GDBUS_SIGNAL("DeviceChanged",
 +                      GDBUS_ARGS({ "device_property", "a{sv}" })) },
 +      { GDBUS_SIGNAL("DeviceDetected",
 +                      GDBUS_ARGS({ "ifname", "s" }, { "detected", "b" })) },
 +#endif
        { },
  };
  
@@@ -2927,9 -1183,7 +2931,9 @@@ static void technology_put(struct connm
          g_source_remove(technology->pending_timeout);
          technology->pending_timeout = 0;
      }
 -
 +#ifdef TIZEN_EXT
 +    g_strfreev(technology->enabled_devices);
 +#endif
        g_free(technology->path);
        g_free(technology->regdom);
        g_free(technology->tethering_ident);
@@@ -2953,12 -1207,7 +2957,12 @@@ static struct connman_technology *techn
  
        technology = technology_find(type);
        if (technology) {
 +#if defined TIZEN_EXT_WIFI_MESH
 +              if (type != CONNMAN_SERVICE_TYPE_P2P &&
 +                      type != CONNMAN_SERVICE_TYPE_MESH)
 +#else
                if (type != CONNMAN_SERVICE_TYPE_P2P)
 +#endif
                        __sync_fetch_and_add(&technology->refcount, 1);
                return technology;
        }
        technology->path = g_strdup_printf("%s/technology/%s",
                                                        CONNMAN_PATH, str);
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +      if (type == CONNMAN_SERVICE_TYPE_MESH) {
 +              struct connman_technology *wifi;
 +
 +              wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
 +              if (wifi)
 +                      technology->enabled = wifi->enabled;
 +      }
 +#endif
 +
        technology_load(technology);
        technology_list = g_slist_prepend(technology_list, technology);
        technology->driver_list = tech_drivers;
@@@ -3076,13 -1315,6 +3080,13 @@@ exist
                        return -ENOMEM;
        }
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +      if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
 +              if (!technology_get(CONNMAN_SERVICE_TYPE_MESH))
 +                      return -ENOMEM;
 +      }
 +#endif
 +
        return 0;
  }
  
@@@ -3120,13 -1352,6 +3124,13 @@@ void connman_technology_driver_unregist
                if (technology)
                        technology_put(technology);
        }
 +#if defined TIZEN_EXT_WIFI_MESH
 +      if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
 +              technology = technology_find(CONNMAN_SERVICE_TYPE_MESH);
 +              if (technology)
 +                      technology_put(technology);
 +      }
 +#endif
  }
  
  void __connman_technology_add_interface(enum connman_service_type type,
        case CONNMAN_SERVICE_TYPE_VPN:
        case CONNMAN_SERVICE_TYPE_GADGET:
        case CONNMAN_SERVICE_TYPE_P2P:
 +#if defined TIZEN_EXT_WIFI_MESH
 +      case CONNMAN_SERVICE_TYPE_MESH:
 +#endif
                break;
        }
  
@@@ -3203,9 -1425,6 +3207,9 @@@ void __connman_technology_remove_interf
        case CONNMAN_SERVICE_TYPE_VPN:
        case CONNMAN_SERVICE_TYPE_GADGET:
        case CONNMAN_SERVICE_TYPE_P2P:
 +#if defined TIZEN_EXT_WIFI_MESH
 +      case CONNMAN_SERVICE_TYPE_MESH:
 +#endif
                break;
        }
  
@@@ -3261,28 -1480,7 +3265,28 @@@ int __connman_technology_add_device(str
  
        if (technology->enable_persistent &&
                                        !global_offlinemode) {
 +#if defined TIZEN_EXT
 +              bool found = true;
 +              int err = 0;
 +              if (technology->enabled_devices && type == CONNMAN_SERVICE_TYPE_WIFI) {
 +                      int i = 0;
 +                      found = false;
 +                      const char *ifname = connman_device_get_string(device, "Interface");
 +
 +                      while (technology->enabled_devices[i]) {
 +                              if (g_strcmp0(technology->enabled_devices[i], ifname) == 0) {
 +                                      found = true;
 +                                      break;
 +                              }
 +                              i++;
 +                      }
 +              }
 +
 +              if (found)
 +                      err = __connman_device_enable(device);
 +#else
                int err = __connman_device_enable(device);
 +#endif
                /*
                 * connman_technology_add_device() calls __connman_device_enable()
                 * but since the device is already enabled, the call does not
@@@ -3300,16 -1498,6 +3304,16 @@@ done
        technology->device_list = g_slist_prepend(technology->device_list,
                                                                device);
  
 +#if defined TIZEN_EXT
 +      technology_save_device(device);
 +
 +      const char *ifname = connman_device_get_string(device, "Interface");
 +      __connman_technology_notify_device_detected(technology, ifname, true);
 +
 +      connman_device_set_mac_policy(device, technology->mac_policy);
 +      connman_device_set_preassoc_mac_policy(device, technology->preassoc_mac_policy);
 +      connman_device_set_random_mac_lifetime(device, technology->random_mac_lifetime);
 +#endif
        return 0;
  }
  
@@@ -3332,13 -1520,6 +3336,13 @@@ int __connman_technology_remove_device(
        technology->device_list = g_slist_remove(technology->device_list,
                                                                device);
  
 +#if defined TIZEN_EXT
 +      technology_save_device(device);
 +
 +      const char *ifname = connman_device_get_string(device, "Interface");
 +      __connman_technology_notify_device_detected(technology, ifname, false);
 +#endif
 +
        if (technology->tethering)
                set_tethering(technology, false);
  
@@@ -3359,13 -1540,11 +3363,13 @@@ int __connman_technology_enabled(enum c
                get_name(type), technology->rfkill_driven,
                technology->enabled);
  
 +#if !defined TIZEN_EXT
        if (technology->rfkill_driven) {
                if (technology->tethering_persistent)
                        enable_tethering(technology);
                return 0;
        }
 +#endif
  
        return technology_enabled(technology);
  }
@@@ -3379,11 -1558,9 +3383,11 @@@ int __connman_technology_disabled(enum 
        if (!technology)
                return -ENXIO;
  
 +#if !defined TIZEN_EXT
        if (technology->rfkill_driven)
                return 0;
  
 +#endif
        for (list = technology->device_list; list; list = list->next) {
                struct connman_device *device = list->data;
  
@@@ -3442,15 -1619,6 +3446,15 @@@ int __connman_technology_set_offlinemod
        return err;
  }
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +static gboolean __add_ethernet_to_bridge(gpointer data)
 +{
 +      DBG("");
 +      __connman_mesh_add_ethernet_to_bridge();
 +      return FALSE;
 +}
 +#endif
 +
  void __connman_technology_set_connected(enum connman_service_type type,
                bool connected)
  {
  
        technology->connected = connected;
  
 +#if defined TIZEN_EXT_WIFI_MESH
 +      if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET && connected)
 +              g_idle_add(__add_ethernet_to_bridge, NULL);
 +#endif
 +
        val = connected;
        connman_dbus_property_changed_basic(technology->path,
                        CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
@@@ -3576,10 -1739,6 +3580,10 @@@ int __connman_technology_add_rfkill(uns
        g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
  
  done:
 +#if defined TIZEN_EXT
 +      /* Fix Svace Issue [WGID: 1348]. */
 +      g_free(rfkill);
 +#endif
        technology = technology_get(type);
        /* If there is no driver for this type, ignore it. */
        if (!technology)
  
        technology->rfkill_driven = true;
  
 +#if !defined TIZEN_EXT
        /* If hardblocked, there is no need to handle softblocked state */
        if (technology_apply_rfkill_change(technology,
                                softblock, hardblock, true))
                return 0;
 +#endif
  
        if (global_offlinemode)
                return 0;
diff --combined src/tethering.c
index e2687b6,f930a26..f930a26
mode 100755,100644..100755
@@@ -386,7 -386,8 +386,8 @@@ static void setup_tun_interface(unsigne
  
        if ((__connman_inet_modify_address(RTM_NEWADDR,
                                NLM_F_REPLACE | NLM_F_ACK, pn->index, AF_INET,
-                               server_ip, peer_ip, prefixlen, NULL)) < 0) {
+                               server_ip, peer_ip, prefixlen, NULL, true))
+                               < 0) {
                DBG("address setting failed");
                return;
        }
diff --combined src/timeserver.c
index a9a73a2,feef8e8..b2707fa
mode 100755,100644..100755
@@@ -29,6 -29,7 +29,7 @@@
  #include <stdlib.h>
  #include <gweb/gresolv.h>
  #include <netdb.h>
+ #include <sys/time.h>
  
  #include "connman.h"
  
@@@ -40,6 -41,7 +41,7 @@@ static GSList *ts_list = NULL
  static char *ts_current = NULL;
  static int ts_recheck_id = 0;
  static int ts_backoff_id = 0;
+ static bool ts_is_synced = false;
  
  static GResolv *resolv = NULL;
  static int resolv_id = 0;
@@@ -53,10 -55,26 +55,26 @@@ static void resolv_debug(const char *st
  
  static void ntp_callback(bool success, void *user_data)
  {
+       dbus_uint64_t timestamp;
+       struct timeval tv;
        DBG("success %d", success);
  
-       if (!success)
+       __connman_timeserver_set_synced(success);
+       if (!success) {
                sync_next();
+               return;
+       }
+       if (gettimeofday(&tv, NULL) < 0) {
+               connman_warn("Failed to get current time");
+       }
+       timestamp = tv.tv_sec;
+       connman_dbus_property_changed_basic(
+                                       CONNMAN_MANAGER_PATH,
+                                       CONNMAN_CLOCK_INTERFACE, "Time",
+                                       DBUS_TYPE_UINT64, &timestamp);
  }
  
  static void save_timeservers(char **servers)
@@@ -100,17 -118,6 +118,17 @@@ static void resolv_result(GResolvResult
  {
        int i;
  
 +#if defined TIZEN_EXT
 +      gchar *server = NULL;
 +
 +      server = g_strdup((gchar *)user_data);
 +      ts_list = g_slist_append(ts_list, server);
 +
 +      if (!simplified_log)
 +              DBG("added server %s", server);
 +
 +      if (!simplified_log)
 +#endif
        DBG("status %d", status);
  
        if (status == G_RESOLV_RESULT_STATUS_SUCCESS) {
@@@ -187,17 -194,10 +205,17 @@@ static void sync_next(void
                        __connman_ntp_start(ts_current, ntp_callback, NULL);
                        return;
                }
 -
 +#if defined TIZEN_EXT
 +      if (!simplified_log)
 +#endif
                DBG("Resolving timeserver %s", ts_current);
 +#if defined TIZEN_EXT
 +              resolv_id = g_resolv_lookup_hostname(resolv, ts_current,
 +                                              resolv_result, ts_current);
 +#else
                resolv_id = g_resolv_lookup_hostname(resolv, ts_current,
                                                resolv_result, NULL);
 +#endif
                return;
        }
  
@@@ -290,6 -290,7 +308,7 @@@ GSList *__connman_timeserver_get_all(st
  
  static gboolean ts_recheck(gpointer user_data)
  {
+       struct connman_service *service;
        GSList *ts;
  
        ts = __connman_timeserver_get_all(connman_service_get_default());
  
                g_slist_free_full(ts, g_free);
  
-               __connman_timeserver_sync(NULL);
+               service = connman_service_get_default();
+               __connman_timeserver_sync(service);
  
                return FALSE;
        }
@@@ -345,31 -347,16 +365,16 @@@ static void ts_recheck_enable(void
                        NULL);
  }
  
- /*
-  * This function must be called every time the default service changes, the
-  * service timeserver(s) or gateway changes or the global timeserver(s) changes.
-  */
- int __connman_timeserver_sync(struct connman_service *default_service)
+ static void ts_reset(struct connman_service *service)
  {
-       struct connman_service *service;
        char **nameservers;
        int i;
  
-       if (default_service)
-               service = default_service;
-       else
-               service = connman_service_get_default();
-       if (!service)
-               return -EINVAL;
+       if (!resolv)
+               return;
  
- #if !defined TIZEN_EXT
-       if (service == ts_service)
-               return -EALREADY;
- #endif
+       __connman_timeserver_set_synced(false);
  
-       if (!resolv)
-               return 0;
        /*
         * Before we start creating the new timeserver list we must stop
         * any ongoing ntp query and server resolution.
        g_resolv_flush_nameservers(resolv);
  
        nameservers = connman_service_get_nameservers(service);
-       if (!nameservers)
-               return -EINVAL;
-       for (i = 0; nameservers[i]; i++)
-               g_resolv_add_nameserver(resolv, nameservers[i], 53, 0);
+       if (nameservers) {
+               for (i = 0; nameservers[i]; i++)
+                       g_resolv_add_nameserver(resolv, nameservers[i], 53, 0);
  
-       g_strfreev(nameservers);
+               g_strfreev(nameservers);
+       }
  
        g_slist_free_full(timeservers_list, g_free);
  
  
        if (!timeservers_list) {
                DBG("No timeservers set.");
-               return 0;
+               return;
        }
  
        ts_recheck_enable();
  
        ts_service = service;
        timeserver_sync_start();
+ }
  
-       return 0;
+ void __connman_timeserver_sync(struct connman_service *service)
+ {
+       if (!service || ts_service == service)
+               return;
+       ts_reset(service);
+ }
+ void __connman_timeserver_conf_update(struct connman_service *service)
+ {
+       if (!service || (ts_service && ts_service != service))
+               return;
+       ts_reset(service);
+ }
+ bool __connman_timeserver_is_synced(void)
+ {
+       return ts_is_synced;
+ }
+ void __connman_timeserver_set_synced(bool status)
+ {
+       dbus_bool_t is_synced;
+       if (ts_is_synced == status)
+               return;
+       ts_is_synced = status;
+       is_synced = status;
+       connman_dbus_property_changed_basic(CONNMAN_MANAGER_PATH,
+                               CONNMAN_CLOCK_INTERFACE, "TimeserverSynced",
+                               DBUS_TYPE_BOOLEAN, &is_synced);
  }
  
  static int timeserver_start(struct connman_service *service)
                g_strfreev(nameservers);
        }
  
-       return __connman_timeserver_sync(service);
+       __connman_timeserver_sync(service);
+       return 0;
  }
  
  static void timeserver_stop(void)
  
  int __connman_timeserver_system_set(char **servers)
  {
+       struct connman_service *service;
        save_timeservers(servers);
  
-       __connman_timeserver_sync(NULL);
+       service = connman_service_get_default();
+       if (service)
+               ts_reset(service);
  
        return 0;
  }
diff --combined src/wispr.c
index 3b203fb,c63dc81..fb101a1
mode 100755,100644..100755
@@@ -96,6 -96,8 +96,8 @@@ static bool wispr_portal_web_result(GWe
  
  static GHashTable *wispr_portal_list = NULL;
  
+ static bool enable_online_to_ready_transition = false;
  static void connman_wispr_message_init(struct connman_wispr_message *msg)
  {
        DBG("");
@@@ -422,10 -424,6 +424,10 @@@ static void wispr_portal_error(struct c
        DBG("Failed to proceed wispr/portal web request");
  
        wp_context->wispr_result = CONNMAN_WISPR_RESULT_FAILED;
 +
 +#if defined TIZEN_EXT
 +      connman_service_set_internet_connection(wp_context->service, false);
 +#endif
  }
  
  static void portal_manage_status(GWebResult *result,
                                &str))
                connman_info("Client-Timezone: %s", str);
  
-       free_connman_wispr_portal_context(wp_context);
+       if (!enable_online_to_ready_transition)
+               free_connman_wispr_portal_context(wp_context);
  
        __connman_service_ipconfig_indicate_state(service,
                                        CONNMAN_SERVICE_STATE_ONLINE, type);
+       if (enable_online_to_ready_transition)
+               __connman_service_online_check(service, type, true);
  }
  
  static bool wispr_route_request(const char *address, int ai_family,
@@@ -711,9 -713,6 +717,9 @@@ static bool wispr_portal_web_result(GWe
        const char *str = NULL;
        guint16 status;
        gsize length;
 +#if defined TIZEN_MAINTAIN_ONLINE
 +      static int retried = 0;
 +#endif
  
        DBG("");
  
                                wp_context->status_url, wp_context);
                break;
        case 200:
 +#if defined TIZEN_MAINTAIN_ONLINE
 +              retried = 0;
 +#endif
                if (wp_context->wispr_msg.message_type >= 0)
                        break;
  
                                        wp_context->redirect_url, wp_context);
  
                break;
+       case 300:
+       case 301:
        case 302:
+       case 303:
+       case 307:
+       case 308:
                if (!g_web_supports_tls() ||
                        !g_web_result_get_header(result, "Location",
                                                        &redirect)) {
                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,
@@@ -891,9 -875,6 +897,9 @@@ static int wispr_portal_detect(struct c
        case CONNMAN_SERVICE_TYPE_GPS:
        case CONNMAN_SERVICE_TYPE_VPN:
        case CONNMAN_SERVICE_TYPE_P2P:
 +#if defined TIZEN_EXT_WIFI_MESH
 +      case CONNMAN_SERVICE_TYPE_MESH:
 +#endif
                return -EOPNOTSUPP;
        }
  
                goto done;
        }
  
 +#if !defined TIZEN_EXT
        if (getenv("CONNMAN_WEB_DEBUG"))
 +#endif
                g_web_set_debug(wp_context->web, web_debug, "WEB");
  
        if (wp_context->type == CONNMAN_IPCONFIG_TYPE_IPV4) {
@@@ -972,11 -951,6 +978,11 @@@ int __connman_wispr_start(struct connma
  
        DBG("service %p", service);
  
 +#if defined TIZEN_EXT
 +      if (connman_service_get_type(service) == CONNMAN_SERVICE_TYPE_CELLULAR)
 +              return -EPERM;
 +#endif
 +
        if (!wispr_portal_list)
                return -EINVAL;
  
  
  void __connman_wispr_stop(struct connman_service *service)
  {
+       struct connman_wispr_portal *wispr_portal;
        int index;
  
        DBG("service %p", service);
        if (index < 0)
                return;
  
-       g_hash_table_remove(wispr_portal_list, GINT_TO_POINTER(index));
+       wispr_portal = g_hash_table_lookup(wispr_portal_list,
+                                       GINT_TO_POINTER(index));
+       if (!wispr_portal)
+               return;
+       if (wispr_portal->ipv4_context) {
+               if (service == wispr_portal->ipv4_context->service)
+                       g_hash_table_remove(wispr_portal_list,
+                                       GINT_TO_POINTER(index));
+       }
+       if (wispr_portal->ipv6_context) {
+               if (service == wispr_portal->ipv6_context->service)
+                       g_hash_table_remove(wispr_portal_list,
+                                       GINT_TO_POINTER(index));
+       }
  }
  
  int __connman_wispr_init(void)
                                                g_direct_equal, NULL,
                                                free_connman_wispr_portal);
  
+       enable_online_to_ready_transition =
+               connman_setting_get_bool("EnableOnlineToReadyTransition");
        return 0;
  }
  
diff --combined vpn/main.c
index ae9c945,92c63e2..e4f4a10
mode 100755,100644..100755
  
  #define CONFIGMAINFILE CONFIGDIR "/connman-vpn.conf"
  
- #define DEFAULT_INPUT_REQUEST_TIMEOUT 300 * 1000
- #define DEFAULT_BROWSER_LAUNCH_TIMEOUT 300 * 1000
  static GMainLoop *main_loop = NULL;
  
  static unsigned int __terminated = 0;
  
- static struct {
-       unsigned int timeout_inputreq;
-       unsigned int timeout_browserlaunch;
- } connman_vpn_settings  = {
-       .timeout_inputreq = DEFAULT_INPUT_REQUEST_TIMEOUT,
-       .timeout_browserlaunch = DEFAULT_BROWSER_LAUNCH_TIMEOUT,
- };
- static GKeyFile *load_config(const char *file)
- {
-       GError *err = NULL;
-       GKeyFile *keyfile;
-       keyfile = g_key_file_new();
-       g_key_file_set_list_separator(keyfile, ',');
-       if (!g_key_file_load_from_file(keyfile, file, 0, &err)) {
-               if (err->code != G_FILE_ERROR_NOENT) {
-                       connman_error("Parsing %s failed: %s", file,
-                                                               err->message);
-               }
-               g_error_free(err);
-               g_key_file_free(keyfile);
-               return NULL;
-       }
-       return keyfile;
- }
- static void parse_config(GKeyFile *config, const char *file)
- {
-       GError *error = NULL;
-       int timeout;
-       if (!config)
-               return;
-       DBG("parsing %s", file);
-       timeout = g_key_file_get_integer(config, "General",
-                       "InputRequestTimeout", &error);
-       if (!error && timeout >= 0)
-               connman_vpn_settings.timeout_inputreq = timeout * 1000;
-       g_clear_error(&error);
- }
- static int config_init(const char *file)
- {
-       GKeyFile *config;
-       config = load_config(file);
-       parse_config(config, file);
-       if (config)
-               g_key_file_free(config);
-       return 0;
- }
  static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
                                                        gpointer user_data)
  {
@@@ -193,7 -129,6 +129,6 @@@ static gchar *option_plugin = NULL
  static gchar *option_noplugin = NULL;
  static bool option_detach = true;
  static bool option_version = false;
- static bool option_routes = false;
  
  static bool parse_debug(const char *key, const char *value,
                                        gpointer user_data, GError **error)
@@@ -220,40 -155,11 +155,48 @@@ static GOptionEntry options[] = 
        { "nodaemon", 'n', G_OPTION_FLAG_REVERSE,
                                G_OPTION_ARG_NONE, &option_detach,
                                "Don't fork daemon to background" },
-       { "routes", 'r', 0, G_OPTION_ARG_NONE, &option_routes,
-                               "Create/delete VPN routes" },
        { "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
                                "Show version information and exit" },
        { 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.
@@@ -263,16 -169,6 +206,6 @@@ unsigned int connman_timeout_input_requ
        return __vpn_settings_get_timeout_inputreq();
  }
  
- unsigned int connman_timeout_browser_launch(void)
- {
-       return connman_vpn_settings.timeout_browserlaunch;
- }
- const char *connman_option_get_string(const char *key)
- {
-       return NULL;
- }
  int main(int argc, char *argv[])
  {
        GOptionContext *context;
  
        __connman_inotify_init();
        __connman_agent_init();
-       __vpn_provider_init(option_routes);
+       __vpn_provider_init();
        __vpn_manager_init();
        __vpn_ipconfig_init();
        __vpn_rtnl_init();
diff --combined vpn/plugins/l2tp.c
index 48894aa,1e4fcd1..1e4fcd1
mode 100755,100644..100755
@@@ -246,6 -246,8 +246,8 @@@ static int l2tp_notify(DBusMessage *msg
                connman_ipaddress_set_ipv4(ipaddress, addressv4, netmask,
                                        gateway);
  
+       connman_ipaddress_set_p2p(ipaddress, true);
        vpn_provider_set_ipaddress(provider, ipaddress);
        vpn_provider_set_nameservers(provider, nameservers);
  
index d600e61,fc6ceff..fc6ceff
mode 100755,100644..100755
@@@ -42,6 -42,8 +42,8 @@@
  #include <connman/setting.h>
  #include <connman/vpn-dbus.h>
  
+ #include <openconnect.h>
  #include "../vpn-provider.h"
  #include "../vpn-agent.h"
  
@@@ -89,7 -91,6 +91,6 @@@ enum oc_connect_type 
  
  static const char *connect_types[] = {"cookie", "cookie_with_userpass",
                        "userpass", "publickey", "pkcs", NULL};
- static const char *protocols[] = { "anyconnect", "nc", "gp", NULL};
  
  struct oc_private_data {
        struct vpn_provider *provider;
        char *dbus_sender;
        vpn_provider_connect_cb_t cb;
        void *user_data;
+       GThread *cookie_thread;
+       struct openconnect_info *vpninfo;
+       int fd_cmd;
+       int err;
        int fd_in;
-       int out_ch_id;
        int err_ch_id;
-       GIOChannel *out_ch;
        GIOChannel *err_ch;
        enum oc_connect_type connect_type;
-       bool interactive;
+       bool tried_passphrase;
  };
  
+ typedef void (*request_input_reply_cb_t) (DBusMessage *reply,
+                                       void *user_data);
+ static int run_connect(struct oc_private_data *data, const char *cookie);
+ static int request_input_credentials_full(
+                       struct oc_private_data *data,
+                       request_input_reply_cb_t cb,
+                       void *user_data);
  static bool is_valid_protocol(const char* protocol)
  {
+       int num_protocols;
+       int i;
+       struct oc_vpn_proto *protos;
        if (!protocol || !*protocol)
                return false;
  
-       return g_strv_contains(protocols, protocol);
+       num_protocols = openconnect_get_supported_protocols(&protos);
+       for (i = 0; i < num_protocols; i++)
+               if (!strcmp(protos[i].name, protocol))
+                       break;
+       openconnect_free_supported_protocols(protos);
+       return i < num_protocols;
  }
  
  static void oc_connect_done(struct oc_private_data *data, int err)
@@@ -139,11 -165,7 +165,7 @@@ static void close_io_channel(struct oc_
        if (!data || !channel)
                return;
  
-       if (data->out_ch == channel) {
-               id = data->out_ch_id;
-               data->out_ch = NULL;
-               data->out_ch_id = 0;
-       } else if (data->err_ch == channel) {
+       if (data->err_ch == channel) {
                id = data->err_ch_id;
                data->err_ch = NULL;
                data->err_ch_id = 0;
@@@ -167,6 -189,9 +189,9 @@@ static void free_private_data(struct oc
  
        connman_info("provider %p", data->provider);
  
+       if (data->vpninfo)
+               openconnect_vpninfo_free(data->vpninfo);
        if (vpn_provider_get_plugin_data(data->provider) == data)
                vpn_provider_set_plugin_data(data->provider, NULL);
  
        if (data->fd_in > 0)
                close(data->fd_in);
        data->fd_in = -1;
-       close_io_channel(data, data->out_ch);
        close_io_channel(data, data->err_ch);
  
        g_free(data->dbus_sender);
@@@ -357,6 -381,8 +381,8 @@@ static int oc_notify(DBusMessage *msg, 
        else
                connman_ipaddress_set_ipv6(ipaddress, addressv6,
                                                prefix_len, gateway);
+       connman_ipaddress_set_p2p(ipaddress, true);
        vpn_provider_set_ipaddress(provider, ipaddress);
        vpn_provider_set_domain(provider, domain);
  
        return VPN_STATE_CONNECT;
  }
  
- static ssize_t full_write(int fd, const void *buf, size_t len)
+ static ssize_t full_write(int fd, const char *buf, size_t len)
  {
        ssize_t byte_write;
  
@@@ -426,37 -452,6 +452,6 @@@ static void oc_died(struct connman_tas
        free_private_data(data);
  }
  
- static gboolean io_channel_out_cb(GIOChannel *source, GIOCondition condition,
-                       gpointer user_data)
- {
-       struct oc_private_data *data;
-       char *str;
-       data = user_data;
-       if (data->out_ch != source)
-               return G_SOURCE_REMOVE;
-       if ((condition & G_IO_IN) &&
-               g_io_channel_read_line(source, &str, NULL, NULL, NULL) ==
-                                                       G_IO_STATUS_NORMAL) {
-               g_strchomp(str);
-               /* Only cookie is printed to stdout */
-               vpn_provider_set_string_hide_value(data->provider,
-                                       "OpenConnect.Cookie", str);
-               g_free(str);
-       } else if (condition & (G_IO_ERR | G_IO_HUP)) {
-               connman_info("Out channel termination");
-               close_io_channel(data, source);
-               return G_SOURCE_REMOVE;
-       }
-       return G_SOURCE_CONTINUE;
- }
  static bool strv_contains_prefix(const char *strv[], const char *str)
  {
        int i;
        return false;
  }
  
- static void clear_provider_credentials(struct vpn_provider *provider)
+ static void clear_provider_credentials(struct vpn_provider *provider,
+                                               bool clear_pkcs_pass)
  {
-       const char *keys[] = { "OpenConnect.Username",
+       const char *keys[] = { "OpenConnect.PKCSPassword",
+                               "OpenConnect.Username",
                                "OpenConnect.Password",
-                               "OpenConnect.PKCSPassword",
                                "OpenConnect.Cookie",
                                NULL
        };
-       int i;
+       size_t i;
  
        connman_info("provider %p", provider);
  
-       for (i = 0; keys[i]; i++) {
+       for (i = !clear_pkcs_pass; keys[i]; i++) {
                if (!vpn_provider_get_string_immutable(provider, keys[i]))
                        vpn_provider_set_string_hide_value(provider, keys[i],
                                                "-");
        }
  }
  
- typedef void (* request_input_reply_cb_t) (DBusMessage *reply,
-                                       void *user_data);
+ static void __attribute__ ((format(printf, 3, 4))) oc_progress(void *user_data,
+               int level, const char *fmt, ...)
+ {
+       va_list ap;
+       char *msg;
  
- static int request_input_credentials(struct oc_private_data *data,
-                       request_input_reply_cb_t cb);
+       va_start(ap, fmt);
+       msg = g_strdup_vprintf(fmt, ap);
+       connman_debug("%s", msg);
+       g_free(msg);
+       va_end(ap);
+ }
+ /*
+  * There is no enum / defines for these in openconnect.h, but these values
+  * are based on the comment for openconnect_validate_peer_cert_vfn.
+  */
+ enum oc_cert_status {
+       OC_CERT_ACCEPT = 0,
+       OC_CERT_REJECT = 1
+ };
+ struct validate_cert_data {
+       GMutex mutex;
+       GCond cond;
+       const char *reason;
+       struct oc_private_data *data;
+       bool processed;
+       enum oc_cert_status status;
+ };
+ static gboolean validate_cert(void *user_data)
+ {
+       struct validate_cert_data *cert_data = user_data;
+       struct oc_private_data *data;
+       const char *server_cert;
+       bool allow_self_signed;
+       DBG("");
+       g_mutex_lock(&cert_data->mutex);
+       data = cert_data->data;
+       server_cert = vpn_provider_get_string(data->provider,
+                                               "OpenConnect.ServerCert");
+       allow_self_signed = vpn_provider_get_boolean(data->provider,
+                                       "OpenConnect.AllowSelfSignedCert",
+                                       false);
  
+       if (!allow_self_signed) {
+               cert_data->status = OC_CERT_REJECT;
+       } else if (server_cert) {
+               /*
+                * Check peer cert hash may return negative values on errors,
+                * but anything non-zero is acceptable.
+                */
+               cert_data->status = openconnect_check_peer_cert_hash(
+                                                               data->vpninfo,
+                                                               server_cert);
+       } else {
+               /*
+                * We could verify this from the agent at this point, and
+                * release the thread upon reply.
+                */
+               DBG("Server cert hash: %s",
+                               openconnect_get_peer_cert_hash(data->vpninfo));
+               vpn_provider_set_string(data->provider,
+                               "OpenConnect.ServerCert",
+                               openconnect_get_peer_cert_hash(data->vpninfo));
+               cert_data->status = OC_CERT_ACCEPT;
+       }
+       cert_data->processed = true;
+       g_cond_signal(&cert_data->cond);
+       g_mutex_unlock(&cert_data->mutex);
+       return G_SOURCE_REMOVE;
+ }
+ static int oc_validate_peer_cert(void *user_data, const char *reason)
+ {
+       struct validate_cert_data data = { .reason = reason,
+                                               .data = user_data,
+                                               .processed = false };
+       g_cond_init(&data.cond);
+       g_mutex_init(&data.mutex);
+       g_mutex_lock(&data.mutex);
+       g_idle_add(validate_cert, &data);
+       while (!data.processed)
+               g_cond_wait(&data.cond, &data.mutex);
+       g_mutex_unlock(&data.mutex);
+       g_mutex_clear(&data.mutex);
+       g_cond_clear(&data.cond);
+       return data.status;
+ }
+ struct process_form_data {
+       GMutex mutex;
+       GCond cond;
+       struct oc_auth_form *form;
+       struct oc_private_data *data;
+       bool processed;
+       int status;
+ };
  
  static void request_input_pkcs_reply(DBusMessage *reply, void *user_data)
  {
-       struct oc_private_data *data = user_data;
-       const char *password = NULL;
+       struct process_form_data *form_data = user_data;
+       struct oc_private_data *data = form_data->data;
+       struct oc_form_opt *opt;
        const char *key;
+       const char *password = NULL;
        DBusMessageIter iter, dict;
-       int err;
  
        connman_info("provider %p", data->provider);
  
-       if (!reply)
+       if (!reply) {
+               data->err = ENOENT;
                goto err;
+       }
  
-       err = vpn_agent_check_and_process_reply_error(reply, data->provider,
-                               data->task, data->cb, data->user_data);
-       if (err) {
-               /* Ensure cb is called only once */
+       if ((data->err = vpn_agent_check_and_process_reply_error(reply,
+                                                       data->provider,
+                                                       data->task,
+                                                       data->cb,
+                                                       data->user_data))) {
                data->cb = NULL;
                data->user_data = NULL;
                goto err;
        }
  
-       if (!vpn_agent_check_reply_has_dict(reply))
+       if (!vpn_agent_check_reply_has_dict(reply)) {
+               data->err = ENOENT;
                goto err;
+       }
  
        dbus_message_iter_init(reply, &iter);
        dbus_message_iter_recurse(&iter, &dict);
                dbus_message_iter_next(&dict);
        }
  
-       if (data->connect_type != OC_CONNECT_PKCS || !password)
+       if (!password)
                goto err;
  
-       if (write_data(data->fd_in, password) != 0) {
-               connman_error("openconnect failed to take PKCS pass phrase on"
-                                       " stdin");
-               goto err;
+       for (opt = form_data->form->opts; opt; opt = opt->next) {
+               if (opt->flags & OC_FORM_OPT_IGNORE)
+                       continue;
+               if (opt->type == OC_FORM_OPT_PASSWORD &&
+                               g_str_has_prefix(opt->name,
+                                       "openconnect_pkcs")) {
+                       opt->_value = strdup(password);
+                       form_data->status = OC_FORM_RESULT_OK;
+                       data->tried_passphrase = true;
+                       break;
+               }
        }
  
-       clear_provider_credentials(data->provider);
+       goto out;
  
-       return;
  err:
-       oc_connect_done(data, EACCES);
+       form_data->status = OC_FORM_RESULT_ERR;
+ out:
+       form_data->processed = true;
+       g_cond_signal(&form_data->cond);
+       g_mutex_unlock(&form_data->mutex);
  }
  
  static gboolean io_channel_err_cb(GIOChannel *source, GIOCondition condition,
-                       gpointer user_data)
+                                                       gpointer user_data)
  {
        struct oc_private_data *data;
        const char *auth_failures[] = {
-                               /* Login failed */
-                               "Got HTTP response: HTTP/1.1 401 Unauthorized",
-                               "Failed to obtain WebVPN cookie",
                                /* Cookie not valid */
                                "Got inappropriate HTTP CONNECT response: "
                                                "HTTP/1.1 401 Unauthorized",
                                /* Invalid cookie */
                                "VPN service unavailable",
-                               /* Problem with certificates */
-                               "SSL connection failure",
-                               "Creating SSL connection failed",
-                               "SSL connection cancelled",
                                NULL
        };
        const char *conn_failures[] = {
                                "Failed to open HTTPS connection to",
                                NULL
        };
-       /* Handle both PKCS#12 and PKCS#8 failures */
-       const char *pkcs_failures[] = {
-                               "Failed to decrypt PKCS#12 certificate file",
-                               "Failed to decrypt PKCS#8 certificate file",
-                               NULL
-       };
-       /* Handle both PKCS#12 and PKCS#8 requests */
-       const char *pkcs_requests[] = {
-                               "Enter PKCS#12 pass phrase",
-                               "Enter PKCS#8 pass phrase",
-                               NULL
-       };
-       const char *server_key_hash = "    --servercert";
+       const char *server_key_hash = "    --servercert ";
        char *str;
-       bool close = false;
        int err = 0;
  
        data = user_data;
  
        if ((condition & G_IO_IN)) {
                gsize len;
-               int pos;
-               if (!data->interactive) {
-                       if (g_io_channel_read_line(source, &str, &len, NULL,
-                                               NULL) != G_IO_STATUS_NORMAL)
-                               err = EIO;
-                       else
-                               str[len - 1] = '\0';
-               } else {
-                       GIOStatus status;
-                       str = g_try_new0(char, OC_MAX_READBUF_LEN);
-                       if (!str)
-                               return G_SOURCE_REMOVE;
  
-                       for (pos = 0; pos < OC_MAX_READBUF_LEN - 1 ; ++pos) {
-                               status = g_io_channel_read_chars(source,
-                                               str+pos, 1, &len, NULL);
-                               if (status == G_IO_STATUS_EOF) {
-                                       break;
-                               } else if (status != G_IO_STATUS_NORMAL) {
-                                       err = EIO;
-                                       break;
-                               }
-                               /* Ignore control chars and digits at start */
-                               if (!pos && (g_ascii_iscntrl(str[pos]) ||
-                                               g_ascii_isdigit(str[pos])))
-                                       --pos;
-                               /* Read zero length or no more to read */
-                               if (!len || g_io_channel_get_buffer_condition(
-                                                       source) != G_IO_IN ||
-                                                       str[pos] == '\n')
-                                       break;
-                       }
-                       /*
-                        * When self signed certificates are allowed and server
-                        * SHA1 fingerprint is printed to stderr there is a
-                        * newline char at the end of SHA1 fingerprint.
-                        */
-                       if (str[pos] == '\n')
-                               str[pos] = '\0';
-               }
+               if (g_io_channel_read_line(source, &str, &len, NULL,
+                                       NULL) != G_IO_STATUS_NORMAL)
+                       err = EIO;
+               else
+                       g_strchomp(str);
  
                connman_info("openconnect: %s", str);
  
  
                                vpn_provider_set_string(data->provider,
                                                "OpenConnect.ServerCert",
-                                               fingerprint);
-                               /*
-                                * OpenConnect waits for "yes" or "no" as
-                                * response to certificate acceptance request.
-                                */
-                               if (write_data(data->fd_in, "yes") != 0)
-                                       connman_error("openconnect: cannot "
-                                               "write answer to certificate "
-                                               "accept request");
+                                               str + strlen(server_key_hash));
                        } else {
                                connman_warn("Self signed certificate is not "
-                                                       " allowed");
-                               /*
-                                * Close IO channel to avoid deadlock as an
-                                * answer is expected for the certificate
-                                * accept request.
-                                */
-                               close = true;
+                                                       "allowed");
                                err = ECONNREFUSED;
                        }
-               } else if (strv_contains_prefix(pkcs_failures, str)) {
-                       connman_warn("PKCS failure: %s", str);
-                       close = true;
-                       err = EACCES;
-               } else if (strv_contains_prefix(pkcs_requests, str)) {
-                       connman_info("PKCS file pass phrase request: %s", str);
-                       err = request_input_credentials(data,
-                                               request_input_pkcs_reply);
-                       if (err != -EINPROGRESS) {
-                               err = EACCES;
-                               close = true;
-                       } else {
-                               err = 0;
-                       }
                } else if (strv_contains_prefix(auth_failures, str)) {
                        connman_warn("authentication failed: %s", str);
                        err = EACCES;
                g_free(str);
        } else if (condition & (G_IO_ERR | G_IO_HUP)) {
                connman_info("Err channel termination");
-               close = true;
+               close_io_channel(data, source);
+               return G_SOURCE_REMOVE;
        }
  
        if (err) {
                switch (err) {
                case EACCES:
-                       clear_provider_credentials(data->provider);
+                       clear_provider_credentials(data->provider, true);
                        break;
                case ECONNREFUSED:
                        /*
                oc_connect_done(data, err);
        }
  
-       if (close) {
-               close_io_channel(data, source);
-               return G_SOURCE_REMOVE;
-       }
        return G_SOURCE_CONTINUE;
  }
  
- static int run_connect(struct oc_private_data *data)
+ static gboolean process_auth_form(void *user_data)
  {
-       struct vpn_provider *provider;
-       struct connman_task *task;
-       const char *vpnhost;
-       const char *vpncookie = NULL;
-       const char *username;
-       const char *password = NULL;
-       const char *certificate = NULL;
-       const char *private_key;
-       const char *setting_str;
-       bool setting;
-       bool use_stdout = false;
-       int fd_out = -1;
-       int fd_err;
-       int err = 0;
-       if (!data)
-               return -EINVAL;
+       struct process_form_data *form_data = user_data;
+       struct oc_private_data *data = form_data->data;
+       struct oc_form_opt *opt;
+       const char *password;
  
-       provider = data->provider;
-       task = data->task;
+       g_mutex_lock(&form_data->mutex);
  
-       connman_info("provider %p task %p", provider, task);
+       DBG("");
  
        switch (data->connect_type) {
-       case OC_CONNECT_COOKIE:
-               vpncookie = vpn_provider_get_string(provider,
-                                       "OpenConnect.Cookie");
-               if (!vpncookie || !g_strcmp0(vpncookie, "-")) {
-                       err = -EACCES;
-                       goto done;
-               }
-               connman_task_add_argument(task, "--cookie-on-stdin", NULL);
-               break;
+       case OC_CONNECT_USERPASS:
        case OC_CONNECT_COOKIE_WITH_USERPASS:
-               vpncookie = vpn_provider_get_string(provider,
-                                       "OpenConnect.Cookie");
-               /* No cookie set yet, username and password used first */
-               if (!vpncookie || !g_strcmp0(vpncookie, "-")) {
-                       username = vpn_provider_get_string(provider,
-                                               "OpenConnect.Username");
-                       password = vpn_provider_get_string(provider,
-                                               "OpenConnect.Password");
-                       if (!username || !password ||
-                                               !g_strcmp0(username, "-") ||
-                                               !g_strcmp0(password, "-")) {
-                               err = -EACCES;
-                               goto done;
-                       }
+               break;
+       case OC_CONNECT_PKCS:
+               password = vpn_provider_get_string(data->provider,
+                                       "OpenConnect.PKCSPassword");
  
-                       connman_task_add_argument(task, "--cookieonly", NULL);
-                       connman_task_add_argument(task, "--user", username);
-                       connman_task_add_argument(task, "--passwd-on-stdin",
-                                               NULL);
+               for (opt = form_data->form->opts; opt; opt = opt->next) {
+                       if (opt->flags & OC_FORM_OPT_IGNORE)
+                               continue;
  
-                       /* Use stdout only when cookie is to be read. */
-                       use_stdout = true;
-               } else {
-                       connman_task_add_argument(task, "--cookie-on-stdin",
-                                               NULL);
+                       if (opt->type == OC_FORM_OPT_PASSWORD &&
+                                       g_str_has_prefix(opt->name,
+                                                       "openconnect_pkcs"))
+                               break;
                }
  
-               break;
-       case OC_CONNECT_USERPASS:
-               username = vpn_provider_get_string(provider,
-                                       "OpenConnect.Username");
-               password = vpn_provider_get_string(provider,
-                                       "OpenConnect.Password");
-               if (!username || !password || !g_strcmp0(username, "-") ||
-                                       !g_strcmp0(password, "-")) {
-                       err = -EACCES;
-                       goto done;
+               if (opt) {
+                       if (password && g_strcmp0(password, "-")) {
+                               opt->_value = strdup(password);
+                               data->tried_passphrase = true;
+                               form_data->status = OC_FORM_RESULT_OK;
+                               goto out;
+                       } else {
+                               if (data->tried_passphrase) {
+                                       vpn_provider_add_error(data->provider,
+                                              VPN_PROVIDER_ERROR_AUTH_FAILED);
+                                       clear_provider_credentials(
+                                                               data->provider,
+                                                               true);
+                               }
+                               request_input_credentials_full(data,
+                                               request_input_pkcs_reply,
+                                               form_data);
+                               return G_SOURCE_REMOVE;
+                       }
                }
  
-               connman_task_add_argument(task, "--user", username);
-               connman_task_add_argument(task, "--passwd-on-stdin", NULL);
-               break;
+               /* fall-through */
+       /*
+        * In case of public key, reaching here means that the
+        * passphrase previously provided was incorrect.
+        */
        case OC_CONNECT_PUBLICKEY:
-               certificate = vpn_provider_get_string(provider,
-                                       "OpenConnect.ClientCert");
-               private_key = vpn_provider_get_string(provider,
-                                       "OpenConnect.UserPrivateKey");
+               data->err = -EACCES;
+               clear_provider_credentials(data->provider, true);
  
-               if (!certificate || !private_key) {
-                       err = -EACCES;
-                       goto done;
-               }
+               /* fall-through */
+       default:
+               form_data->status = OC_FORM_RESULT_ERR;
+               goto out;
+       }
  
-               connman_task_add_argument(task, "--certificate", certificate);
-               connman_task_add_argument(task, "--sslkey", private_key);
-               break;
-       case OC_CONNECT_PKCS:
-               certificate = vpn_provider_get_string(provider,
-                                       "OpenConnect.PKCSClientCert");
-               if (!certificate) {
-                       err = -EACCES;
-                       goto done;
+       /*
+        * Form values are released with free(), so always use strdup()
+        * instead of g_strdup()
+        */
+       for (opt = form_data->form->opts; opt; opt = opt->next) {
+               if (opt->flags & OC_FORM_OPT_IGNORE)
+                       continue;
+               if (opt->type == OC_FORM_OPT_TEXT &&
+                               g_str_has_prefix(opt->name, "user")) {
+                       const char *user = vpn_provider_get_string(
+                                               data->provider,
+                                               "OpenConnect.Username");
+                       if (user)
+                               opt->_value = strdup(user);
+               } else if (opt->type == OC_FORM_OPT_PASSWORD) {
+                       const char *pass = vpn_provider_get_string(
+                                               data->provider,
+                                               "OpenConnect.Password");
+                       if (pass)
+                               opt->_value = strdup(pass);
                }
+       }
  
-               connman_task_add_argument(task, "--certificate", certificate);
+       form_data->status = OC_FORM_RESULT_OK;
  
-               password = vpn_provider_get_string(data->provider,
-                                       "OpenConnect.PKCSPassword");
-               /* Add password only if it is has been set */
-               if (!password || !g_strcmp0(password, "-"))
-                       break;
+ out:
+       form_data->processed = true;
+       g_cond_signal(&form_data->cond);
+       g_mutex_unlock(&form_data->mutex);
+       return G_SOURCE_REMOVE;
+ }
+ static int oc_process_auth_form(void *user_data, struct oc_auth_form *form)
+ {
+       struct process_form_data data = { .form = form,
+                                               .data = user_data,
+                                               .processed = false };
+       DBG("");
+       g_cond_init(&data.cond);
+       g_mutex_init(&data.mutex);
+       g_mutex_lock(&data.mutex);
+       g_idle_add(process_auth_form, &data);
+       while (!data.processed)
+               g_cond_wait(&data.cond, &data.mutex);
+       g_mutex_unlock(&data.mutex);
+       g_mutex_clear(&data.mutex);
+       g_cond_clear(&data.cond);
+       return data.status;
+ }
+ static gboolean authenticated(void *user_data)
+ {
+       struct oc_private_data *data = user_data;
+       int rv = GPOINTER_TO_INT(g_thread_join(data->cookie_thread));
+       DBG("");
+       data->cookie_thread = NULL;
+       if (rv == 0)
+               rv = run_connect(data, openconnect_get_cookie(data->vpninfo));
+       else if (rv < 0)
+               clear_provider_credentials(data->provider, true);
+       openconnect_vpninfo_free(data->vpninfo);
+       data->vpninfo = NULL;
+       if (rv != -EINPROGRESS) {
+               oc_connect_done(data, data->err ? data->err : rv);
+               free_private_data(data);
+       }
  
-               connman_task_add_argument(task, "--passwd-on-stdin", NULL);
+       return G_SOURCE_REMOVE;
+ }
+ static void *obtain_cookie_thread(void *user_data)
+ {
+       struct oc_private_data *data = user_data;
+       int ret;
+       DBG("%p", data->vpninfo);
+       ret = openconnect_obtain_cookie(data->vpninfo);
+       g_idle_add(authenticated, data);
+       return GINT_TO_POINTER(ret);
+ }
+ static int authenticate(struct oc_private_data *data)
+ {
+       const char *cert = NULL;
+       const char *key = NULL;
+       const char *urlpath;
+       const char *vpnhost;
+       DBG("");
+       switch (data->connect_type) {
+       case OC_CONNECT_PKCS:
+               cert = vpn_provider_get_string(data->provider,
+                                       "OpenConnect.PKCSClientCert");
                break;
+       case OC_CONNECT_PUBLICKEY:
+               cert = vpn_provider_get_string(data->provider,
+                                       "OpenConnect.ClientCert");
+               key = vpn_provider_get_string(data->provider,
+                                       "OpenConnect.UserPrivateKey");
+               break;
+       case OC_CONNECT_USERPASS:
+       case OC_CONNECT_COOKIE_WITH_USERPASS:
+               break;
+       default:
+               return -EINVAL;
        }
  
-       vpnhost = vpn_provider_get_string(provider, "OpenConnect.VPNHost");
+       openconnect_init_ssl();
+       data->vpninfo = openconnect_vpninfo_new("ConnMan VPN Agent",
+                       oc_validate_peer_cert,
+                       NULL,
+                       oc_process_auth_form,
+                       oc_progress,
+                       data);
+       /* Replicating how openconnect's --usergroup argument works */
+       urlpath = vpn_provider_get_string(data->provider,
+                                               "OpenConnect.Usergroup");
+       if (urlpath)
+               openconnect_set_urlpath(data->vpninfo, urlpath);
+       if (vpn_provider_get_boolean(data->provider,
+                                       "OpenConnect.DisableIPv6", false))
+               openconnect_disable_ipv6(data->vpninfo);
+       vpnhost = vpn_provider_get_string(data->provider,
+                                               "OpenConnect.VPNHost");
        if (!vpnhost || !*vpnhost)
-               vpnhost = vpn_provider_get_string(provider, "Host");
+               vpnhost = vpn_provider_get_string(data->provider, "Host");
  
-       task_append_config_data(provider, task);
+       openconnect_set_hostname(data->vpninfo, vpnhost);
+       if (cert)
+               openconnect_set_client_cert(data->vpninfo, cert, key);
+       data->fd_cmd = openconnect_setup_cmd_pipe(data->vpninfo);
  
        /*
-        * To clarify complex situation, if cookie is expected to be printed
-        * to stdout all other output must go to syslog. But with PKCS all
-        * output must be caught in order to get message about file decryption
-        * error. For this reason, the mode has to be interactive as well.
+        * openconnect_obtain_cookie blocks, so run it in background thread
+        * instead
         */
-       switch (data->connect_type) {
-       case OC_CONNECT_COOKIE:
-               /* fall through */
-       case OC_CONNECT_COOKIE_WITH_USERPASS:
-               /* fall through */
-       case OC_CONNECT_USERPASS:
-               /* fall through */
-       case OC_CONNECT_PUBLICKEY:
-               connman_task_add_argument(task, "--syslog", NULL);
+       data->cookie_thread = g_thread_try_new("obtain_cookie",
+                                                       obtain_cookie_thread,
+                                                       data, NULL);
+       if (!data->cookie_thread)
+               return -EIO;
+       return -EINPROGRESS;
+ }
  
-               setting = vpn_provider_get_boolean(provider,
+ static int run_connect(struct oc_private_data *data, const char *cookie)
+ {
+       struct vpn_provider *provider;
+       struct connman_task *task;
+       const char *vpnhost;
+       int fd_err;
+       int err = 0;
+       bool allow_self_signed;
+       const char *server_cert;
+       if (!data || !cookie)
+               return -EINVAL;
+       provider = data->provider;
+       task = data->task;
+       server_cert = vpn_provider_get_string(provider,
+                                               "OpenConnect.ServerCert");
+       allow_self_signed = vpn_provider_get_boolean(provider,
                                        "OpenConnect.AllowSelfSignedCert",
                                        false);
-               setting_str = vpn_provider_get_string(provider,
-                                       "OpenConnect.ServerCert");
  
-               /*
-                * Run in interactive mode if self signed certificates are
-                * allowed and there is no set server SHA1 fingerprint.
-                */
-               if (setting_str || !setting)
-                       connman_task_add_argument(task, "--non-inter", NULL);
-               else
-                       data->interactive = true;
-               break;
-       case OC_CONNECT_PKCS:
-               data->interactive = true;
-               break;
-       }
+       DBG("provider %p task %p", provider, task);
+       connman_task_add_argument(task, "--cookie-on-stdin", NULL);
+       vpnhost = vpn_provider_get_string(provider, "OpenConnect.VPNHost");
+       if (!vpnhost || !*vpnhost)
+               vpnhost = vpn_provider_get_string(provider, "Host");
+       task_append_config_data(provider, task);
  
        connman_task_add_argument(task, "--script", SCRIPTDIR "/vpn-script");
  
  
        connman_task_add_argument(task, (char *)vpnhost, NULL);
  
-       err = connman_task_run(task, oc_died, data, &data->fd_in, use_stdout ?
-                               &fd_out : NULL, &fd_err);
+       err = connman_task_run(task, oc_died, data, &data->fd_in,
+                               NULL, &fd_err);
        if (err < 0) {
                err = -EIO;
                goto done;
        }
  
-       switch (data->connect_type) {
-       case OC_CONNECT_COOKIE:
-               if (write_data(data->fd_in, vpncookie) != 0) {
-                       connman_error("openconnect failed to take cookie on "
-                                               "stdin");
-                       err = -EIO;
-               }
-               break;
-       case OC_CONNECT_USERPASS:
-               if (write_data(data->fd_in, password) != 0) {
-                       connman_error("openconnect failed to take password on "
-                                               "stdin");
-                       err = -EIO;
-               }
-               break;
-       case OC_CONNECT_COOKIE_WITH_USERPASS:
-               if (!vpncookie || !g_strcmp0(vpncookie, "-")) {
-                       if (write_data(data->fd_in, password) != 0) {
-                               connman_error("openconnect failed to take "
-                                                       "password on stdin");
-                               err = -EIO;
-                       }
-               } else {
-                       if (write_data(data->fd_in, vpncookie) != 0) {
-                               connman_error("openconnect failed to take "
-                                                       "cookie on stdin");
-                               err = -EIO;
-                       }
-               }
-               break;
-       case OC_CONNECT_PUBLICKEY:
-               break;
-       case OC_CONNECT_PKCS:
-               if (!password || !g_strcmp0(password, "-"))
-                       break;
+       if (write_data(data->fd_in, cookie) != 0) {
+               connman_error("openconnect failed to take cookie on "
+                               "stdin");
+               err = -EIO;
+       }
  
-               if (write_data(data->fd_in, password) != 0) {
-                       connman_error("openconnect failed to take PKCS "
-                                               "pass phrase on stdin");
+       if (!server_cert || !allow_self_signed) {
+               if (write_data(data->fd_in,
+                                       (allow_self_signed ? "yes" : "no"))) {
+                       connman_error("openconnect failed to take certificate "
+                                       "acknowledgement on stdin");
                        err = -EIO;
                }
-               break;
        }
  
        if (err) {
-               if (fd_out > 0)
-                       close(fd_out);
-               if (fd_err > 0)
+               if (fd_err >= 0)
                        close(fd_err);
  
                goto done;
  
        err = -EINPROGRESS;
  
-       if (use_stdout) {
-               data->out_ch = g_io_channel_unix_new(fd_out);
-               /* Use ASCII encoding only */
-               if (g_io_channel_set_encoding(data->out_ch, NULL, NULL) !=
-                                       G_IO_STATUS_NORMAL) {
-                       close_io_channel(data, data->out_ch);
-                       err = -EIO;
-               } else {
-                       data->out_ch_id = g_io_add_watch(data->out_ch,
-                                               G_IO_IN | G_IO_ERR | G_IO_HUP,
-                                               (GIOFunc)io_channel_out_cb,
-                                               data);
-               }
-       }
        data->err_ch = g_io_channel_unix_new(fd_err);
  
        /* Use ASCII encoding only */
        }
  
  done:
-       clear_provider_credentials(data->provider);
+       clear_provider_credentials(data->provider, err != -EINPROGRESS);
  
        return err;
  }
@@@ -1119,8 -1208,10 +1208,10 @@@ static void request_input_credentials_r
  
        connman_info("provider %p", data->provider);
  
-       if (!reply)
+       if (!reply) {
+               err = ENOENT;
                goto err;
+       }
  
        err = vpn_agent_check_and_process_reply_error(reply, data->provider,
                                data->task, data->cb, data->user_data);
                goto out;
        }
  
-       if (!vpn_agent_check_reply_has_dict(reply))
+       if (!vpn_agent_check_reply_has_dict(reply)) {
+               err = ENOENT;
                goto err;
+       }
  
        dbus_message_iter_init(reply, &iter);
        dbus_message_iter_recurse(&iter, &dict);
  
        switch (data->connect_type) {
        case OC_CONNECT_COOKIE:
-               if (!cookie)
+               if (!cookie) {
+                       err = EACCES;
                        goto err;
+               }
  
                break;
        case OC_CONNECT_USERPASS:
                /* fall through */
        case OC_CONNECT_COOKIE_WITH_USERPASS:
-               if (!username || !password)
+               if (!username || !password) {
+                       err = EACCES;
                        goto err;
+               }
  
                break;
        case OC_CONNECT_PUBLICKEY:
                break; // This should not be reached.
        case OC_CONNECT_PKCS:
-               if (!pkcspassword)
+               if (!pkcspassword) {
+                       err = EACCES;
                        goto err;
+               }
  
                break;
        }
  
-       err = run_connect(data);
+       if (cookie)
+               err = run_connect(data, cookie);
+       else
+               err = authenticate(data);
        if (err != -EINPROGRESS)
                goto err;
  
        return;
  
  err:
-       oc_connect_done(data, EACCES);
+       oc_connect_done(data, err);
  
  out:
        free_private_data(data);
  }
  
- static int request_input_credentials(struct oc_private_data *data,
-                       request_input_reply_cb_t cb)
+ static int request_input_credentials_full(
+                       struct oc_private_data *data,
+                       request_input_reply_cb_t cb,
+                       void *user_data)
  {
        DBusMessage *message;
        const char *path;
  
        /*
         * For backwards compatibility add OpenConnect.ServerCert and
-        * OpenConnect.VPNHost as madnatory only in the default authentication
+        * OpenConnect.VPNHost as mandatory only in the default authentication
         * mode. Otherwise. add the fields as informational. These should be
         * set in provider settings and not to be queried with every connection
         * attempt.
                                request_input_append_informational,
                                "OpenConnect.PKCSClientCert");
  
+               /* Do not allow to store or retrieve the encrypted PKCS pass */
+               vpn_agent_append_allow_credential_storage(&dict, false);
+               vpn_agent_append_allow_credential_retrieval(&dict, false);
+               /*
+                * Indicate to keep credentials, the PKCS password should not
+                * affect the credential storing.
+                */
+               vpn_agent_append_keep_credentials(&dict, true);
                request_input_append_to_dict(data->provider, &dict,
                                        request_input_append_password,
                                        "OpenConnect.PKCSPassword");
        connman_dbus_dict_close(&iter, &dict);
  
        err = connman_agent_queue_message(data->provider, message,
-                       connman_timeout_input_request(), cb, data, agent);
+                       connman_timeout_input_request(), cb, user_data, agent);
  
        dbus_message_unref(message);
  
        return -EINPROGRESS;
  }
  
+ static int request_input_credentials(struct oc_private_data *data,
+                       request_input_reply_cb_t cb)
+ {
+       return request_input_credentials_full(data, cb, data);
+ }
  static enum oc_connect_type get_authentication_type(
                        struct vpn_provider *provider)
  {
@@@ -1395,7 -1516,7 +1516,7 @@@ static int oc_connect(struct vpn_provid
                        const char *dbus_sender, void *user_data)
  {
        struct oc_private_data *data;
-       const char *vpncookie;
+       const char *vpncookie = NULL;
        const char *certificate;
        const char *username;
        const char *password;
                break;
        }
  
-       return run_connect(data);
+       if (vpncookie && g_strcmp0(vpncookie, "-"))
+               return run_connect(data, vpncookie);
+       return authenticate(data);
  
  request_input:
        err = request_input_credentials(data, request_input_credentials_reply);
  
  static void oc_disconnect(struct vpn_provider *provider)
  {
+       struct oc_private_data *data;
        connman_info("provider %p", provider);
  
        if (!provider)
        * agent request to avoid having multiple ones visible.
        */
        connman_agent_cancel(provider);
+       data = vpn_provider_get_plugin_data(provider);
+       if (!data)
+               return;
+       if (data->cookie_thread) {
+               char cmd = OC_CMD_CANCEL;
+               int w = write(data->fd_cmd, &cmd, 1);
+               if (w != 1)
+                       DBG("Write failed, might be leaking a thread");
+       }
  }
  
  static int oc_save(struct vpn_provider *provider, GKeyFile *keyfile)
@@@ -1547,7 -1685,7 +1685,7 @@@ static int oc_error_code(struct vpn_pro
        switch (exit_code) {
        case 2:
                /* Cookie has failed */
-               clear_provider_credentials(provider);
+               clear_provider_credentials(provider, false);
                return VPN_PROVIDER_ERROR_LOGIN_FAILED;
        case 1:
                /* fall through */
  }
  
  static int oc_route_env_parse(struct vpn_provider *provider, const char *key,
-               int *family, unsigned long *idx, enum vpn_provider_route_type *type)
+               int *family, unsigned long *idx,
+               enum vpn_provider_route_type *type)
  {
        char *end;
        const char *start;
diff --combined vpn/plugins/openvpn.c
index ef0bf78,daf66cd..8c8d316
mode 100755,100644..100755
@@@ -51,7 -51,6 +51,6 @@@
  #include "../vpn-agent.h"
  
  #include "vpn.h"
- #include "../vpn.h"
  
  #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
  
@@@ -84,6 -83,9 +83,9 @@@ struct 
        { "OpenVPN.ConfigFile", "--config", 1 },
        { "OpenVPN.DeviceType", NULL, 1 },
        { "OpenVPN.Verb", "--verb", 1 },
+       { "OpenVPN.Ping", "--ping", 1},
+       { "OpenVPN.PingExit", "--ping-exit", 1},
+       { "OpenVPN.RemapUsr1", "--remap-usr1", 1},
  };
  
  struct ov_private_data {
@@@ -152,15 -154,8 +154,15 @@@ static struct nameserver_entry *ov_appe
                                options[2]) {
  
                entry = g_try_new(struct nameserver_entry, 1);
 +#if defined TIZEN_EXT
 +              if (!entry) {
 +                      g_strfreev(options);
 +                      return NULL;
 +              }
 +#else
                if (!entry)
                        return NULL;
 +#endif
  
                entry->nameserver = g_strdup(options[2]);
                entry->id = atoi(key + 15); /* foreign_option_XXX */
@@@ -297,6 -292,7 +299,7 @@@ static int ov_notify(DBusMessage *msg, 
  
        connman_ipaddress_set_ipv4(ipaddress, address, netmask, gateway);
        connman_ipaddress_set_peer(ipaddress, peer);
+       connman_ipaddress_set_p2p(ipaddress, true);
        vpn_provider_set_ipaddress(provider, ipaddress);
  
        if (nameserver_list) {
@@@ -500,22 -496,17 +503,19 @@@ 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
         * trying to resolve the OpenVPN servers address.
-        */
-       connman_task_add_argument(task, "--ping-restart", "0");
-       /*
+        *
         * Disable connetion retrying when OpenVPN is connected over TCP.
         * With TCP OpenVPN attempts to handle reconnection silently without
         * reporting the error back when establishing a connection or
         * including DNS.
        */
        option = vpn_provider_get_string(provider, "OpenVPN.Proto");
-       if (option && g_str_has_prefix(option, "tcp"))
+       if (option && g_str_has_prefix(option, "tcp")) {
+               option = vpn_provider_get_string(provider, "OpenVPN.PingExit");
+               if (!option)
+                       connman_task_add_argument(task, "--ping-restart", "0");
                connman_task_add_argument(task, "--connect-retry-max", "1");
+       /* Apply defaults for --ping and --ping-exit only with UDP protocol. */
+       } else {
+               /* Apply default of 10 second interval for ping if omitted. */
+               option = vpn_provider_get_string(provider, "OpenVPN.Ping");
+               if (!option)
+                       connman_task_add_argument(task, "--ping", "10");
+               /* Apply default of 60 seconds for ping exit if omitted. */
+               option = vpn_provider_get_string(provider, "OpenVPN.PingExit");
+               if (!option)
+                       connman_task_add_argument(task, "--ping-exit", "60");
+       }
  
        err = connman_task_run(task, ov_died, data, NULL, NULL, NULL);
        if (err < 0) {
diff --combined vpn/plugins/pptp.c
index 5fc861e,4a704bb..4a704bb
mode 100755,100644..100755
  enum {
        OPT_STRING = 1,
        OPT_BOOL = 2,
+       OPT_PPTP_ONLY = 3,
  };
  
  struct {
        const char *cm_opt;
        const char *pptp_opt;
-       const char *vpnc_default;
+       const char *pptp_default;
        int type;
  } pptp_options[] = {
        { "PPTP.User", "user", NULL, OPT_STRING },
+       { "PPTP.IdleWait", "--idle-wait", NULL, OPT_PPTP_ONLY},
+       { "PPTP.MaxEchoWait", "--max-echo-wait", NULL, OPT_PPTP_ONLY},
        { "PPPD.EchoFailure", "lcp-echo-failure", "0", OPT_STRING },
        { "PPPD.EchoInterval", "lcp-echo-interval", "0", OPT_STRING },
        { "PPPD.Debug", "debug", NULL, OPT_STRING },
@@@ -204,6 -207,7 +207,7 @@@ static int pptp_notify(DBusMessage *msg
                connman_ipaddress_set_ipv4(ipaddress, addressv4, netmask,
                                        gateway);
  
+       connman_ipaddress_set_p2p(ipaddress, true);
        vpn_provider_set_ipaddress(provider, ipaddress);
        vpn_provider_set_nameservers(provider, nameservers);
  
@@@ -436,7 -440,9 +440,9 @@@ static int run_connect(struct vpn_provi
                        vpn_provider_connect_cb_t cb, void *user_data,
                        const char *username, const char *password)
  {
-       const char *opt_s, *host;
+       GString *pptp_opt_s;
+       const char *opt_s;
+       const char *host;
        char *str;
        int err, i;
  
        DBG("username %s password %p", username, password);
  
        host = vpn_provider_get_string(provider, "Host");
-       str = g_strdup_printf("%s %s --nolaunchpppd --loglevel 2",
-                               PPTP, host);
-       if (!str) {
-               connman_error("can not allocate memory");
-               err = -ENOMEM;
-               goto done;
-       }
  
-       connman_task_add_argument(task, "pty", str);
-       g_free(str);
+       /* Create PPTP options for pppd "pty" */
+       pptp_opt_s = g_string_new(NULL);
+       g_string_append_printf(pptp_opt_s, "%s %s --nolaunchpppd --loglevel 2",
+                               PPTP, host);
  
        connman_task_add_argument(task, "nodetach", NULL);
        connman_task_add_argument(task, "lock", NULL);
                opt_s = vpn_provider_get_string(provider,
                                        pptp_options[i].cm_opt);
                if (!opt_s)
-                       opt_s = pptp_options[i].vpnc_default;
+                       opt_s = pptp_options[i].pptp_default;
  
                if (!opt_s)
                        continue;
                else if (pptp_options[i].type == OPT_BOOL)
                        pptp_write_bool_option(task,
                                        pptp_options[i].pptp_opt, opt_s);
+               else if (pptp_options[i].type == OPT_PPTP_ONLY)
+                       g_string_append_printf(pptp_opt_s, " %s %s",
+                                       pptp_options[i].pptp_opt, opt_s);
        }
  
+       str = g_string_free(pptp_opt_s, FALSE);
+       connman_task_add_argument(task, "pty", str);
+       g_free(str);
        connman_task_add_argument(task, "plugin",
                                SCRIPTDIR "/libppp-plugin.so");
  
diff --combined vpn/plugins/vpn.c
index c0b2977,cb0d304..b89c222
mode 100755,100644..100755
@@@ -65,7 -65,7 +65,7 @@@ struct vpn_data 
  struct vpn_driver_data {
        const char *name;
        const char *program;
-       struct vpn_driver *vpn_driver;
+       const struct vpn_driver *vpn_driver;
        struct vpn_provider_driver provider_driver;
  };
  
@@@ -349,56 -349,6 +349,56 @@@ static DBusMessage *vpn_notify(struct c
        return NULL;
  }
  
 +#if defined TIZEN_EXT
 +static void vpn_event(struct vpn_provider *provider, int state)
 +{
 +      struct vpn_driver_data *vpn_driver_data;
 +      const char *name;
 +
 +      name = vpn_provider_get_driver_name(provider);
 +      if (!name) {
 +              DBG("Cannot find VPN driver for provider %p", provider);
 +              vpn_provider_set_state(provider, VPN_PROVIDER_STATE_FAILURE);
 +              return;
 +      }
 +
 +      vpn_driver_data = g_hash_table_lookup(driver_hash, name);
 +      if (!vpn_driver_data) {
 +              DBG("Cannot find VPN driver data for name %s", name);
 +              vpn_provider_set_state(provider, VPN_PROVIDER_STATE_FAILURE);
 +              return;
 +      }
 +
 +      DBG("provider %p driver %s state %d", provider, name, state);
 +
 +      switch (state) {
 +      case VPN_STATE_CONNECT:
 +              vpn_provider_set_state(provider,
 +                              VPN_PROVIDER_STATE_CONNECT);
 +              break;
 +      case VPN_STATE_READY:
 +              vpn_provider_set_state(provider,
 +                              VPN_PROVIDER_STATE_READY);
 +              break;
 +
 +      case VPN_STATE_UNKNOWN:
 +      case VPN_STATE_IDLE:
 +      case VPN_STATE_DISCONNECT:
 +      case VPN_STATE_FAILURE:
 +              vpn_provider_set_state(provider,
 +                                      VPN_PROVIDER_STATE_DISCONNECT);
 +              break;
 +
 +      case VPN_STATE_AUTH_FAILURE:
 +              vpn_provider_indicate_error(provider,
 +                                      VPN_PROVIDER_ERROR_AUTH_FAILED);
 +              break;
 +      }
 +
 +      return;
 +}
 +#endif
 +
  static int vpn_create_tun(struct vpn_provider *provider, int flags)
  {
        struct vpn_data *data = vpn_provider_get_data(provider);
@@@ -471,61 -421,26 +471,26 @@@ exist_err
        return ret;
  }
  
- static gboolean is_numeric(const char *str)
+ static gid_t get_gid(const char *group_name)
  {
-       gint i;
-       if(!str || !(*str))
-               return false;
-       for(i = 0; str[i] ; i++) {
-               if(!g_ascii_isdigit(str[i]))
-                       return false;
-       }
-       return true;
- }
- static gint get_gid(const char *group_name)
- {
-       gint gid = -1;
        struct group *grp;
  
-       if(!group_name || !(*group_name))
-               return gid;
-       if (is_numeric(group_name)) {
-               gid_t group_id = (gid_t)g_ascii_strtoull(group_name, NULL, 10);
-               grp = getgrgid(group_id);
-       } else {
-               grp = getgrnam(group_name);
-       }
+       grp = vpn_util_get_group(group_name);
        if (grp)
-               gid = grp->gr_gid;
+               return grp->gr_gid;
  
-       return gid;
+       return -1;
  }
  
- static gint get_uid(const char *user_name)
+ static uid_t get_uid(const char *user_name)
  {
-       gint uid = -1;
        struct passwd *pw;
  
-       if(!user_name || !(*user_name))
-               return uid;
-       if (is_numeric(user_name)) {
-               uid_t user_id = (uid_t)g_ascii_strtoull(user_name, NULL, 10);
-               pw = getpwuid(user_id);
-       } else {
-               pw = getpwnam(user_name);
-       }
+       pw = vpn_util_get_passwd(user_name);
        if (pw)
-               uid = pw->pw_uid;
+               return pw->pw_uid;
  
-       return uid;
+       return -1;
  }
  
  static gint get_supplementary_gids(gchar **groups, gid_t **gid_list)
  static void vpn_task_setup(gpointer user_data)
  {
        struct vpn_plugin_data *data;
-       gint uid;
-       gint gid;
+       uid_t uid;
+       gid_t gid;
        gid_t *gid_list = NULL;
        size_t gid_list_size;
        const gchar *user;
@@@ -682,7 -597,7 +647,7 @@@ static int vpn_connect(struct vpn_provi
                        vpn_driver_data->vpn_driver->flags & VPN_FLAG_NO_DAEMON) {
  
                ret = vpn_driver_data->vpn_driver->connect(provider,
-                                               NULL, NULL, NULL, NULL, NULL);
+                                       NULL, NULL, cb, dbus_sender, user_data);
                if (ret) {
                        stop_vpn(provider);
                        goto exist_err;
                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);
@@@ -868,7 -777,7 +832,7 @@@ static int vpn_route_env_parse(struct v
        return 0;
  }
  
- int vpn_register(const char *name, struct vpn_driver *vpn_driver,
+ int vpn_register(const char *name, const struct vpn_driver *vpn_driver,
                        const char *program)
  {
        struct vpn_driver_data *data;
diff --combined vpn/plugins/vpn.h
index 893e9a1,fd10add..7956ffa
mode 100755,100644..100755
@@@ -41,16 -41,9 +41,16 @@@ enum vpn_state 
        VPN_STATE_AUTH_FAILURE  = 6,
  };
  
 +#if defined TIZEN_EXT
 +typedef void (*vpn_event_callback)(struct vpn_provider *provider, int state);
 +#endif
 +
  struct vpn_driver {
        int flags;
        int (*notify) (DBusMessage *msg, struct vpn_provider *provider);
 +#if defined TIZEN_EXT
 +      void (*set_event_cb) (vpn_event_callback event_cb, struct vpn_provider *provider);
 +#endif
        int (*connect) (struct vpn_provider *provider,
                        struct connman_task *task, const char *if_name,
                        vpn_provider_connect_cb_t cb, const char *dbus_sender,
@@@ -65,7 -58,7 +65,7 @@@
                        enum vpn_provider_route_type *type);
  };
  
- int vpn_register(const char *name, struct vpn_driver *driver,
+ int vpn_register(const char *name, const struct vpn_driver *driver,
                        const char *program);
  void vpn_unregister(const char *provider_name);
  void vpn_died(struct connman_task *task, int exit_code, void *user_data);
diff --combined vpn/plugins/vpnc.c
index 8350fc3,d11b911..d11b911
mode 100755,100644..100755
  #include <stdio.h>
  #include <net/if.h>
  #include <linux/if_tun.h>
+ #include <sys/types.h>
+ #include <pwd.h>
+ #include <grp.h>
+ #include <fcntl.h>
  
  #include <glib.h>
  
@@@ -50,6 -54,7 +54,7 @@@
  #include "../vpn.h"
  
  #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
+ #define PID_PATH_ROOT "/var/run/user"
  
  enum {
        OPT_STRING = 1,
@@@ -240,6 -245,7 +245,7 @@@ static int vc_notify(DBusMessage *msg, 
        }
  
        connman_ipaddress_set_ipv4(ipaddress, address, netmask, gateway);
+       connman_ipaddress_set_p2p(ipaddress, true);
        vpn_provider_set_ipaddress(provider, ipaddress);
  
        g_free(address);
@@@ -430,14 -436,49 +436,49 @@@ static gboolean io_channel_cb(GIOChanne
        return G_SOURCE_CONTINUE;
  }
  
+ static char *create_pid_path(const char *user, const char *group)
+ {
+       struct passwd *pwd;
+       struct group *grp;
+       char *uid_str;
+       char *pid_path = NULL;
+       int mode = S_IRWXU|S_IRWXG;
+       gid_t gid;
+       if (!user || !*user)
+               return NULL;
+       if (vpn_settings_is_system_user(user))
+               return NULL;
+       pwd = vpn_util_get_passwd(user);
+       uid_str = g_strdup_printf("%d", pwd->pw_uid);
+       grp = vpn_util_get_group(group);
+       gid = grp ? grp->gr_gid : pwd->pw_gid;
+       pid_path = g_build_filename(PID_PATH_ROOT, uid_str, "vpnc", "pid",
+                               NULL);
+       if (vpn_util_create_path(pid_path, pwd->pw_uid, gid, mode)) {
+               g_free(pid_path);
+               pid_path = NULL;
+       }
+       g_free(uid_str);
+       return pid_path;
+ }
  static int run_connect(struct vc_private_data *data)
  {
        struct vpn_provider *provider;
        struct connman_task *task;
+       struct vpn_plugin_data *plugin_data;
        const char *credentials[] = {"VPNC.IPSec.Secret", "VPNC.Xauth.Username",
                                "VPNC.Xauth.Password", NULL};
        const char *if_name;
        const char *option;
+       char *pid_path;
        int err;
        int fd_in;
        int fd_err;
                connman_task_add_argument(task, "--ifmode", "tun");
        }
  
+       plugin_data = vpn_settings_get_vpn_plugin_config("vpnc");
+       option = vpn_settings_get_binary_user(plugin_data);
+       if (option) {
+               pid_path = create_pid_path(option,
+                                       vpn_settings_get_binary_group(
+                                               plugin_data));
+               if (pid_path)
+                       connman_task_add_argument(task, "--pid-file",
+                                                               pid_path);
+               g_free(pid_path);
+       }
        connman_task_add_argument(task, "--script", SCRIPTDIR "/vpn-script");
  
        option = vpn_provider_get_string(provider, "VPNC.Debug");
@@@ -619,8 -674,10 +674,10 @@@ static void request_input_credentials_r
  
        DBG("provider %p", data->provider);
  
-       if (!reply)
+       if (!reply) {
+               err = ENOENT;
                goto err;
+       }
  
        err = vpn_agent_check_and_process_reply_error(reply, data->provider,
                                data->task, data->cb, data->user_data);
                return;
        }
  
-       if (!vpn_agent_check_reply_has_dict(reply))
+       if (!vpn_agent_check_reply_has_dict(reply)) {
+               err = ENOENT;
                goto err;
+       }
  
        dbus_message_iter_init(reply, &iter);
        dbus_message_iter_recurse(&iter, &dict);
                dbus_message_iter_next(&dict);
        }
  
-       if (!secret || !username || !password)
+       if (!secret || !username || !password) {
+               vpn_provider_indicate_error(data->provider,
+                                       VPN_PROVIDER_ERROR_AUTH_FAILED);
+               err = EACCES;
                goto err;
+       }
  
-       err = run_connect(data);
-       if (err != -EINPROGRESS)
+       /* vpn_provider.c:connect_cb() expects positive errors */
+       err = -run_connect(data);
+       if (err != EINPROGRESS)
                goto err;
  
        return;
  
  err:
-       vc_connect_done(data, EACCES);
+       vc_connect_done(data, err);
  }
  
  static int request_input_credentials(struct vc_private_data *data,
diff --combined vpn/plugins/wireguard.c
@@@ -50,9 -50,6 +50,9 @@@
  #include "wireguard.h"
  
  #define DNS_RERESOLVE_TIMEOUT 20
 +#if defined TIZEN_EXT
 +#define ADD_ALLOWED_IP_ROUTE_TIMEOUT 2
 +#endif /* TIZEN_EXT */
  
  struct wireguard_info {
        struct wg_device device;
@@@ -60,9 -57,6 +60,9 @@@
        char *endpoint_fqdn;
        char *port;
        int reresolve_id;
 +#if defined TIZEN_EXT
 +      int allowed_ip_route_id;
 +#endif /* TIZEN_EXT */
  };
  
  struct sockaddr_u {
@@@ -100,49 -94,14 +100,49 @@@ static int parse_allowed_ips(const cha
        int i;
  
        curaip = NULL;
 +#if defined TIZEN_EXT
 +      /**
 +       * Note: At API level we donot check Wireguard specific configurations,
 +       * User can provide any space separated string for IP.
 +       * Ideally it should be using "10.0.0.2/32, 10.0.0.3/32"
 +       * However there can be cases like "10.0.0.2/32,10.0.0.3/32"
 +       *
 +       * So we need to parse the allowed_ips configuration properly.
 +       */
 +      tokens = g_strsplit(allowed_ips, ",", -1);
 +#else
        tokens = g_strsplit(allowed_ips, ", ", -1);
 +#endif
        for (i = 0; tokens[i]; i++) {
 +#if defined TIZEN_EXT
 +              int len = strlen(tokens[i]);
 +              char *ptr = tokens[i];
 +              int j = -1;
 +
 +              //skip forward spaces
 +              while (++j < len && ptr[j] == ' ')
 +                      ;// Do Nothing
 +
 +              if (!ptr[j])
 +                      continue;
 +
 +              toks = g_strsplit(ptr + j, "/", -1);
 +              if (g_strv_length(toks) != 2) {
 +                      DBG("Ignore AllowedIPs value [%s]", ptr + j);
 +                      g_strfreev(toks);
 +                      continue;
 +              }
 +
 +              DBG("Parsed AllowedIPs [%s]", ptr + j);
 +#else
 +
                toks = g_strsplit(tokens[i], "/", -1);
                if (g_strv_length(toks) != 2) {
                        DBG("Ignore AllowedIPs value %s", tokens[i]);
                        g_strfreev(toks);
                        continue;
                }
 +#endif
  
                allowedip = g_malloc0(sizeof(*allowedip));
  
                        allowedip->family = AF_INET6;
                        memcpy(&allowedip->ip6, buf, sizeof(allowedip->ip6));
                } else {
 +#if defined TIZEN_EXT
 +                      DBG("Ignore AllowedIPs value [%s]", ptr + j);
 +#else
                        DBG("Ignore AllowedIPs value %s", tokens[i]);
 +#endif
                        g_free(allowedip);
                        g_strfreev(toks);
                        continue;
                        curaip->next_allowedip = allowedip;
  
                curaip = allowedip;
 +#if defined TIZEN_EXT
 +              g_strfreev(toks);
 +#endif
        }
  
        peer->last_allowedip = curaip;
@@@ -260,6 -212,8 +260,8 @@@ static int parse_address(const char *ad
                err = -EINVAL;
        }
  
+       connman_ipaddress_set_p2p(*ipaddress, true);
        g_strfreev(tokens);
        if (err)
                connman_ipaddress_free(*ipaddress);
@@@ -317,143 -271,6 +319,143 @@@ static bool sockaddr_cmp_addr(struct so
        return false;
  }
  
 +#if defined TIZEN_EXT
 +#include <unistd.h>
 +#include <sys/types.h>
 +#include <sys/wait.h>
 +#include <stdio.h>
 +
 +#define MAX_SIZE_ERROR_BUFFER 256
 +#define MAX_CMD_SIZE 80
 +
 +typedef struct {
 +      struct vpn_provider *provider;
 +      struct wireguard_info *info;
 +} wg_allowed_ip_route_cb_data_s;
 +
 +static int wg_execute_cmd(const char *format, ...)
 +{
 +      int status = 0;
 +      int rv = 0;
 +      char cmd[MAX_CMD_SIZE] = { 0, };
 +      char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
 +      pid_t pid = 0;
 +      va_list va_ptr;
 +      gchar **args = NULL;
 +
 +      va_start(va_ptr, format);
 +      vsnprintf(cmd, (unsigned int) MAX_CMD_SIZE, format, va_ptr);
 +      va_end(va_ptr);
 +
 +      if (strlen(cmd) == 0)
 +              return -EIO;
 +
 +      DBG("command: %s", cmd);
 +
 +      args = g_strsplit_set(cmd, " ", -1);
 +
 +      errno = 0;
 +      if (!(pid = fork())) {
 +              DBG("pid(%d), ppid (%d)", getpid(), getppid());
 +
 +              errno = 0;
 +              if (execv(args[0], args) == -1) {
 +                      DBG("Fail to execute command (%s)",
 +                                      strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER));
 +                      g_strfreev(args);
 +                      exit(1);
 +              }
 +      } else if (pid > 0) {
 +              if (waitpid(pid, &status, 0) == -1)
 +                      DBG("wait pid (%u) status (%d)", pid, status);
 +
 +              if (WIFEXITED(status)) {
 +                      rv = WEXITSTATUS(status);
 +                      DBG("exited, status=%d", rv);
 +
 +              } else if (WIFSIGNALED(status)) {
 +                      DBG("killed by signal %d", WTERMSIG(status));
 +
 +              } else if (WIFSTOPPED(status)) {
 +                      DBG("stopped by signal %d", WSTOPSIG(status));
 +
 +              } else if (WIFCONTINUED(status)) {
 +                      DBG("continued");
 +              }
 +
 +              g_strfreev(args);
 +              return rv;
 +      }
 +
 +      DBG("failed to fork(%s)", strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER));
 +      g_strfreev(args);
 +
 +      return -EIO;
 +}
 +
 +static gboolean wg_add_allowed_ip_route_cb(gpointer user_data)
 +{
 +      wg_allowed_ip_route_cb_data_s *cb_data = user_data;
 +      const char *allowed_ips;
 +      char **tokens = NULL;
 +      char **toks = NULL;
 +      int i;
 +
 +      DBG("");
 +
 +      allowed_ips = vpn_provider_get_string(cb_data->provider, "WireGuard.AllowedIPs");
 +      if (!allowed_ips) {
 +              DBG("WireGuard.AllowedIPs is missing");
 +              goto done;
 +      }
 +
 +      tokens = g_strsplit(allowed_ips, ",", -1);
 +      if (g_strv_length(tokens) == 0)
 +              goto done;
 +
 +      for (i = 0; tokens[i]; i++) {
 +              int len = strlen(tokens[i]);
 +              char *ptr = tokens[i];
 +              int j = -1;
 +
 +              //skip forward spaces
 +              while (++j < len && ptr[j] == ' ')
 +                      ;// Do Nothing
 +
 +              if (!ptr[j])
 +                      continue;
 +
 +              toks = g_strsplit(ptr + j, "/", -1);
 +              if (g_strv_length(toks) != 2) {
 +                      DBG("Ignore AllowedIPs value [%s]", ptr + j);
 +                      g_strfreev(toks);
 +                      continue;
 +              }
 +              g_strfreev(toks);
 +
 +              DBG("Allowed IP: [%s], Device Name: [%s]", ptr + j, cb_data->info->device.name);
 +
 +              // TODO: Remove system call to add route entry present in wg_execute_cmd()
 +              if (!g_strcmp0("0.0.0.0/0", ptr + j)) {
 +                      // TODO: Update default route because user wants all data to be routed from wg0,
 +                      // when 0.0.0.0/0 is passed in allowed ips list.
 +                      // Should we replace the default route?
 +                      // If yes, then how to recover default route when wg0 tunnel is removed.
 +              } else {
 +                      wg_execute_cmd("/usr/sbin/ip route add %s dev %s", ptr + j, cb_data->info->device.name);
 +              }
 +      }
 +
 +done:
 +      if (tokens)
 +              g_strfreev(tokens);
 +
 +      free(cb_data);
 +
 +      return FALSE;
 +}
 +#endif /* TIZEN_EXT */
 +
  static gboolean wg_dns_reresolve_cb(gpointer user_data)
  {
        struct wireguard_info *info = user_data;
@@@ -617,24 -434,6 +619,24 @@@ done
  
        connman_ipaddress_free(ipaddress);
  
 +#if defined TIZEN_EXT
 +      if (!err) {
 +              const char *allowed_ips = vpn_provider_get_string(provider, "WireGuard.AllowedIPs");
 +              if (allowed_ips) {
 +                      wg_allowed_ip_route_cb_data_s *cb_data =
 +                              (wg_allowed_ip_route_cb_data_s *) calloc(1, sizeof(wg_allowed_ip_route_cb_data_s));
 +                      if (cb_data) {
 +                              cb_data->provider = provider;
 +                              cb_data->info = info;
 +
 +                              info->allowed_ip_route_id =
 +                                      g_timeout_add_seconds(ADD_ALLOWED_IP_ROUTE_TIMEOUT,
 +                                                      wg_add_allowed_ip_route_cb, cb_data);
 +                      }
 +              }
 +      }
 +#endif /* TIZEN_EXT */
 +
        if (!err)
                info->reresolve_id =
                        g_timeout_add_seconds(DNS_RERESOLVE_TIMEOUT,
@@@ -651,11 -450,6 +653,11 @@@ static void wg_disconnect(struct vpn_pr
        if (!info)
                return;
  
 +#if defined TIZEN_EXT
 +      if (info->allowed_ip_route_id > 0)
 +              g_source_remove(info->allowed_ip_route_id);
 +#endif /* TIZEN_EXT */
 +
        if (info->reresolve_id > 0)
                g_source_remove(info->reresolve_id);
  
        g_free(info);
  }
  
 +#if defined TIZEN_EXT
 +static int wg_save(struct vpn_provider *provider, GKeyFile *keyfile)
 +{
 +      const char *option;
 +
 +      DBG("");
 +
 +      /*
 +       * The client/own device listen port.
 +       */
 +      option = vpn_provider_get_string(provider, "WireGuard.ListenPort");
 +      if (option)
 +              g_key_file_set_string(keyfile,
 +                              vpn_provider_get_save_group(provider),
 +                              "WireGuard.ListenPort",
 +                              option);
 +
 +      /*
 +       * comma separated DNS.
 +       */
 +      option = vpn_provider_get_string(provider, "WireGuard.DNS");
 +      if (option)
 +              g_key_file_set_string(keyfile,
 +                              vpn_provider_get_save_group(provider),
 +                              "WireGuard.DNS",
 +                              option);
 +
 +      /*
 +       * The client private key.
 +       */
 +      option = vpn_provider_get_string(provider, "WireGuard.PrivateKey");
 +      if (option)
 +              g_key_file_set_string(keyfile,
 +                              vpn_provider_get_save_group(provider),
 +                              "WireGuard.PrivateKey",
 +                              option);
 +
 +      /*
 +       * The server public key.
 +       */
 +      option = vpn_provider_get_string(provider, "WireGuard.PublicKey");
 +      if (option)
 +              g_key_file_set_string(keyfile,
 +                              vpn_provider_get_save_group(provider),
 +                              "WireGuard.PublicKey",
 +                              option);
 +
 +      /*
 +       * The preshared key.
 +       */
 +      option = vpn_provider_get_string(provider, "WireGuard.PresharedKey");
 +      if (option)
 +              g_key_file_set_string(keyfile,
 +                              vpn_provider_get_save_group(provider),
 +                              "WireGuard.PresharedKey",
 +                              option);
 +
 +      /*
 +       * Subnets accessed via VPN tunnel, 0.0.0.0/0 routes all traffic.
 +       */
 +      option = vpn_provider_get_string(provider, "WireGuard.AllowedIPs");
 +      if (option)
 +              g_key_file_set_string(keyfile,
 +                              vpn_provider_get_save_group(provider),
 +                              "WireGuard.AllowedIPs",
 +                              option);
 +
 +      /*
 +       * The time in seconds to emit periodic keep alive message.
 +       */
 +      option = vpn_provider_get_string(provider, "WireGuard.PersistentKeepalive");
 +      if (option)
 +              g_key_file_set_string(keyfile,
 +                              vpn_provider_get_save_group(provider),
 +                              "WireGuard.PersistentKeepalive",
 +                              option);
 +
 +      /*
 +       * The server listen port, default: 51820
 +       */
 +      option = vpn_provider_get_string(provider, "WireGuard.EndpointPort");
 +      if (option)
 +              g_key_file_set_string(keyfile,
 +                              vpn_provider_get_save_group(provider),
 +                              "WireGuard.EndpointPort",
 +                              option);
 +
 +      /*
 +       * Save Address: The internal IP of the client node
 +       */
 +      option = vpn_provider_get_string(provider, "WireGuard.Address");
 +      if (option)
 +              g_key_file_set_string(keyfile,
 +                              vpn_provider_get_save_group(provider),
 +                              "WireGuard.Address",
 +                              option);
 +
 +      return 0;
 +}
 +#endif
 +
  static struct vpn_driver vpn_driver = {
        .flags          = VPN_FLAG_NO_TUN | VPN_FLAG_NO_DAEMON,
        .connect        = wg_connect,
        .disconnect     = wg_disconnect,
 +#if defined TIZEN_EXT
 +      .save           = wg_save,
 +#endif
  };
  
  static int wg_init(void)
diff --combined vpn/vpn-config.c
index 97e072c,8c6b068..e412b89
mode 100755,100644..100755
@@@ -203,11 -203,7 +203,11 @@@ static int load_provider(GKeyFile *keyf
                                struct vpn_config *config, enum what action)
  {
        struct vpn_config_provider *config_provider;
 +#if !defined TIZEN_EXT
        const char *ident, *host, *domain;
 +#else
 +      const char *ident, *host, *domain, *name;
 +#endif
        int err;
  
        /* Strip off "provider_" prefix */
  
        host = get_string(config_provider, "Host");
        domain = get_string(config_provider, "Domain");
 +#if !defined TIZEN_EXT
        if (host) {
                char *id = __vpn_provider_create_identifier(host, domain);
 +#else
 +      name = get_string(config_provider, "Name");
 +      if (host && name) {
 +              char *id = __vpn_provider_create_identifier(host, domain, name);
 +#endif
  
                struct vpn_provider *provider;
                provider = __vpn_provider_lookup(id);
  
                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;
        }
@@@ -594,3 -580,18 +594,18 @@@ char **__vpn_config_get_string_list(GKe
  
        return strlist;
  }
+ bool __vpn_config_get_boolean(GKeyFile *key_file, const char *group_name,
+                       const char *key, bool default_value)
+ {
+       GError *error = NULL;
+       bool val;
+       val = g_key_file_get_boolean(key_file, group_name, key, &error);
+       if (error) {
+               g_error_free(error);
+               return default_value;
+       }
+       return val;
+ }
diff --combined vpn/vpn-dbus.conf
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>
diff --combined vpn/vpn-ipconfig.c
index c4fa548,825b43c..825b43c
mode 100755,100644..100755
@@@ -211,7 -211,7 +211,7 @@@ int __vpn_ipconfig_address_add(struct v
  
        if (family == AF_INET)
                return connman_inet_set_address(ipconfig->index,
-                                               ipconfig->address);
+                                                       ipconfig->address);
        else if (family == AF_INET6)
                return connman_inet_set_ipv6_address(ipconfig->index,
                                                        ipconfig->address);
@@@ -282,7 -282,10 +282,10 @@@ static struct vpn_ipconfig *create_ipv6
                return NULL;
        }
  
+       connman_ipaddress_set_p2p(ipv6config->address, true);
        ipv6config->system = connman_ipaddress_alloc(AF_INET6);
+       connman_ipaddress_set_p2p(ipv6config->system, true);
  
        DBG("ipconfig %p", ipv6config);
  
@@@ -314,7 -317,10 +317,10 @@@ struct vpn_ipconfig *__vpn_ipconfig_cre
                return NULL;
        }
  
+       connman_ipaddress_set_p2p(ipconfig->address, true);
        ipconfig->system = connman_ipaddress_alloc(AF_INET);
+       connman_ipaddress_set_p2p(ipconfig->system, true);
  
        DBG("ipconfig %p", ipconfig);
  
diff --combined vpn/vpn-provider.c
index 6a6b661,59c805c..8092b5d
mode 100755,100644..100755
@@@ -44,7 -44,6 +44,6 @@@ static DBusConnection *connection
  static GHashTable *provider_hash;
  static GSList *driver_list;
  static int configuration_count;
- static bool handle_routes;
  
  struct vpn_route {
        int family;
@@@ -71,6 -70,7 +70,7 @@@ struct vpn_provider 
        char *host;
        char *domain;
        int family;
+       bool do_split_routing;
        GHashTable *routes;
        struct vpn_provider_driver *driver;
        void *driver_data;
@@@ -91,6 -91,7 +91,7 @@@
        void *plugin_data;
        unsigned int auth_error_counter;
        unsigned int conn_error_counter;
+       unsigned int signal_watch;
  };
  
  static void append_properties(DBusMessageIter *iter,
@@@ -366,22 -367,8 +367,8 @@@ static void set_user_networks(struct vp
  static void del_routes(struct vpn_provider *provider)
  {
        GHashTableIter hash;
-       gpointer value, key;
  
        g_hash_table_iter_init(&hash, provider->user_routes);
-       while (handle_routes && g_hash_table_iter_next(&hash,
-                                               &key, &value)) {
-               struct vpn_route *route = value;
-               if (route->family == AF_INET6) {
-                       unsigned char prefixlen = atoi(route->netmask);
-                       connman_inet_del_ipv6_network_route(provider->index,
-                                                       route->network,
-                                                       prefixlen);
-               } else
-                       connman_inet_del_host_route(provider->index,
-                                               route->network);
-       }
        g_hash_table_remove_all(provider->user_routes);
        g_slist_free_full(provider->user_networks, free_route);
        provider->user_networks = NULL;
@@@ -404,6 -391,16 +391,16 @@@ static void send_value(const char *path
                                        &str);
  }
  
+ static void send_value_boolean(const char *path, const char *key,
+                                                       dbus_bool_t value)
+ {
+       connman_dbus_property_changed_basic(path,
+                                       VPN_CONNECTION_INTERFACE,
+                                       key,
+                                       DBUS_TYPE_BOOLEAN,
+                                       &value);
+ }
  static gboolean provider_send_changed(gpointer data)
  {
        struct vpn_provider *provider = data;
@@@ -474,6 -471,11 +471,11 @@@ static bool compare_network_lists(GSLis
        return true;
  }
  
+ static const char *bool2str(bool value)
+ {
+       return value ? "true" : "false";
+ }
  static int set_provider_property(struct vpn_provider *provider,
                        const char *name, DBusMessageIter *value, int type)
  {
                del_routes(provider);
                provider->user_networks = networks;
                set_user_networks(provider, provider->user_networks);
+               send_routes(provider, provider->user_routes, "UserRoutes");
+       } else if (g_str_equal(name, "SplitRouting")) {
+               dbus_bool_t split_routing;
+               if (type != DBUS_TYPE_BOOLEAN)
+                       return -EINVAL;
  
-               if (!handle_routes)
-                       send_routes(provider, provider->user_routes,
-                                               "UserRoutes");
+               dbus_message_iter_get_basic(value, &split_routing);
+               DBG("property %s value %s ", name, bool2str(split_routing));
+               vpn_provider_set_boolean(provider, name, split_routing, false);
        } else {
                const char *str;
  
@@@ -576,8 -585,13 +585,13 @@@ static DBusMessage *set_properties(DBus
                dbus_message_iter_recurse(&entry, &value);
  
                type = dbus_message_iter_get_arg_type(&value);
-               /* Ignore and report back all invalid property types */
-               if (type != DBUS_TYPE_STRING && type != DBUS_TYPE_ARRAY) {
+               switch (type) {
+               case DBUS_TYPE_STRING:
+               case DBUS_TYPE_ARRAY:
+               case DBUS_TYPE_BOOLEAN:
+                       break;
+               default:
+                       /* Ignore and report back all invalid property types */
                        invalid = append_to_gstring(invalid, key);
                        continue;
                }
@@@ -702,8 -716,7 +716,7 @@@ static DBusMessage *clear_property(DBus
  
                del_routes(provider);
  
-               if (!handle_routes)
-                       send_routes(provider, provider->user_routes, name);
+               send_routes(provider, provider->user_routes, name);
        } else if (vpn_provider_get_string(provider, name)) {
                err = vpn_provider_set_string(provider, name, NULL);
                switch (err) {
@@@ -841,6 -854,8 +854,8 @@@ static void provider_resolv_host_addr(s
  void __vpn_provider_append_properties(struct vpn_provider *provider,
                                                        DBusMessageIter *iter)
  {
+       dbus_bool_t split_routing;
        if (provider->host)
                connman_dbus_dict_append_basic(iter, "Host",
                                        DBUS_TYPE_STRING, &provider->host);
        if (provider->type)
                connman_dbus_dict_append_basic(iter, "Type", DBUS_TYPE_STRING,
                                                 &provider->type);
+       split_routing = provider->do_split_routing;
+       connman_dbus_dict_append_basic(iter, "SplitRouting", DBUS_TYPE_BOOLEAN,
+                                                       &split_routing);
  }
  
  int __vpn_provider_append_user_route(struct vpn_provider *provider,
@@@ -984,7 -1003,7 +1003,7 @@@ static GSList *get_routes(gchar **netwo
  static int provider_load_from_keyfile(struct vpn_provider *provider,
                GKeyFile *keyfile)
  {
-       gsize idx = 0;
+       gsize idx;
        gchar **settings;
        gchar *key, *value;
        gsize length, num_user_networks;
                return -ENOENT;
        }
  
-       while (idx < length) {
+       for (idx = 0; idx < length; idx++) {
                key = settings[idx];
-               if (key) {
-                       if (g_str_equal(key, "Networks")) {
-                               networks = __vpn_config_get_string_list(keyfile,
-                                               provider->identifier,
-                                               key,
-                                               &num_user_networks,
+               if (!key)
+                       continue;
+               if (g_str_equal(key, "Networks")) {
+                       networks = __vpn_config_get_string_list(keyfile,
+                                               provider->identifier,key,
+                                               &num_user_networks, NULL);
+                       provider->user_networks = get_routes(networks);
+               } else {
+                       value = __vpn_config_get_string(keyfile,
+                                               provider->identifier, key,
                                                NULL);
-                               provider->user_networks = get_routes(networks);
-                       } else {
-                               value = __vpn_config_get_string(keyfile,
-                                                       provider->identifier,
-                                                       key, NULL);
-                               vpn_provider_set_string(provider, key,
-                                                       value);
-                               g_free(value);
-                       }
+                       vpn_provider_set_string(provider, key, value);
+                       g_free(value);
                }
-               idx += 1;
        }
        g_strfreev(settings);
        g_strfreev(networks);
  
@@@ -1135,6 -1152,7 +1152,7 @@@ static int vpn_provider_save(struct vpn
                        "Host", provider->host);
        g_key_file_set_string(keyfile, provider->identifier,
                        "VPN.Domain", provider->domain);
        if (provider->user_networks) {
                gchar **networks;
                gsize network_count;
@@@ -1725,6 -1743,7 +1743,7 @@@ static void append_properties(DBusMessa
        GHashTableIter hash;
        gpointer value, key;
        dbus_bool_t immutable;
+       dbus_bool_t split_routing;
  
        connman_dbus_dict_open(iter, &dict);
  
        connman_dbus_dict_append_basic(&dict, "Immutable", DBUS_TYPE_BOOLEAN,
                                        &immutable);
  
+       split_routing = provider->do_split_routing;
+       connman_dbus_dict_append_basic(&dict, "SplitRouting",
+                                       DBUS_TYPE_BOOLEAN, &split_routing);
        if (provider->family == AF_INET)
                connman_dbus_dict_append_dict(&dict, "IPv4", append_ipv4,
                                                provider);
                while (g_hash_table_iter_next(&hash, &key, &value)) {
                        struct vpn_setting *setting = value;
  
-                       if (!setting->hide_value &&
-                                                       setting->value)
+                       if (!setting->hide_value && setting->value)
                                connman_dbus_dict_append_basic(&dict, key,
                                                        DBUS_TYPE_STRING,
                                                        &setting->value);
@@@ -1806,55 -1828,6 +1828,6 @@@ static void connection_added_signal(str
        dbus_message_unref(signal);
  }
  
- static bool check_host(char **hosts, char *host)
- {
-       int i;
-       if (!hosts)
-               return false;
-       for (i = 0; hosts[i]; i++) {
-               if (g_strcmp0(hosts[i], host) == 0)
-                       return true;
-       }
-       return false;
- }
- static void provider_append_routes(gpointer key, gpointer value,
-                                       gpointer user_data)
- {
-       struct vpn_route *route = value;
-       struct vpn_provider *provider = user_data;
-       int index = provider->index;
-       if (!handle_routes)
-               return;
-       /*
-        * If the VPN administrator/user has given a route to
-        * VPN server, then we must discard that because the
-        * server cannot be contacted via VPN tunnel.
-        */
-       if (check_host(provider->host_ip, route->network)) {
-               DBG("Discarding VPN route to %s via %s at index %d",
-                       route->network, route->gateway, index);
-               return;
-       }
-       if (route->family == AF_INET6) {
-               unsigned char prefix_len = atoi(route->netmask);
-               connman_inet_add_ipv6_network_route(index, route->network,
-                                                       route->gateway,
-                                                       prefix_len);
-       } else {
-               connman_inet_add_network_route(index, route->network,
-                                               route->gateway,
-                                               route->netmask);
-       }
- }
  static int set_connected(struct vpn_provider *provider,
                                        bool connected)
  {
  
                __vpn_ipconfig_address_add(ipconfig, provider->family);
  
-               if (handle_routes)
-                       __vpn_ipconfig_gateway_add(ipconfig, provider->family);
                provider_indicate_state(provider,
                                        VPN_PROVIDER_STATE_READY);
-               g_hash_table_foreach(provider->routes, provider_append_routes,
-                                       provider);
-               g_hash_table_foreach(provider->user_routes,
-                                       provider_append_routes, provider);
        } else {
                provider_indicate_state(provider,
                                        VPN_PROVIDER_STATE_DISCONNECT);
@@@ -1949,10 -1912,61 +1912,61 @@@ int vpn_provider_indicate_error(struct 
        return 0;
  }
  
+ static gboolean provider_property_changed(DBusConnection *conn,
+                                       DBusMessage *message, void *user_data)
+ {
+       DBusMessageIter iter;
+       DBusMessageIter value;
+       struct vpn_provider *provider = user_data;
+       const char *key;
+       if (!dbus_message_iter_init(message, &iter))
+               return TRUE;
+       dbus_message_iter_get_basic(&iter, &key);
+       dbus_message_iter_next(&iter);
+       dbus_message_iter_recurse(&iter, &value);
+       DBG("provider %p key %s", provider, key);
+       if (g_str_equal(key, "SplitRouting")) {
+               dbus_bool_t split_routing;
+               if (dbus_message_iter_get_arg_type(&value) !=
+                                                       DBUS_TYPE_BOOLEAN)
+                       goto out;
+               dbus_message_iter_get_basic(&value, &split_routing);
+               DBG("property %s value %s", key, bool2str(split_routing));
+               /*
+                * Even though this is coming from connmand, signal the value
+                * for other components listening to the changes via VPN API
+                * only. provider.c will skip setting the same value in order
+                * to avoid signaling loop. This is needed for ensuring that
+                * all components using VPN API will be informed about the
+                * correct status of SplitRouting. Especially when loading the
+                * services after a crash, for instance.
+                */
+               vpn_provider_set_boolean(provider, "SplitRouting",
+                                       split_routing, true);
+       }
+ out:
+       return TRUE;
+ }
  static int connection_unregister(struct vpn_provider *provider)
  {
        DBG("provider %p path %s", provider, provider->path);
  
+       if (provider->signal_watch) {
+               g_dbus_remove_watch(connection, provider->signal_watch);
+               provider->signal_watch = 0;
+       }
        if (!provider->path)
                return -EALREADY;
  
  
  static int connection_register(struct vpn_provider *provider)
  {
+       char *connmand_vpn_path;
        DBG("provider %p path %s", provider, provider->path);
  
        if (provider->path)
                                connection_methods, connection_signals,
                                NULL, provider, NULL);
  
+       connmand_vpn_path = g_strdup_printf("%s/service/vpn_%s", CONNMAN_PATH,
+                                               provider->identifier);
+       provider->signal_watch = g_dbus_add_signal_watch(connection,
+                                       CONNMAN_SERVICE, connmand_vpn_path,
+                                       CONNMAN_SERVICE_INTERFACE,
+                                       PROPERTY_CHANGED,
+                                       provider_property_changed,
+                                       provider, NULL);
+       g_free(connmand_vpn_path);
        return 0;
  }
  
@@@ -2017,6 -2045,7 +2045,7 @@@ static void provider_initialize(struct 
        provider->domain = NULL;
        provider->identifier = NULL;
        provider->immutable = false;
+       provider->do_split_routing = false;
        provider->user_networks = NULL;
        provider->routes = g_hash_table_new_full(g_direct_hash, g_direct_equal,
                                        NULL, free_route);
@@@ -2112,9 -2141,12 +2141,12 @@@ static struct vpn_provider *provider_cr
                        return NULL;
                }
  
-               if (provider_register(provider) == 0)
+               if (!provider_register(provider)) {
                        connection_register(provider);
+                       connection_added_signal(provider);
+               }
        }
        return provider;
  }
  
@@@ -2162,7 -2194,6 +2194,7 @@@ static void provider_create_all_from_ty
        g_strfreev(providers);
  }
  
 +#if !defined TIZEN_EXT
  char *__vpn_provider_create_identifier(const char *host, const char *domain)
  {
        char *ident;
  
        return ident;
  }
 +#else
 +char *__vpn_provider_create_identifier(const char *host, const char *domain, const char *name)
 +{
 +      char *ident;
 +
 +      if (domain)
 +              ident = g_strdup_printf("%s_%s_%s", host, domain, name);
 +      else
 +              ident = g_strdup_printf("%s_%s", host, name);
 +      if (!ident)
 +              return NULL;
 +
 +      provider_dbus_ident(ident);
 +
 +      return ident;
 +}
 +#endif
  
  int __vpn_provider_create(DBusMessage *msg)
  {
        GSList *networks = NULL;
        char *ident;
        int err;
+       dbus_bool_t split_routing = false;
  
        dbus_message_iter_init(msg, &iter);
        dbus_message_iter_recurse(&iter, &array);
                                        g_str_equal(key, "Domain"))
                                dbus_message_iter_get_basic(&value, &domain);
                        break;
+               case DBUS_TYPE_BOOLEAN:
+                       if (g_str_equal(key, "SplitRouting"))
+                               dbus_message_iter_get_basic(&value,
+                                                       &split_routing);
+                       break;
                case DBUS_TYPE_ARRAY:
                        if (g_str_equal(key, "UserRoutes"))
                                networks = get_user_networks(&value);
        if (!type || !name)
                return -EOPNOTSUPP;
  
 +#if !defined TIZEN_EXT
        ident = __vpn_provider_create_identifier(host, domain);
 +#else
 +      ident = __vpn_provider_create_identifier(host, domain, name);
 +#endif
        DBG("ident %s", ident);
  
        provider = __vpn_provider_lookup(ident);
                provider->domain = g_strdup(domain);
                provider->name = g_strdup(name);
                provider->type = g_strdup(type);
+               provider->do_split_routing = split_routing;
  
                if (provider_register(provider) == 0)
                        vpn_provider_load(provider);
@@@ -2439,11 -2456,7 +2478,11 @@@ int __vpn_provider_create_from_config(G
                goto fail;
        }
  
 +#if !defined TIZEN_EXT
        ident = __vpn_provider_create_identifier(host, domain);
 +#else
 +      ident = __vpn_provider_create_identifier(host, domain, name);
 +#endif
        DBG("ident %s", ident);
  
        provider = __vpn_provider_lookup(ident);
@@@ -2515,11 -2528,7 +2554,11 @@@ static void append_connection_structs(D
        while (g_hash_table_iter_next(&hash, &key, &value)) {
                struct vpn_provider *provider = value;
  
 +#if defined TIZEN_EXT
 +              DBG("provider %p", provider);
 +#else
                DBG("path %s", provider->path);
 +#endif
  
                if (!provider->identifier)
                        continue;
@@@ -2594,6 -2603,10 +2633,10 @@@ static int set_string(struct vpn_provid
                g_free(provider->domain);
                provider->domain = g_strdup(value);
                send_value(provider->path, "Domain", provider->domain);
+       } else if (g_str_equal(key, "SplitRouting")) {
+               connman_warn("VPN SplitRouting value attempted to set as "
+                                       "string, is boolean");
+               return -EINVAL;
        } else {
                struct vpn_setting *setting;
                bool replace = true;
@@@ -2680,6 -2693,25 +2723,25 @@@ const char *vpn_provider_get_string(str
        return setting->value;
  }
  
+ int vpn_provider_set_boolean(struct vpn_provider *provider, const char *key,
+                                               bool value, bool force_change)
+ {
+       DBG("provider %p key %s", provider, key);
+       if (g_str_equal(key, "SplitRouting")) {
+               if (provider->do_split_routing == value && !force_change)
+                       return -EALREADY;
+               DBG("SplitRouting set to %s", bool2str(value));
+               provider->do_split_routing = value;
+               send_value_boolean(provider->path, key,
+                                       provider->do_split_routing);
+       }
+       return 0;
+ }
  bool vpn_provider_get_boolean(struct vpn_provider *provider, const char *key,
                                                        bool default_value)
  {
@@@ -2754,10 -2786,6 +2816,10 @@@ void vpn_provider_set_data(struct vpn_p
  
  void *vpn_provider_get_plugin_data(struct vpn_provider *provider)
  {
 +#if defined TIZEN_EXT
 +      if (!provider)
 +              return NULL;
 +#endif
        return provider->plugin_data;
  }
  
@@@ -2952,11 -2980,8 +3014,8 @@@ int vpn_provider_append_route(struct vp
                break;
        }
  
-       if (!handle_routes) {
-               if (route->netmask && route->gateway &&
-                                                       route->network)
-                       provider_schedule_changed(provider);
-       }
+       if (route->netmask && route->gateway && route->network)
+               provider_schedule_changed(provider);
  
        return 0;
  }
@@@ -3015,6 -3040,12 +3074,12 @@@ void vpn_provider_driver_unregister(str
                if (provider && provider->driver &&
                                g_strcmp0(provider->driver->name,
                                                        driver->name) == 0) {
+                       /*
+                        * Cancel VPN agent request to avoid segfault at
+                        * shutdown as the callback, if set can point to a
+                        * function in the plugin that is to be removed.
+                        */
+                       connman_agent_cancel(provider);
                        provider->driver = NULL;
                }
        }
@@@ -3093,7 -3124,7 +3158,7 @@@ void vpn_provider_clear_address(struct 
                        DBG("ipv6 %s/%d", address, len);
  
                        connman_inet_clear_ipv6_address(provider->index,
-                                                       address, len);
+                                               provider->prev_ipv6_addr);
  
                        connman_ipaddress_free(provider->prev_ipv6_addr);
                        provider->prev_ipv6_addr = NULL;
@@@ -3183,14 -3214,12 +3248,12 @@@ static void remove_unprovisioned_provid
        g_strfreev(providers);
  }
  
- int __vpn_provider_init(bool do_routes)
+ int __vpn_provider_init(void)
  {
        int err;
  
        DBG("");
  
-       handle_routes = do_routes;
        err = connman_agent_driver_register(&agent_driver);
        if (err < 0) {
                connman_error("Cannot register agent driver for %s",
diff --combined vpn/vpn-provider.h
index 0275d51,f7fa859..f7fa859
mode 100755,100644..100755
@@@ -83,6 -83,9 +83,9 @@@ const char *vpn_provider_get_string(str
                                                        const char *key);
  bool vpn_provider_get_string_immutable(struct vpn_provider *provider,
                                                        const char *key);
+ int vpn_provider_set_boolean(struct vpn_provider *provider, const char *key,
+                                                       bool value,
+                                                       bool force_change);
  bool vpn_provider_get_boolean(struct vpn_provider *provider, const char *key,
                                                        bool default_value);
  
@@@ -118,6 -121,7 +121,7 @@@ const char *vpn_provider_get_save_group
  const char *vpn_provider_get_name(struct vpn_provider *provider);
  const char *vpn_provider_get_host(struct vpn_provider *provider);
  const char *vpn_provider_get_path(struct vpn_provider *provider);
+ const char *vpn_provider_get_ident(struct vpn_provider *provider);
  
  unsigned int vpn_provider_get_authentication_errors(
                                        struct vpn_provider *provider);
diff --combined vpn/vpn.h
index e68b8ad,477cb22..94cee25
mode 100755,100644..100755
+++ b/vpn/vpn.h
@@@ -71,11 -71,8 +71,11 @@@ int __vpn_ipconfig_init(void)
  void __vpn_ipconfig_cleanup(void);
  
  #include "vpn-provider.h"
 -
 +#if !defined TIZEN_EXT
  char *__vpn_provider_create_identifier(const char *host, const char *domain);
 +#else
 +char *__vpn_provider_create_identifier(const char *host, const char *domain, const char *name);
 +#endif
  bool __vpn_provider_check_routes(struct vpn_provider *provider);
  int __vpn_provider_append_user_route(struct vpn_provider *provider,
                                int family, const char *network,
@@@ -88,7 -85,6 +88,6 @@@ int __vpn_provider_create_from_config(G
  int __vpn_provider_set_string_immutable(struct vpn_provider *provider,
                                        const char *key, const char *value);
  DBusMessage *__vpn_provider_get_connections(DBusMessage *msg);
- const char *vpn_provider_get_ident(struct vpn_provider *provider);
  struct vpn_provider *__vpn_provider_lookup(const char *identifier);
  int __vpn_provider_indicate_state(struct vpn_provider *provider,
                                        enum vpn_provider_state state);
@@@ -100,7 -96,7 +99,7 @@@ int __vpn_provider_disconnect(struct vp
  int __vpn_provider_remove(const char *path);
  int __vpn_provider_delete(struct vpn_provider *provider);
  void __vpn_provider_cleanup(void);
- int __vpn_provider_init(bool handle_routes);
+ int __vpn_provider_init();
  
  #include "vpn-rtnl.h"
  
@@@ -115,10 -111,12 +114,12 @@@ int __vpn_rtnl_send(const void *buf, si
  
  int __vpn_config_init(void);
  void __vpn_config_cleanup(void);
- char *__vpn_config_get_string(GKeyFile *key_file,
-         const char *group_name, const char *key, GError **error);
- char **__vpn_config_get_string_list(GKeyFile *key_file,
-         const char *group_name, const char *key, gsize *length, GError **error);
+ char *__vpn_config_get_string(GKeyFile *key_file, const char *group_name,
+                                       const char *key, GError **error);
+ char **__vpn_config_get_string_list(GKeyFile *key_file, const char *group_name,
+                       const char *key, gsize *length, GError **error);
+ bool __vpn_config_get_boolean(GKeyFile *key_file, const char *group_name,
+                       const char *key, bool default_value);
  
  int __vpn_settings_init(const char *file);
  void __vpn_settings_cleanup(void);
@@@ -135,3 -133,8 +136,8 @@@ const char * vpn_settings_get_binary_us
  const char * vpn_settings_get_binary_group(struct vpn_plugin_data *data);
  char ** vpn_settings_get_binary_supplementary_groups(
        struct vpn_plugin_data *data);
+ bool vpn_settings_is_system_user(const char *user);
+ struct passwd *vpn_util_get_passwd(const char *username);
+ struct group *vpn_util_get_group(const char *groupname);
+ int vpn_util_create_path(const char *path, uid_t uid, gid_t grp, int mode);